mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-23 05:41:19 -05:00
Implement support for "latest" placeholders for Azure TDX
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
a34493caa6
commit
9159b60331
@ -6,7 +6,7 @@ go_library(
|
||||
srcs = [
|
||||
"attestationconfigapi.go",
|
||||
"fetcher.go",
|
||||
"snp.go",
|
||||
"version.go",
|
||||
],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi",
|
||||
visibility = ["//:__subpackages__"],
|
||||
@ -22,7 +22,7 @@ go_test(
|
||||
name = "attestationconfigapi_test",
|
||||
srcs = [
|
||||
"fetcher_test.go",
|
||||
"snp_test.go",
|
||||
"version_test.go",
|
||||
],
|
||||
embed = [":attestationconfigapi"],
|
||||
deps = [
|
||||
|
@ -20,6 +20,7 @@ go_library(
|
||||
deps = [
|
||||
"//internal/api/attestationconfigapi",
|
||||
"//internal/api/attestationconfigapi/cli/client",
|
||||
"//internal/api/fetcher",
|
||||
"//internal/attestation/variant",
|
||||
"//internal/cloud/cloudprovider",
|
||||
"//internal/constants",
|
||||
|
@ -22,27 +22,27 @@ const AttestationURLPath = "constellation/v1/attestation"
|
||||
// SEVSNPVersion tracks the latest version of each component for SEV-SNP.
|
||||
type SEVSNPVersion struct {
|
||||
// Bootloader is the latest version of the SEV-SNP bootloader.
|
||||
Bootloader uint8 `json:"bootloader,omitempty"`
|
||||
Bootloader uint8 `json:"bootloader"`
|
||||
// TEE is the latest version of the SEV-SNP TEE.
|
||||
TEE uint8 `json:"tee,omitempty"`
|
||||
TEE uint8 `json:"tee"`
|
||||
// SNP is the latest version of the SEV-SNP SNP.
|
||||
SNP uint8 `json:"snp,omitempty"`
|
||||
SNP uint8 `json:"snp"`
|
||||
// Microcode is the latest version of the SEV-SNP microcode.
|
||||
Microcode uint8 `json:"microcode,omitempty"`
|
||||
Microcode uint8 `json:"microcode"`
|
||||
}
|
||||
|
||||
// TDXVersion tracks the latest version of each component for TDX.
|
||||
type TDXVersion struct {
|
||||
// QESVN is the latest QE security version number.
|
||||
QESVN uint16 `json:"qeSVN,omitempty"`
|
||||
QESVN uint16 `json:"qeSVN"`
|
||||
// PCESVN is the latest PCE security version number.
|
||||
PCESVN uint16 `json:"pceSVN,omitempty"`
|
||||
PCESVN uint16 `json:"pceSVN"`
|
||||
// TEETCBSVN are the latest component-wise security version numbers for the TEE.
|
||||
TEETCBSVN [16]byte `json:"teeTCBSVN,omitempty"`
|
||||
TEETCBSVN [16]byte `json:"teeTCBSVN"`
|
||||
// QEVendorID is the latest QE vendor ID.
|
||||
QEVendorID [16]byte `json:"qeVendorID,omitempty"`
|
||||
QEVendorID [16]byte `json:"qeVendorID"`
|
||||
// XFAM is the latest XFAM field.
|
||||
XFAM [8]byte `json:"xfam,omitempty"`
|
||||
XFAM [8]byte `json:"xfam"`
|
||||
}
|
||||
|
||||
// VersionAPIEntry is the request to get the version information of the specific version in the config api.
|
||||
|
@ -103,14 +103,14 @@ func (v *Validator) validateQuote(tdxQuote *tdx.QuoteV4) error {
|
||||
|
||||
if err := validate.TdxQuote(tdxQuote, &validate.Options{
|
||||
HeaderOptions: validate.HeaderOptions{
|
||||
MinimumQeSvn: v.cfg.QESVN,
|
||||
MinimumPceSvn: v.cfg.PCESVN,
|
||||
QeVendorID: v.cfg.QEVendorID,
|
||||
MinimumQeSvn: v.cfg.QESVN.Value,
|
||||
MinimumPceSvn: v.cfg.PCESVN.Value,
|
||||
QeVendorID: v.cfg.QEVendorID.Value,
|
||||
},
|
||||
TdQuoteBodyOptions: validate.TdQuoteBodyOptions{
|
||||
MinimumTeeTcbSvn: v.cfg.TEETCBSVN,
|
||||
MinimumTeeTcbSvn: v.cfg.TEETCBSVN.Value,
|
||||
MrSeam: v.cfg.MRSeam,
|
||||
Xfam: v.cfg.XFAM,
|
||||
Xfam: v.cfg.XFAM.Value,
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
|
@ -63,6 +63,7 @@ go_test(
|
||||
"//internal/cloud/cloudprovider",
|
||||
"//internal/config/instancetypes",
|
||||
"//internal/constants",
|
||||
"//internal/encoding",
|
||||
"//internal/file",
|
||||
"//internal/semver",
|
||||
"//internal/versions",
|
||||
|
@ -9,47 +9,49 @@ package config
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/encoding"
|
||||
)
|
||||
|
||||
const placeholderVersionValue = 0
|
||||
type versionValue interface {
|
||||
encoding.HexBytes | uint8 | uint16
|
||||
}
|
||||
|
||||
func placeholderVersionValue[T versionValue]() T {
|
||||
var placeholder T
|
||||
return placeholder
|
||||
}
|
||||
|
||||
// NewLatestPlaceholderVersion returns the latest version with a placeholder version value.
|
||||
func NewLatestPlaceholderVersion() AttestationVersion {
|
||||
return AttestationVersion{
|
||||
Value: placeholderVersionValue,
|
||||
func NewLatestPlaceholderVersion[T versionValue]() AttestationVersion[T] {
|
||||
return AttestationVersion[T]{
|
||||
Value: placeholderVersionValue[T](),
|
||||
WantLatest: true,
|
||||
}
|
||||
}
|
||||
|
||||
// AttestationVersion is a type that represents a version of a SNP.
|
||||
type AttestationVersion struct {
|
||||
Value uint8
|
||||
// AttestationVersion holds version information.
|
||||
type AttestationVersion[T versionValue] struct {
|
||||
Value T
|
||||
WantLatest bool
|
||||
}
|
||||
|
||||
// MarshalYAML implements a custom marshaller to resolve "latest" values.
|
||||
func (v AttestationVersion) MarshalYAML() (any, error) {
|
||||
// MarshalYAML implements a custom marshaller to write "latest" as the type's value, if set.
|
||||
func (v AttestationVersion[T]) MarshalYAML() (any, error) {
|
||||
if v.WantLatest {
|
||||
return "latest", nil
|
||||
}
|
||||
return v.Value, nil
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements a custom unmarshaller to resolve "atest" values.
|
||||
func (v *AttestationVersion) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
var rawUnmarshal string
|
||||
if err := unmarshal(&rawUnmarshal); err != nil {
|
||||
return fmt.Errorf("raw unmarshal: %w", err)
|
||||
}
|
||||
|
||||
return v.parseRawUnmarshal(rawUnmarshal)
|
||||
// UnmarshalYAML implements a custom unmarshaller to resolve "latest" values.
|
||||
func (v *AttestationVersion[T]) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
return v.unmarshal(unmarshal)
|
||||
}
|
||||
|
||||
// MarshalJSON implements a custom marshaller to resolve "latest" values.
|
||||
func (v AttestationVersion) MarshalJSON() ([]byte, error) {
|
||||
// MarshalJSON implements a custom marshaller to write "latest" as the type's value, if set.
|
||||
func (v AttestationVersion[T]) MarshalJSON() ([]byte, error) {
|
||||
if v.WantLatest {
|
||||
return json.Marshal("latest")
|
||||
}
|
||||
@ -57,39 +59,31 @@ func (v AttestationVersion) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements a custom unmarshaller to resolve "latest" values.
|
||||
func (v *AttestationVersion) UnmarshalJSON(data []byte) (err error) {
|
||||
// JSON has two distinct ways to represent numbers and strings.
|
||||
// This means we cannot simply unmarshal to string, like with YAML.
|
||||
// Unmarshalling to `any` causes Go to unmarshal numbers to float64.
|
||||
// Therefore, try to unmarshal to string, and then to int, instead of using type assertions.
|
||||
func (v *AttestationVersion[T]) UnmarshalJSON(data []byte) (err error) {
|
||||
return v.unmarshal(func(a any) error {
|
||||
return json.Unmarshal(data, a)
|
||||
})
|
||||
}
|
||||
|
||||
// unmarshal takes care of unmarshalling the value from YAML or JSON.
|
||||
func (v *AttestationVersion[T]) unmarshal(unmarshal func(any) error) error {
|
||||
// Start by trying to unmarshal to the distinct type
|
||||
var distinctType T
|
||||
if err := unmarshal(&distinctType); err == nil {
|
||||
v.Value = distinctType
|
||||
return nil
|
||||
}
|
||||
|
||||
var unmarshalString string
|
||||
if err := json.Unmarshal(data, &unmarshalString); err != nil {
|
||||
var unmarshalInt int64
|
||||
if err := json.Unmarshal(data, &unmarshalInt); err != nil {
|
||||
return fmt.Errorf("unable to unmarshal to string or int: %w", err)
|
||||
}
|
||||
unmarshalString = strconv.FormatInt(unmarshalInt, 10)
|
||||
if err := unmarshal(&unmarshalString); err != nil {
|
||||
return fmt.Errorf("failed unmarshalling to %T or string: %w", distinctType, err)
|
||||
}
|
||||
|
||||
return v.parseRawUnmarshal(unmarshalString)
|
||||
}
|
||||
|
||||
func (v *AttestationVersion) parseRawUnmarshal(str string) error {
|
||||
if strings.HasPrefix(str, "0") && len(str) != 1 {
|
||||
return fmt.Errorf("no format with prefixed 0 (octal, hexadecimal) allowed: %s", str)
|
||||
}
|
||||
if strings.ToLower(str) == "latest" {
|
||||
if strings.ToLower(unmarshalString) == "latest" {
|
||||
v.WantLatest = true
|
||||
v.Value = placeholderVersionValue
|
||||
} else {
|
||||
ui, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid version value: %s", str)
|
||||
}
|
||||
if ui > math.MaxUint8 {
|
||||
return fmt.Errorf("integer value is out ouf uint8 range: %d", ui)
|
||||
}
|
||||
v.Value = uint8(ui)
|
||||
v.Value = placeholderVersionValue[T]()
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
|
||||
return fmt.Errorf("failed unmarshalling to %T or string: invalid value: %s", distinctType, unmarshalString)
|
||||
}
|
||||
|
@ -7,204 +7,307 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/edgelesssys/constellation/v2/internal/encoding"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TestVersionMarshalYAML(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
sut AttestationVersion
|
||||
testCasesUint8 := map[string]struct {
|
||||
sut AttestationVersion[uint8]
|
||||
want string
|
||||
}{
|
||||
"isLatest resolves to latest": {
|
||||
sut: AttestationVersion{
|
||||
"version with latest writes latest": {
|
||||
sut: AttestationVersion[uint8]{
|
||||
Value: 1,
|
||||
WantLatest: true,
|
||||
},
|
||||
want: "latest\n",
|
||||
},
|
||||
"value 5 resolves to 5": {
|
||||
sut: AttestationVersion{
|
||||
"value 5 writes 5": {
|
||||
sut: AttestationVersion[uint8]{
|
||||
Value: 5,
|
||||
WantLatest: false,
|
||||
},
|
||||
want: "5\n",
|
||||
},
|
||||
}
|
||||
for name, tc := range tests {
|
||||
for name, tc := range testCasesUint8 {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
assert := assert.New(t)
|
||||
|
||||
bt, err := yaml.Marshal(tc.sut)
|
||||
require.NoError(err)
|
||||
require.Equal(tc.want, string(bt))
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, string(bt))
|
||||
})
|
||||
}
|
||||
|
||||
testCasesUint16 := map[string]struct {
|
||||
sut AttestationVersion[uint16]
|
||||
want string
|
||||
}{
|
||||
"version with latest writes latest": {
|
||||
sut: AttestationVersion[uint16]{
|
||||
Value: 1,
|
||||
WantLatest: true,
|
||||
},
|
||||
want: "latest\n",
|
||||
},
|
||||
"value 5 writes 5": {
|
||||
sut: AttestationVersion[uint16]{
|
||||
Value: 5,
|
||||
WantLatest: false,
|
||||
},
|
||||
want: "5\n",
|
||||
},
|
||||
}
|
||||
for name, tc := range testCasesUint16 {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
bt, err := yaml.Marshal(tc.sut)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, string(bt))
|
||||
})
|
||||
}
|
||||
|
||||
testCasesHexBytes := map[string]struct {
|
||||
sut AttestationVersion[encoding.HexBytes]
|
||||
want string
|
||||
}{
|
||||
"version with latest writes latest": {
|
||||
sut: AttestationVersion[encoding.HexBytes]{
|
||||
Value: encoding.HexBytes(bytes.Repeat([]byte("0"), 16)),
|
||||
WantLatest: true,
|
||||
},
|
||||
want: "latest\n",
|
||||
},
|
||||
"value 5 writes 5": {
|
||||
sut: AttestationVersion[encoding.HexBytes]{
|
||||
Value: encoding.HexBytes(bytes.Repeat([]byte("A"), 16)),
|
||||
WantLatest: false,
|
||||
},
|
||||
want: "\"41414141414141414141414141414141\"\n",
|
||||
},
|
||||
}
|
||||
for name, tc := range testCasesHexBytes {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
bt, err := yaml.Marshal(tc.sut)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, string(bt))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionUnmarshalYAML(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
sut string
|
||||
want AttestationVersion
|
||||
wantErr bool
|
||||
func TestVersionUnmarshal(t *testing.T) {
|
||||
testCasesUint8 := map[string]struct {
|
||||
yamlData string
|
||||
jsonData string
|
||||
want AttestationVersion[uint8]
|
||||
wantErr bool
|
||||
}{
|
||||
"latest resolves to isLatest": {
|
||||
sut: "latest",
|
||||
want: AttestationVersion{
|
||||
yamlData: "latest",
|
||||
jsonData: "\"latest\"",
|
||||
want: AttestationVersion[uint8]{
|
||||
Value: 0,
|
||||
WantLatest: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"1 resolves to value 1": {
|
||||
sut: "1",
|
||||
want: AttestationVersion{
|
||||
yamlData: "1",
|
||||
jsonData: "1",
|
||||
want: AttestationVersion[uint8]{
|
||||
Value: 1,
|
||||
WantLatest: false,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"max uint8+1 errors": {
|
||||
sut: "256",
|
||||
wantErr: true,
|
||||
yamlData: "256",
|
||||
jsonData: "256",
|
||||
wantErr: true,
|
||||
},
|
||||
"-1 errors": {
|
||||
sut: "-1",
|
||||
wantErr: true,
|
||||
},
|
||||
"2.6 errors": {
|
||||
sut: "2.6",
|
||||
wantErr: true,
|
||||
},
|
||||
"2.0 errors": {
|
||||
sut: "2.0",
|
||||
wantErr: true,
|
||||
},
|
||||
"hex format is invalid": {
|
||||
sut: "0x10",
|
||||
wantErr: true,
|
||||
},
|
||||
"octal format is invalid": {
|
||||
sut: "010",
|
||||
wantErr: true,
|
||||
yamlData: "-1",
|
||||
jsonData: "-1",
|
||||
wantErr: true,
|
||||
},
|
||||
"0 resolves to value 0": {
|
||||
sut: "0",
|
||||
want: AttestationVersion{
|
||||
yamlData: "0",
|
||||
jsonData: "0",
|
||||
want: AttestationVersion[uint8]{
|
||||
Value: 0,
|
||||
WantLatest: false,
|
||||
},
|
||||
},
|
||||
"00 errors": {
|
||||
sut: "00",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for name, tc := range tests {
|
||||
for name, tc := range testCasesUint8 {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
assert := assert.New(t)
|
||||
|
||||
var sut AttestationVersion
|
||||
err := yaml.Unmarshal([]byte(tc.sut), &sut)
|
||||
if tc.wantErr {
|
||||
require.Error(err)
|
||||
return
|
||||
{
|
||||
var sut AttestationVersion[uint8]
|
||||
err := yaml.Unmarshal([]byte(tc.yamlData), &sut)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, sut)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var sut AttestationVersion[uint8]
|
||||
err := json.Unmarshal([]byte(tc.jsonData), &sut)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, sut)
|
||||
}
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Equal(tc.want, sut)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionUnmarshalJSON(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
sut string
|
||||
want AttestationVersion
|
||||
wantErr bool
|
||||
testCasesUint16 := map[string]struct {
|
||||
yamlData string
|
||||
jsonData string
|
||||
want AttestationVersion[uint16]
|
||||
wantErr bool
|
||||
}{
|
||||
"latest resolves to isLatest": {
|
||||
sut: `"latest"`,
|
||||
want: AttestationVersion{
|
||||
yamlData: "latest",
|
||||
jsonData: "\"latest\"",
|
||||
want: AttestationVersion[uint16]{
|
||||
Value: 0,
|
||||
WantLatest: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"1 resolves to value 1": {
|
||||
sut: "1",
|
||||
want: AttestationVersion{
|
||||
yamlData: "1",
|
||||
jsonData: "1",
|
||||
want: AttestationVersion[uint16]{
|
||||
Value: 1,
|
||||
WantLatest: false,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"quoted number resolves to value": {
|
||||
sut: `"1"`,
|
||||
want: AttestationVersion{
|
||||
Value: 1,
|
||||
WantLatest: false,
|
||||
},
|
||||
},
|
||||
"quoted float errors": {
|
||||
sut: `"1.0"`,
|
||||
wantErr: true,
|
||||
},
|
||||
"max uint8+1 errors": {
|
||||
sut: "256",
|
||||
wantErr: true,
|
||||
"max uint16+1 errors": {
|
||||
yamlData: "65536",
|
||||
jsonData: "65536",
|
||||
wantErr: true,
|
||||
},
|
||||
"-1 errors": {
|
||||
sut: "-1",
|
||||
wantErr: true,
|
||||
},
|
||||
"2.6 errors": {
|
||||
sut: "2.6",
|
||||
wantErr: true,
|
||||
},
|
||||
"2.0 errors": {
|
||||
sut: "2.0",
|
||||
wantErr: true,
|
||||
},
|
||||
"hex format is invalid": {
|
||||
sut: "0x10",
|
||||
wantErr: true,
|
||||
},
|
||||
"octal format is invalid": {
|
||||
sut: "010",
|
||||
wantErr: true,
|
||||
yamlData: "-1",
|
||||
jsonData: "-1",
|
||||
wantErr: true,
|
||||
},
|
||||
"0 resolves to value 0": {
|
||||
sut: "0",
|
||||
want: AttestationVersion{
|
||||
yamlData: "0",
|
||||
jsonData: "0",
|
||||
want: AttestationVersion[uint16]{
|
||||
Value: 0,
|
||||
WantLatest: false,
|
||||
},
|
||||
},
|
||||
"quoted 0 resolves to value 0": {
|
||||
sut: `"0"`,
|
||||
want: AttestationVersion{
|
||||
Value: 0,
|
||||
WantLatest: false,
|
||||
},
|
||||
},
|
||||
"00 errors": {
|
||||
sut: "00",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for name, tc := range tests {
|
||||
for name, tc := range testCasesUint16 {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
assert := assert.New(t)
|
||||
|
||||
var sut AttestationVersion
|
||||
err := json.Unmarshal([]byte(tc.sut), &sut)
|
||||
if tc.wantErr {
|
||||
require.Error(err)
|
||||
return
|
||||
{
|
||||
var sut AttestationVersion[uint16]
|
||||
err := yaml.Unmarshal([]byte(tc.yamlData), &sut)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, sut)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var sut AttestationVersion[uint16]
|
||||
err := json.Unmarshal([]byte(tc.jsonData), &sut)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, sut)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
testCasesHexBytes := map[string]struct {
|
||||
yamlData string
|
||||
jsonData string
|
||||
want AttestationVersion[encoding.HexBytes]
|
||||
wantErr bool
|
||||
}{
|
||||
"latest resolves to isLatest": {
|
||||
yamlData: "latest",
|
||||
jsonData: "\"latest\"",
|
||||
want: AttestationVersion[encoding.HexBytes]{
|
||||
Value: encoding.HexBytes(nil),
|
||||
WantLatest: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"hex string resolves to correctly": {
|
||||
yamlData: "41414141414141414141414141414141",
|
||||
jsonData: "\"41414141414141414141414141414141\"",
|
||||
want: AttestationVersion[encoding.HexBytes]{
|
||||
Value: encoding.HexBytes(bytes.Repeat([]byte("A"), 16)),
|
||||
WantLatest: false,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"invalid hex string": {
|
||||
yamlData: "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
|
||||
jsonData: "\"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\"",
|
||||
wantErr: true,
|
||||
},
|
||||
"non hex data": {
|
||||
yamlData: "-15",
|
||||
jsonData: "-15",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for name, tc := range testCasesHexBytes {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
{
|
||||
var sut AttestationVersion[encoding.HexBytes]
|
||||
err := yaml.Unmarshal([]byte(tc.yamlData), &sut)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, sut)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var sut AttestationVersion[encoding.HexBytes]
|
||||
err := json.Unmarshal([]byte(tc.jsonData), &sut)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, sut)
|
||||
}
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Equal(tc.want, sut)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ var _ svnResolveMarshaller = &AWSSEVSNP{}
|
||||
func DefaultForAWSSEVSNP() *AWSSEVSNP {
|
||||
return &AWSSEVSNP{
|
||||
Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSSEVSNP{}),
|
||||
BootloaderVersion: NewLatestPlaceholderVersion(),
|
||||
TEEVersion: NewLatestPlaceholderVersion(),
|
||||
SNPVersion: NewLatestPlaceholderVersion(),
|
||||
MicrocodeVersion: NewLatestPlaceholderVersion(),
|
||||
BootloaderVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
TEEVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
SNPVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
MicrocodeVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
AMDRootKey: mustParsePEM(arkPEM),
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,10 @@ var (
|
||||
func DefaultForAzureSEVSNP() *AzureSEVSNP {
|
||||
return &AzureSEVSNP{
|
||||
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}),
|
||||
BootloaderVersion: NewLatestPlaceholderVersion(),
|
||||
TEEVersion: NewLatestPlaceholderVersion(),
|
||||
SNPVersion: NewLatestPlaceholderVersion(),
|
||||
MicrocodeVersion: NewLatestPlaceholderVersion(),
|
||||
BootloaderVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
TEEVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
SNPVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
MicrocodeVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
FirmwareSignerConfig: SNPFirmwareSignerConfig{
|
||||
AcceptedKeyDigests: idkeydigest.DefaultList(),
|
||||
EnforcementPolicy: idkeydigest.MAAFallback,
|
||||
@ -142,14 +142,14 @@ func DefaultForAzureTDX() *AzureTDX {
|
||||
return &AzureTDX{
|
||||
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTDX{}),
|
||||
// TODO(AB#3798): Enable latest versioning for Azure TDX
|
||||
QESVN: 0,
|
||||
PCESVN: 0,
|
||||
TEETCBSVN: encoding.HexBytes{0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
QEVendorID: encoding.HexBytes{0x93, 0x9a, 0x72, 0x33, 0xf7, 0x9c, 0x4c, 0xa9, 0x94, 0x0a, 0x0d, 0xb3, 0x95, 0x7f, 0x06, 0x07},
|
||||
QESVN: NewLatestPlaceholderVersion[uint16](),
|
||||
PCESVN: NewLatestPlaceholderVersion[uint16](),
|
||||
TEETCBSVN: NewLatestPlaceholderVersion[encoding.HexBytes](),
|
||||
QEVendorID: NewLatestPlaceholderVersion[encoding.HexBytes](),
|
||||
// Don't set a default for MRSEAM as it effectively prevents upgrading the SEAM module
|
||||
// Quote verification still makes sure the module comes from Intel (through MRSIGNERSEAM), and is not of a lower version than expected
|
||||
// MRSeam: nil,
|
||||
XFAM: encoding.HexBytes{0xe7, 0x18, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
XFAM: NewLatestPlaceholderVersion[encoding.HexBytes](),
|
||||
|
||||
IntelRootKey: mustParsePEM(tdxRootPEM),
|
||||
}
|
||||
@ -179,9 +179,43 @@ func (c AzureTDX) EqualTo(other AttestationCfg) (bool, error) {
|
||||
return c.Measurements.EqualTo(otherCfg.Measurements), nil
|
||||
}
|
||||
|
||||
// FetchAndSetLatestVersionNumbers fetches the latest version numbers from the configapi and sets them.
|
||||
func (c *AzureTDX) FetchAndSetLatestVersionNumbers(ctx context.Context, fetcher attestationconfigapi.Fetcher) error {
|
||||
// Only talk to the API if at least one version number is set to latest.
|
||||
if !(c.PCESVN.WantLatest || c.QESVN.WantLatest || c.TEETCBSVN.WantLatest || c.QEVendorID.WantLatest || c.XFAM.WantLatest) {
|
||||
return nil
|
||||
}
|
||||
|
||||
versions, err := fetcher.FetchLatestVersion(ctx, variant.AzureTDX{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching latest TCB versions from configapi: %w", err)
|
||||
}
|
||||
|
||||
// set values and keep WantLatest flag
|
||||
if c.PCESVN.WantLatest {
|
||||
c.PCESVN.Value = versions.PCESVN
|
||||
}
|
||||
if c.QESVN.WantLatest {
|
||||
c.QESVN.Value = versions.QESVN
|
||||
}
|
||||
if c.TEETCBSVN.WantLatest {
|
||||
c.TEETCBSVN.Value = versions.TEETCBSVN[:]
|
||||
}
|
||||
if c.QEVendorID.WantLatest {
|
||||
c.QEVendorID.Value = versions.QEVendorID[:]
|
||||
}
|
||||
if c.XFAM.WantLatest {
|
||||
c.XFAM.Value = versions.XFAM[:]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AzureTDX) getToMarshallLatestWithResolvedVersions() AttestationCfg {
|
||||
cp := *c
|
||||
// TODO: We probably want to support "latest" pseudo versioning for Azure TDX
|
||||
// But we should decide on which claims can be reliably used for attestation first
|
||||
cp.PCESVN.WantLatest = false
|
||||
cp.QESVN.WantLatest = false
|
||||
cp.TEETCBSVN.WantLatest = false
|
||||
cp.QEVendorID.WantLatest = false
|
||||
cp.XFAM.WantLatest = false
|
||||
return &cp
|
||||
}
|
||||
|
@ -468,18 +468,22 @@ func New(fileHandler file.Handler, name string, fetcher attestationconfigapi.Fet
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Replace "latest" placeholders for attestation version numbers with the actual latest version numbers from config API
|
||||
if azure := c.Attestation.AzureSEVSNP; azure != nil {
|
||||
if err := azure.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil {
|
||||
return c, err
|
||||
}
|
||||
}
|
||||
|
||||
if azure := c.Attestation.AzureTDX; azure != nil {
|
||||
if err := azure.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil {
|
||||
return c, err
|
||||
}
|
||||
}
|
||||
if aws := c.Attestation.AWSSEVSNP; aws != nil {
|
||||
if err := aws.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil {
|
||||
return c, err
|
||||
}
|
||||
}
|
||||
|
||||
if gcp := c.Attestation.GCPSEVSNP; gcp != nil {
|
||||
if err := gcp.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil {
|
||||
return c, err
|
||||
@ -993,16 +997,16 @@ type GCPSEVSNP struct {
|
||||
Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"`
|
||||
// description: |
|
||||
// Lowest acceptable bootloader version.
|
||||
BootloaderVersion AttestationVersion `json:"bootloaderVersion" yaml:"bootloaderVersion"`
|
||||
BootloaderVersion AttestationVersion[uint8] `json:"bootloaderVersion" yaml:"bootloaderVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable TEE version.
|
||||
TEEVersion AttestationVersion `json:"teeVersion" yaml:"teeVersion"`
|
||||
TEEVersion AttestationVersion[uint8] `json:"teeVersion" yaml:"teeVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable SEV-SNP version.
|
||||
SNPVersion AttestationVersion `json:"snpVersion" yaml:"snpVersion"`
|
||||
SNPVersion AttestationVersion[uint8] `json:"snpVersion" yaml:"snpVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable microcode version.
|
||||
MicrocodeVersion AttestationVersion `json:"microcodeVersion" yaml:"microcodeVersion"`
|
||||
MicrocodeVersion AttestationVersion[uint8] `json:"microcodeVersion" yaml:"microcodeVersion"`
|
||||
// description: |
|
||||
// AMD Root Key certificate used to verify the SEV-SNP certificate chain.
|
||||
AMDRootKey Certificate `json:"amdRootKey" yaml:"amdRootKey"`
|
||||
@ -1080,16 +1084,16 @@ type AWSSEVSNP struct {
|
||||
Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"`
|
||||
// description: |
|
||||
// Lowest acceptable bootloader version.
|
||||
BootloaderVersion AttestationVersion `json:"bootloaderVersion" yaml:"bootloaderVersion"`
|
||||
BootloaderVersion AttestationVersion[uint8] `json:"bootloaderVersion" yaml:"bootloaderVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable TEE version.
|
||||
TEEVersion AttestationVersion `json:"teeVersion" yaml:"teeVersion"`
|
||||
TEEVersion AttestationVersion[uint8] `json:"teeVersion" yaml:"teeVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable SEV-SNP version.
|
||||
SNPVersion AttestationVersion `json:"snpVersion" yaml:"snpVersion"`
|
||||
SNPVersion AttestationVersion[uint8] `json:"snpVersion" yaml:"snpVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable microcode version.
|
||||
MicrocodeVersion AttestationVersion `json:"microcodeVersion" yaml:"microcodeVersion"`
|
||||
MicrocodeVersion AttestationVersion[uint8] `json:"microcodeVersion" yaml:"microcodeVersion"`
|
||||
// description: |
|
||||
// AMD Root Key certificate used to verify the SEV-SNP certificate chain.
|
||||
AMDRootKey Certificate `json:"amdRootKey" yaml:"amdRootKey"`
|
||||
@ -1112,16 +1116,16 @@ type AzureSEVSNP struct {
|
||||
Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"`
|
||||
// description: |
|
||||
// Lowest acceptable bootloader version.
|
||||
BootloaderVersion AttestationVersion `json:"bootloaderVersion" yaml:"bootloaderVersion"`
|
||||
BootloaderVersion AttestationVersion[uint8] `json:"bootloaderVersion" yaml:"bootloaderVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable TEE version.
|
||||
TEEVersion AttestationVersion `json:"teeVersion" yaml:"teeVersion"`
|
||||
TEEVersion AttestationVersion[uint8] `json:"teeVersion" yaml:"teeVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable SEV-SNP version.
|
||||
SNPVersion AttestationVersion `json:"snpVersion" yaml:"snpVersion"`
|
||||
SNPVersion AttestationVersion[uint8] `json:"snpVersion" yaml:"snpVersion"`
|
||||
// description: |
|
||||
// Lowest acceptable microcode version.
|
||||
MicrocodeVersion AttestationVersion `json:"microcodeVersion" yaml:"microcodeVersion"`
|
||||
MicrocodeVersion AttestationVersion[uint8] `json:"microcodeVersion" yaml:"microcodeVersion"`
|
||||
// description: |
|
||||
// Configuration for validating the firmware signature.
|
||||
FirmwareSignerConfig SNPFirmwareSignerConfig `json:"firmwareSignerConfig" yaml:"firmwareSignerConfig"`
|
||||
@ -1147,22 +1151,22 @@ type AzureTDX struct {
|
||||
Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"`
|
||||
// description: |
|
||||
// Minimum required QE security version number (SVN).
|
||||
QESVN uint16 `json:"qeSVN" yaml:"qeSVN"`
|
||||
QESVN AttestationVersion[uint16] `json:"qeSVN" yaml:"qeSVN"`
|
||||
// description: |
|
||||
// Minimum required PCE security version number (SVN).
|
||||
PCESVN uint16 `json:"pceSVN" yaml:"pceSVN"`
|
||||
PCESVN AttestationVersion[uint16] `json:"pceSVN" yaml:"pceSVN"`
|
||||
// description: |
|
||||
// Component-wise minimum required 16 byte hex-encoded TEE_TCB security version number (SVN).
|
||||
TEETCBSVN encoding.HexBytes `json:"teeTCBSVN" yaml:"teeTCBSVN"`
|
||||
TEETCBSVN AttestationVersion[encoding.HexBytes] `json:"teeTCBSVN" yaml:"teeTCBSVN"`
|
||||
// description: |
|
||||
// Expected 16 byte hex-encoded QE_VENDOR_ID field.
|
||||
QEVendorID encoding.HexBytes `json:"qeVendorID" yaml:"qeVendorID"`
|
||||
QEVendorID AttestationVersion[encoding.HexBytes] `json:"qeVendorID" yaml:"qeVendorID"`
|
||||
// description: |
|
||||
// Expected 48 byte hex-encoded MR_SEAM value.
|
||||
MRSeam encoding.HexBytes `json:"mrSeam,omitempty" yaml:"mrSeam,omitempty"`
|
||||
// description: |
|
||||
// Expected 8 byte hex-encoded XFAM field.
|
||||
XFAM encoding.HexBytes `json:"xfam" yaml:"xfam"`
|
||||
XFAM AttestationVersion[encoding.HexBytes] `json:"xfam" yaml:"xfam"`
|
||||
// description: |
|
||||
// Intel Root Key certificate used to verify the TDX certificate chain.
|
||||
IntelRootKey Certificate `json:"intelRootKey" yaml:"intelRootKey"`
|
||||
|
@ -70,10 +70,10 @@ func TestGetAttestationConfigMarshalsNumericalVersion(t *testing.T) {
|
||||
var mp map[string]interface{}
|
||||
require.NoError(yaml.Unmarshal(bt, &mp))
|
||||
assert := assert.New(t)
|
||||
assert.Equal(placeholderVersionValue, mp["microcodeVersion"])
|
||||
assert.Equal(placeholderVersionValue, mp["teeVersion"])
|
||||
assert.Equal(placeholderVersionValue, mp["snpVersion"])
|
||||
assert.Equal(placeholderVersionValue, mp["bootloaderVersion"])
|
||||
assert.EqualValues(placeholderVersionValue[uint8](), mp["microcodeVersion"])
|
||||
assert.EqualValues(placeholderVersionValue[uint8](), mp["teeVersion"])
|
||||
assert.EqualValues(placeholderVersionValue[uint8](), mp["snpVersion"])
|
||||
assert.EqualValues(placeholderVersionValue[uint8](), mp["bootloaderVersion"])
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
@ -99,19 +99,19 @@ func TestNew(t *testing.T) {
|
||||
wantResult: func() *Config {
|
||||
conf := Default()
|
||||
modifyConfigForAzureToPassValidate(conf)
|
||||
conf.Attestation.AzureSEVSNP.MicrocodeVersion = AttestationVersion{
|
||||
conf.Attestation.AzureSEVSNP.MicrocodeVersion = AttestationVersion[uint8]{
|
||||
Value: testCfg.Microcode,
|
||||
WantLatest: true,
|
||||
}
|
||||
conf.Attestation.AzureSEVSNP.TEEVersion = AttestationVersion{
|
||||
conf.Attestation.AzureSEVSNP.TEEVersion = AttestationVersion[uint8]{
|
||||
Value: 2,
|
||||
WantLatest: false,
|
||||
}
|
||||
conf.Attestation.AzureSEVSNP.BootloaderVersion = AttestationVersion{
|
||||
conf.Attestation.AzureSEVSNP.BootloaderVersion = AttestationVersion[uint8]{
|
||||
Value: 1,
|
||||
WantLatest: false,
|
||||
}
|
||||
conf.Attestation.AzureSEVSNP.SNPVersion = AttestationVersion{
|
||||
conf.Attestation.AzureSEVSNP.SNPVersion = AttestationVersion[uint8]{
|
||||
Value: testCfg.SNP,
|
||||
WantLatest: true,
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ var _ svnResolveMarshaller = &GCPSEVSNP{}
|
||||
func DefaultForGCPSEVSNP() *GCPSEVSNP {
|
||||
return &GCPSEVSNP{
|
||||
Measurements: measurements.DefaultsFor(cloudprovider.GCP, variant.GCPSEVSNP{}),
|
||||
BootloaderVersion: NewLatestPlaceholderVersion(),
|
||||
TEEVersion: NewLatestPlaceholderVersion(),
|
||||
SNPVersion: NewLatestPlaceholderVersion(),
|
||||
MicrocodeVersion: NewLatestPlaceholderVersion(),
|
||||
BootloaderVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
TEEVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
SNPVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
MicrocodeVersion: NewLatestPlaceholderVersion[uint8](),
|
||||
AMDRootKey: mustParsePEM(arkPEM),
|
||||
}
|
||||
}
|
||||
|
@ -415,19 +415,19 @@ func V3ToV4(path string, fileHandler file.Handler) error {
|
||||
case cfgV3.Attestation.AzureSEVSNP != nil:
|
||||
cfgV4.Attestation.AzureSEVSNP = &config.AzureSEVSNP{
|
||||
Measurements: cfgV3.Attestation.AzureSEVSNP.Measurements,
|
||||
BootloaderVersion: config.AttestationVersion{
|
||||
BootloaderVersion: config.AttestationVersion[uint8]{
|
||||
Value: cfgV3.Attestation.AzureSEVSNP.BootloaderVersion.Value,
|
||||
WantLatest: cfgV3.Attestation.AzureSEVSNP.BootloaderVersion.WantLatest,
|
||||
},
|
||||
TEEVersion: config.AttestationVersion{
|
||||
TEEVersion: config.AttestationVersion[uint8]{
|
||||
Value: cfgV3.Attestation.AzureSEVSNP.TEEVersion.Value,
|
||||
WantLatest: cfgV3.Attestation.AzureSEVSNP.TEEVersion.WantLatest,
|
||||
},
|
||||
SNPVersion: config.AttestationVersion{
|
||||
SNPVersion: config.AttestationVersion[uint8]{
|
||||
Value: cfgV3.Attestation.AzureSEVSNP.SNPVersion.Value,
|
||||
WantLatest: cfgV3.Attestation.AzureSEVSNP.SNPVersion.WantLatest,
|
||||
},
|
||||
MicrocodeVersion: config.AttestationVersion{
|
||||
MicrocodeVersion: config.AttestationVersion[uint8]{
|
||||
Value: cfgV3.Attestation.AzureSEVSNP.MicrocodeVersion.Value,
|
||||
WantLatest: cfgV3.Attestation.AzureSEVSNP.MicrocodeVersion.WantLatest,
|
||||
},
|
||||
|
@ -32,6 +32,7 @@ go_library(
|
||||
"//internal/constellation/helm",
|
||||
"//internal/constellation/kubecmd",
|
||||
"//internal/constellation/state",
|
||||
"//internal/encoding",
|
||||
"//internal/file",
|
||||
"//internal/grpc/dialer",
|
||||
"//internal/imagefetcher",
|
||||
|
@ -162,17 +162,18 @@ func (d *AttestationDataSource) Read(ctx context.Context, req datasource.ReadReq
|
||||
|
||||
insecureFetch := data.Insecure.ValueBool()
|
||||
|
||||
snpVersions := attestationconfigapi.VersionAPIEntry{}
|
||||
if attestationVariant.Equal(variant.AzureSEVSNP{}) ||
|
||||
attestationVariant.Equal(variant.AWSSEVSNP{}) ||
|
||||
latestVersions := attestationconfigapi.VersionAPIEntry{}
|
||||
if attestationVariant.Equal(variant.AWSSEVSNP{}) ||
|
||||
attestationVariant.Equal(variant.AzureSEVSNP{}) ||
|
||||
attestationVariant.Equal(variant.AzureTDX{}) ||
|
||||
attestationVariant.Equal(variant.GCPSEVSNP{}) {
|
||||
snpVersions, err = d.fetcher.FetchLatestVersion(ctx, attestationVariant)
|
||||
latestVersions, err = d.fetcher.FetchLatestVersion(ctx, attestationVariant)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Fetching SNP Version numbers", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
tfAttestation, err := convertToTfAttestation(attestationVariant, snpVersions)
|
||||
tfAttestation, err := convertToTfAttestation(attestationVariant, latestVersions)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Converting attestation", err.Error())
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||
"github.com/edgelesssys/constellation/v2/internal/encoding"
|
||||
)
|
||||
|
||||
// naming schema:
|
||||
@ -110,12 +111,12 @@ func convertFromTfAttestationCfg(tfAttestation attestationAttribute, attestation
|
||||
|
||||
attestationConfig = &config.AzureTDX{
|
||||
Measurements: c11nMeasurements,
|
||||
QESVN: tfAttestation.TDX.QESVN,
|
||||
PCESVN: tfAttestation.TDX.PCESVN,
|
||||
TEETCBSVN: teeTCBSVN,
|
||||
QEVendorID: qeVendorID,
|
||||
QESVN: newVersion(tfAttestation.TDX.QESVN),
|
||||
PCESVN: newVersion(tfAttestation.TDX.PCESVN),
|
||||
TEETCBSVN: newVersion(encoding.HexBytes(teeTCBSVN)),
|
||||
QEVendorID: newVersion(encoding.HexBytes(qeVendorID)),
|
||||
MRSeam: mrSeam,
|
||||
XFAM: xfam,
|
||||
XFAM: newVersion(encoding.HexBytes(xfam)),
|
||||
IntelRootKey: rootKey,
|
||||
}
|
||||
case variant.GCPSEVES{}:
|
||||
@ -137,13 +138,9 @@ func convertFromTfAttestationCfg(tfAttestation attestationAttribute, attestation
|
||||
}
|
||||
|
||||
// convertToTfAttestationCfg converts the constellation attestation config to the related terraform structs.
|
||||
func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfigapi.VersionAPIEntry) (tfAttestation attestationAttribute, err error) {
|
||||
func convertToTfAttestation(attVar variant.Variant, latestVersions attestationconfigapi.VersionAPIEntry) (tfAttestation attestationAttribute, err error) {
|
||||
tfAttestation = attestationAttribute{
|
||||
Variant: attVar.String(),
|
||||
BootloaderVersion: snpVersions.Bootloader,
|
||||
TEEVersion: snpVersions.TEE,
|
||||
SNPVersion: snpVersions.SNP,
|
||||
MicrocodeVersion: snpVersions.Microcode,
|
||||
Variant: attVar.String(),
|
||||
}
|
||||
|
||||
switch attVar {
|
||||
@ -153,6 +150,10 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi
|
||||
return tfAttestation, err
|
||||
}
|
||||
tfAttestation.AMDRootKey = certStr
|
||||
tfAttestation.BootloaderVersion = latestVersions.Bootloader
|
||||
tfAttestation.TEEVersion = latestVersions.TEE
|
||||
tfAttestation.SNPVersion = latestVersions.SNP
|
||||
tfAttestation.MicrocodeVersion = latestVersions.Microcode
|
||||
|
||||
case variant.GCPSEVSNP{}:
|
||||
certStr, err := certAsString(config.DefaultForGCPSEVSNP().AMDRootKey)
|
||||
@ -160,6 +161,10 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi
|
||||
return tfAttestation, err
|
||||
}
|
||||
tfAttestation.AMDRootKey = certStr
|
||||
tfAttestation.BootloaderVersion = latestVersions.Bootloader
|
||||
tfAttestation.TEEVersion = latestVersions.TEE
|
||||
tfAttestation.SNPVersion = latestVersions.SNP
|
||||
tfAttestation.MicrocodeVersion = latestVersions.Microcode
|
||||
|
||||
case variant.AzureSEVSNP{}:
|
||||
certStr, err := certAsString(config.DefaultForAzureSEVSNP().AMDRootKey)
|
||||
@ -167,6 +172,10 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi
|
||||
return tfAttestation, err
|
||||
}
|
||||
tfAttestation.AMDRootKey = certStr
|
||||
tfAttestation.BootloaderVersion = latestVersions.Bootloader
|
||||
tfAttestation.TEEVersion = latestVersions.TEE
|
||||
tfAttestation.SNPVersion = latestVersions.SNP
|
||||
tfAttestation.MicrocodeVersion = latestVersions.Microcode
|
||||
|
||||
firmwareCfg := config.DefaultForAzureSEVSNP().FirmwareSignerConfig
|
||||
tfFirmwareCfg, err := convertToTfFirmwareCfg(firmwareCfg)
|
||||
@ -174,24 +183,19 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi
|
||||
return tfAttestation, err
|
||||
}
|
||||
tfAttestation.AzureSNPFirmwareSignerConfig = tfFirmwareCfg
|
||||
|
||||
case variant.AzureTDX{}:
|
||||
tdxCfg := config.DefaultForAzureTDX()
|
||||
certStr, err := certAsString(tdxCfg.IntelRootKey)
|
||||
certStr, err := certAsString(config.DefaultForAzureTDX().IntelRootKey)
|
||||
if err != nil {
|
||||
return tfAttestation, err
|
||||
}
|
||||
tfAttestation.TDX.IntelRootKey = certStr
|
||||
tfAttestation.TDX.PCESVN = latestVersions.PCESVN
|
||||
tfAttestation.TDX.QESVN = latestVersions.QESVN
|
||||
tfAttestation.TDX.TEETCBSVN = hex.EncodeToString(latestVersions.TEETCBSVN[:])
|
||||
tfAttestation.TDX.QEVendorID = hex.EncodeToString(latestVersions.QEVendorID[:])
|
||||
tfAttestation.TDX.XFAM = hex.EncodeToString(latestVersions.XFAM[:])
|
||||
|
||||
tfTdxCfg := tdxConfigAttribute{
|
||||
IntelRootKey: certStr,
|
||||
// TODO(AB#3798): Load these values dynamically from our attestation API
|
||||
QESVN: tdxCfg.QESVN,
|
||||
PCESVN: tdxCfg.PCESVN,
|
||||
TEETCBSVN: hex.EncodeToString(tdxCfg.TEETCBSVN),
|
||||
QEVendorID: hex.EncodeToString(tdxCfg.QEVendorID),
|
||||
MRSeam: hex.EncodeToString(tdxCfg.MRSeam),
|
||||
XFAM: hex.EncodeToString(tdxCfg.XFAM),
|
||||
}
|
||||
tfAttestation.TDX = tfTdxCfg
|
||||
case variant.GCPSEVES{}, variant.QEMUVTPM{}:
|
||||
// no additional fields
|
||||
default:
|
||||
@ -251,8 +255,8 @@ func convertToTfMeasurements(m measurements.M) map[string]measurementAttribute {
|
||||
return tfMeasurements
|
||||
}
|
||||
|
||||
func newVersion(v uint8) config.AttestationVersion {
|
||||
return config.AttestationVersion{
|
||||
func newVersion[T uint8 | uint16 | encoding.HexBytes](v T) config.AttestationVersion[T] {
|
||||
return config.AttestationVersion[T]{
|
||||
Value: v,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user