-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.go
More file actions
142 lines (126 loc) · 3.54 KB
/
code.go
File metadata and controls
142 lines (126 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package play
// CodeResult reports whether runtime engine code still matches the manifest pin.
type CodeResult struct {
Engine string
Path string
ExpectedSHA256 string
ActualSHA256 string
Recorded bool
Match bool
OK bool
Issues ValidationErrors
}
// EngineCodeIdentity describes the currently selected runtime engine code.
type EngineCodeIdentity struct {
Name string
Path string
SHA256 string
}
// EngineCodeProvider is implemented by engines that expose an integrity identity.
type EngineCodeProvider interface {
CodeIdentity() EngineCodeIdentity
}
func verifyCode(bundle Bundle, registry *Registry) CodeResult {
result := CodeResult{
Engine: bundle.Manifest.Runtime.Engine,
Path: bundle.Manifest.Verification.Engine.Path,
}
if registry == nil {
result.Issues = append(result.Issues, ValidationIssue{
Code: "engine/registry-missing",
Field: "runtime.engine",
Message: "engine registry is required",
})
result.OK = false
return result
}
engine, found := registry.Resolve(bundle.Manifest.Runtime.Engine)
if !found {
result.Issues = append(result.Issues, ValidationIssue{
Code: "engine/unavailable",
Field: "runtime.engine",
Message: "runtime engine is not registered",
})
result.OK = false
return result
}
if err := engine.Verify(); err != nil {
result.Issues = append(result.Issues, ValidationIssue{
Code: "engine/verify-failed",
Field: "runtime.engine",
Message: err.Error(),
})
result.OK = false
return result
}
pin := bundle.Manifest.Verification.Engine
result.ExpectedSHA256 = pin.SHA256
result.Recorded = pin.SHA256 != ""
if !result.Recorded {
result.OK = true
return result
}
actual := hashPinnedEngine(bundle, engine, pin)
result.ActualSHA256 = actual.SHA256
if result.Path == "" {
result.Path = actual.Path
}
if actual.SHA256 == "" {
result.Issues = append(result.Issues, ValidationIssue{
Code: "code/hash-unavailable",
Field: "verification.engine.sha256",
Message: "engine hash could not be recalculated",
})
result.OK = false
return result
}
if actual.SHA256 != pin.SHA256 {
result.Issues = append(result.Issues, ValidationIssue{
Code: "code/hash-mismatch",
Field: "verification.engine.sha256",
Message: "engine hash does not match the manifest",
})
result.OK = false
return result
}
result.Match = true
result.OK = true
return result
}
func hashPinnedEngine(bundle Bundle, engine Engine, pin CodePin) EngineCodeIdentity {
if pin.Path != "" && validBundlePath(pin.Path) {
if data, ok := bundleFileData(bundle, pin.Path); ok {
return EngineCodeIdentity{
Name: defaultString(pin.Name, engine.Name()),
Path: pin.Path,
SHA256: sha256Hex(data),
}
}
}
if provider, ok := engine.(EngineCodeProvider); ok {
return provider.CodeIdentity()
}
return EngineCodeIdentity{}
}
func plannedCodePin(request BundleRequest, engineName string) CodePin {
if request.EngineBinarySHA256 != "" || len(request.EngineBinaryData) > 0 {
enginePath := defaultString(request.EngineBinaryPath, engineName)
engineHash := request.EngineBinarySHA256
if len(request.EngineBinaryData) > 0 {
engineHash = sha256Hex(request.EngineBinaryData)
}
return CodePin{
Name: engineName,
Path: enginePath,
SHA256: engineHash,
}
}
return CodePin{
Name: engineName,
Path: engineName,
SHA256: virtualEngineCodeSHA256(engineName),
}
}
func virtualEngineCodeSHA256(engineName string) string {
return sha256Hex([]byte("core-play-engine:" + engineName))
}