-
Notifications
You must be signed in to change notification settings - Fork 0
/
variant.go
362 lines (297 loc) · 9.68 KB
/
variant.go
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
Package variant defines Attestation variants for different CSPs.
Each variant defines an OID, a string representation, and a function to compare it to other OIDs.
The OID is used in attested TLS to distinguish the attestation documents.
OIDs beginning with 1.3.9900 are reserved and can be used without registration.
* The 1.3.9900.1 branch is reserved for placeholder values and testing.
* The 1.3.9900.2 branch is reserved for AWS.
* The 1.3.9900.3 branch is reserved for GCP.
* The 1.3.9900.4 branch is reserved for Azure.
* The 1.3.9900.5 branch is reserved for QEMU.
Deprecated OIDs should never be reused for different purposes.
Instead, new OIDs should be added in the appropriate branch at the next available index.
String representation should be lowercase and contain only letters, numbers, and hyphens.
They should be prefixed with the branch name, e.g. all variants in the 1.3.9900.2 (AWS) branch should start with "aws-".
Each variant should have a unique string representation.
*/
package variant
import (
"encoding/asn1"
"fmt"
"sort"
"github.com/flashbots/cvm-reverse-proxy/internal/cloud/cloudprovider"
)
const (
dummy = "dummy"
awsNitroTPM = "aws-nitro-tpm"
awsSEVSNP = "aws-sev-snp"
gcpSEVES = "gcp-sev-es"
gcpSEVSNP = "gcp-sev-snp"
azureTDX = "azure-tdx"
azureSEVSNP = "azure-sev-snp"
azureTrustedLaunch = "azure-trustedlaunch"
qemuVTPM = "qemu-vtpm"
qemuTDX = "qemu-tdx"
)
var providerAttestationMapping = map[cloudprovider.Provider][]Variant{
cloudprovider.AWS: {AWSSEVSNP{}, AWSNitroTPM{}},
cloudprovider.Azure: {AzureSEVSNP{}, AzureTDX{}, AzureTrustedLaunch{}},
cloudprovider.GCP: {GCPSEVSNP{}, GCPSEVES{}},
cloudprovider.QEMU: {QEMUVTPM{}},
cloudprovider.OpenStack: {QEMUVTPM{}},
}
// GetDefaultAttestation returns the default attestation variant for the given provider. If not found, it returns the default variant.
func GetDefaultAttestation(provider cloudprovider.Provider) Variant {
res, ok := providerAttestationMapping[provider]
if ok {
return res[0]
}
return Dummy{}
}
// GetAvailableAttestationVariants returns the available attestation variants.
func GetAvailableAttestationVariants() []Variant {
var res []Variant
// assumes that cloudprovider.Provider is a uint32 to sort the providers and get a consistent order
var keys []cloudprovider.Provider
for k := range providerAttestationMapping {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
return uint(keys[i]) < uint(keys[j])
})
for _, k := range keys {
res = append(res, providerAttestationMapping[k]...)
}
return RemoveDuplicate(res)
}
// Getter returns an ASN.1 Object Identifier.
type Getter interface {
OID() asn1.ObjectIdentifier
}
// Variant describes an attestation variant.
type Variant interface {
Getter
String() string
Equal(other Getter) bool
}
func FromOID(oid asn1.ObjectIdentifier) (Variant, error) {
switch oid.String() {
case Dummy{}.OID().String():
return Dummy{}, nil
case AWSSEVSNP{}.OID().String():
return AWSSEVSNP{}, nil
case AWSNitroTPM{}.OID().String():
return AWSNitroTPM{}, nil
case GCPSEVES{}.OID().String():
return GCPSEVES{}, nil
case GCPSEVSNP{}.OID().String():
return GCPSEVSNP{}, nil
case AzureSEVSNP{}.OID().String():
return AzureSEVSNP{}, nil
case AzureTrustedLaunch{}.OID().String():
return AzureTrustedLaunch{}, nil
case AzureTDX{}.OID().String():
return AzureTDX{}, nil
case QEMUVTPM{}.OID().String():
return QEMUVTPM{}, nil
case QEMUTDX{}.OID().String():
return QEMUTDX{}, nil
}
return nil, fmt.Errorf("unknown OID: %q", oid)
}
// FromString returns the OID for the given string.
func FromString(oid string) (Variant, error) {
switch oid {
case dummy:
return Dummy{}, nil
case awsSEVSNP:
return AWSSEVSNP{}, nil
case awsNitroTPM:
return AWSNitroTPM{}, nil
case gcpSEVES:
return GCPSEVES{}, nil
case gcpSEVSNP:
return GCPSEVSNP{}, nil
case azureSEVSNP:
return AzureSEVSNP{}, nil
case azureTrustedLaunch:
return AzureTrustedLaunch{}, nil
case azureTDX:
return AzureTDX{}, nil
case qemuVTPM:
return QEMUVTPM{}, nil
case qemuTDX:
return QEMUTDX{}, nil
}
return nil, fmt.Errorf("unknown OID: %q", oid)
}
// ValidProvider returns true if the attestation variants is valid for the given provider.
func ValidProvider(provider cloudprovider.Provider, variant Variant) bool {
validTypes, ok := providerAttestationMapping[provider]
if ok {
for _, aType := range validTypes {
if variant.Equal(aType) {
return true
}
}
}
return false
}
// Dummy OID for testing.
type Dummy struct{}
// OID returns the struct's object identifier.
func (Dummy) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 1, 1}
}
// String returns the string representation of the OID.
func (Dummy) String() string {
return dummy
}
// Equal returns true if the other variant is also a Default.
func (Dummy) Equal(other Getter) bool {
return other.OID().Equal(Dummy{}.OID())
}
// AWSNitroTPM holds the AWS nitro TPM OID.
type AWSNitroTPM struct{}
// OID returns the struct's object identifier.
func (AWSNitroTPM) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 2, 1}
}
// String returns the string representation of the OID.
func (AWSNitroTPM) String() string {
return awsNitroTPM
}
// Equal returns true if the other variant is also AWSNitroTPM.
func (AWSNitroTPM) Equal(other Getter) bool {
return other.OID().Equal(AWSNitroTPM{}.OID())
}
// AWSSEVSNP holds the AWS nitro TPM OID.
type AWSSEVSNP struct{}
// OID returns the struct's object identifier.
func (AWSSEVSNP) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 2, 2}
}
// String returns the string representation of the OID.
func (AWSSEVSNP) String() string {
return awsSEVSNP
}
// Equal returns true if the other variant is also AWSSEVSNP.
func (AWSSEVSNP) Equal(other Getter) bool {
return other.OID().Equal(AWSSEVSNP{}.OID())
}
// GCPSEVES holds the GCP SEV-ES OID.
type GCPSEVES struct{}
// OID returns the struct's object identifier.
func (GCPSEVES) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 3, 1}
}
// String returns the string representation of the OID.
func (GCPSEVES) String() string {
return gcpSEVES
}
// Equal returns true if the other variant is also GCPSEVES.
func (GCPSEVES) Equal(other Getter) bool {
return other.OID().Equal(GCPSEVES{}.OID())
}
// GCPSEVSNP holds the GCP SEV-SNP OID.
type GCPSEVSNP struct{}
// OID returns the struct's object identifier.
func (GCPSEVSNP) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 3, 2}
}
// String returns the string representation of the OID.
func (GCPSEVSNP) String() string {
return gcpSEVSNP
}
// Equal returns true if the other variant is also GCPSEVSNP.
func (GCPSEVSNP) Equal(other Getter) bool {
return other.OID().Equal(GCPSEVSNP{}.OID())
}
// AzureTDX holds the OID for Azure TDX CVMs.
type AzureTDX struct{}
// OID returns the struct's object identifier.
func (AzureTDX) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 4, 3}
}
// String returns the string representation of the OID.
func (AzureTDX) String() string {
return azureTDX
}
// Equal returns true if the other variant is also AzureTDX.
func (AzureTDX) Equal(other Getter) bool {
return other.OID().Equal(AzureTDX{}.OID())
}
// AzureSEVSNP holds the OID for Azure SNP CVMs.
type AzureSEVSNP struct{}
// OID returns the struct's object identifier.
func (AzureSEVSNP) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 4, 1}
}
// String returns the string representation of the OID.
func (AzureSEVSNP) String() string {
return azureSEVSNP
}
// Equal returns true if the other variant is also AzureSEVSNP.
func (AzureSEVSNP) Equal(other Getter) bool {
return other.OID().Equal(AzureSEVSNP{}.OID())
}
// AzureTrustedLaunch holds the OID for Azure TrustedLaunch VMs.
type AzureTrustedLaunch struct{}
// OID returns the struct's object identifier.
func (AzureTrustedLaunch) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 4, 2}
}
// String returns the string representation of the OID.
func (AzureTrustedLaunch) String() string {
return azureTrustedLaunch
}
// Equal returns true if the other variant is also AzureTrustedLaunch.
func (AzureTrustedLaunch) Equal(other Getter) bool {
return other.OID().Equal(AzureTrustedLaunch{}.OID())
}
// QEMUVTPM holds the QEMUVTPM OID.
type QEMUVTPM struct{}
// OID returns the struct's object identifier.
func (QEMUVTPM) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 5, 1}
}
// String returns the string representation of the OID.
func (QEMUVTPM) String() string {
return qemuVTPM
}
// Equal returns true if the other variant is also QEMUVTPM.
func (QEMUVTPM) Equal(other Getter) bool {
return other.OID().Equal(QEMUVTPM{}.OID())
}
// QEMUTDX holds the QEMU TDX OID.
// Placeholder for dev-cloud integration.
type QEMUTDX struct{}
// OID returns the struct's object identifier.
// Placeholder for dev-cloud integration.
func (QEMUTDX) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 5, 99}
}
// String returns the string representation of the OID.
func (QEMUTDX) String() string {
return qemuTDX
}
// Equal returns true if the other variant is also QEMUTDX.
func (QEMUTDX) Equal(other Getter) bool {
return other.OID().Equal(QEMUTDX{}.OID())
}
// RemoveDuplicate removes duplicate elements from a slice.
func RemoveDuplicate[T comparable](sliceList []T) []T {
allKeys := make(map[T]bool)
list := []T{}
for _, item := range sliceList {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}