s3 draft working

fix tests with DefaultWithPanic()
This commit is contained in:
Adrian Stobbe 2023-05-19 23:50:53 +02:00
parent 934722ae76
commit 0f942bafca
33 changed files with 548 additions and 194 deletions

View file

@ -41,18 +41,18 @@ func TestCreator(t *testing.T) {
"gcp": { "gcp": {
tfClient: &stubTerraformClient{ip: ip}, tfClient: &stubTerraformClient{ip: ip},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
config: config.Default(), config: config.DefaultWithPanic(),
}, },
"gcp newTerraformClient error": { "gcp newTerraformClient error": {
newTfClientErr: someErr, newTfClientErr: someErr,
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
config: config.Default(), config: config.DefaultWithPanic(),
wantErr: true, wantErr: true,
}, },
"gcp create cluster error": { "gcp create cluster error": {
tfClient: &stubTerraformClient{createClusterErr: someErr}, tfClient: &stubTerraformClient{createClusterErr: someErr},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
config: config.Default(), config: config.DefaultWithPanic(),
wantErr: true, wantErr: true,
wantRollback: true, wantRollback: true,
wantTerraformRollback: true, wantTerraformRollback: true,
@ -61,7 +61,7 @@ func TestCreator(t *testing.T) {
tfClient: &stubTerraformClient{ip: ip}, tfClient: &stubTerraformClient{ip: ip},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure) cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
return cfg return cfg
}(), }(),
@ -71,7 +71,7 @@ func TestCreator(t *testing.T) {
tfClient: &stubTerraformClient{ip: ip}, tfClient: &stubTerraformClient{ip: ip},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.Attestation = config.AttestationConfig{ cfg.Attestation = config.AttestationConfig{
AzureTrustedLaunch: &config.AzureTrustedLaunch{}, AzureTrustedLaunch: &config.AzureTrustedLaunch{},
} }
@ -83,7 +83,7 @@ func TestCreator(t *testing.T) {
tfClient: &stubTerraformClient{ip: ip}, tfClient: &stubTerraformClient{ip: ip},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure) cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
return cfg return cfg
}(), }(),
@ -94,7 +94,7 @@ func TestCreator(t *testing.T) {
newTfClientErr: someErr, newTfClientErr: someErr,
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure) cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
return cfg return cfg
}(), }(),
@ -105,7 +105,7 @@ func TestCreator(t *testing.T) {
tfClient: &stubTerraformClient{createClusterErr: someErr}, tfClient: &stubTerraformClient{createClusterErr: someErr},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure) cfg.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
return cfg return cfg
}(), }(),
@ -119,7 +119,7 @@ func TestCreator(t *testing.T) {
libvirt: &stubLibvirtRunner{}, libvirt: &stubLibvirtRunner{},
provider: cloudprovider.OpenStack, provider: cloudprovider.OpenStack,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.Provider.OpenStack.Cloud = "testcloud" cfg.Provider.OpenStack.Cloud = "testcloud"
return cfg return cfg
}(), }(),
@ -128,7 +128,7 @@ func TestCreator(t *testing.T) {
tfClient: &stubTerraformClient{ip: ip}, tfClient: &stubTerraformClient{ip: ip},
libvirt: &stubLibvirtRunner{}, libvirt: &stubLibvirtRunner{},
provider: cloudprovider.OpenStack, provider: cloudprovider.OpenStack,
config: config.Default(), config: config.DefaultWithPanic(),
wantErr: true, wantErr: true,
}, },
"openstack newTerraformClient error": { "openstack newTerraformClient error": {
@ -136,7 +136,7 @@ func TestCreator(t *testing.T) {
libvirt: &stubLibvirtRunner{}, libvirt: &stubLibvirtRunner{},
provider: cloudprovider.OpenStack, provider: cloudprovider.OpenStack,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.Provider.OpenStack.Cloud = "testcloud" cfg.Provider.OpenStack.Cloud = "testcloud"
return cfg return cfg
}(), }(),
@ -147,7 +147,7 @@ func TestCreator(t *testing.T) {
libvirt: &stubLibvirtRunner{}, libvirt: &stubLibvirtRunner{},
provider: cloudprovider.OpenStack, provider: cloudprovider.OpenStack,
config: func() *config.Config { config: func() *config.Config {
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.Provider.OpenStack.Cloud = "testcloud" cfg.Provider.OpenStack.Cloud = "testcloud"
return cfg return cfg
}(), }(),
@ -159,21 +159,21 @@ func TestCreator(t *testing.T) {
tfClient: &stubTerraformClient{ip: ip}, tfClient: &stubTerraformClient{ip: ip},
libvirt: &stubLibvirtRunner{}, libvirt: &stubLibvirtRunner{},
provider: cloudprovider.QEMU, provider: cloudprovider.QEMU,
config: config.Default(), config: config.DefaultWithPanic(),
wantErr: failOnNonAMD64, wantErr: failOnNonAMD64,
}, },
"qemu newTerraformClient error": { "qemu newTerraformClient error": {
newTfClientErr: someErr, newTfClientErr: someErr,
libvirt: &stubLibvirtRunner{}, libvirt: &stubLibvirtRunner{},
provider: cloudprovider.QEMU, provider: cloudprovider.QEMU,
config: config.Default(), config: config.DefaultWithPanic(),
wantErr: true, wantErr: true,
}, },
"qemu create cluster error": { "qemu create cluster error": {
tfClient: &stubTerraformClient{createClusterErr: someErr}, tfClient: &stubTerraformClient{createClusterErr: someErr},
libvirt: &stubLibvirtRunner{}, libvirt: &stubLibvirtRunner{},
provider: cloudprovider.QEMU, provider: cloudprovider.QEMU,
config: config.Default(), config: config.DefaultWithPanic(),
wantErr: true, wantErr: true,
wantRollback: !failOnNonAMD64, // if we run on non-AMD64/linux, we don't get to a point where rollback is needed wantRollback: !failOnNonAMD64, // if we run on non-AMD64/linux, we don't get to a point where rollback is needed
wantTerraformRollback: true, wantTerraformRollback: true,
@ -182,14 +182,14 @@ func TestCreator(t *testing.T) {
tfClient: &stubTerraformClient{ip: ip}, tfClient: &stubTerraformClient{ip: ip},
libvirt: &stubLibvirtRunner{startErr: someErr}, libvirt: &stubLibvirtRunner{startErr: someErr},
provider: cloudprovider.QEMU, provider: cloudprovider.QEMU,
config: config.Default(), config: config.DefaultWithPanic(),
wantRollback: !failOnNonAMD64, wantRollback: !failOnNonAMD64,
wantTerraformRollback: false, wantTerraformRollback: false,
wantErr: true, wantErr: true,
}, },
"unknown provider": { "unknown provider": {
provider: cloudprovider.Unknown, provider: cloudprovider.Unknown,
config: config.Default(), config: config.DefaultWithPanic(),
wantErr: true, wantErr: true,
}, },
} }

View file

@ -250,7 +250,7 @@ func TestConfigFetchMeasurements(t *testing.T) {
cmd.Flags().Bool("force", true, "") // register persistent flag manually cmd.Flags().Bool("force", true, "") // register persistent flag manually
fileHandler := file.NewHandler(afero.NewMemMapFs()) fileHandler := file.NewHandler(afero.NewMemMapFs())
gcpConfig := defaultConfigWithExpectedMeasurements(t, config.Default(), cloudprovider.GCP) gcpConfig := defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), cloudprovider.GCP)
gcpConfig.Image = "v999.999.999" gcpConfig.Image = "v999.999.999"
err := fileHandler.WriteYAML(constants.ConfigFilename, gcpConfig, file.OptMkdirAll) err := fileHandler.WriteYAML(constants.ConfigFilename, gcpConfig, file.OptMkdirAll)

View file

@ -36,7 +36,7 @@ func newConfigGenerateCmd() *cobra.Command {
RunE: runConfigGenerate, RunE: runConfigGenerate,
} }
cmd.Flags().StringP("file", "f", constants.ConfigFilename, "path to output file, or '-' for stdout") cmd.Flags().StringP("file", "f", constants.ConfigFilename, "path to output file, or '-' for stdout")
cmd.Flags().StringP("kubernetes", "k", semver.MajorMinor(config.Default().KubernetesVersion), "Kubernetes version to use in format MAJOR.MINOR") cmd.Flags().StringP("kubernetes", "k", semver.MajorMinor(config.DefaultWithPanic().KubernetesVersion), "Kubernetes version to use in format MAJOR.MINOR")
cmd.Flags().StringP("attestation", "a", "", fmt.Sprintf("attestation variant to use %s. If not specified, the default for the cloud provider is used", printFormattedSlice(variant.GetAvailableAttestationTypes()))) cmd.Flags().StringP("attestation", "a", "", fmt.Sprintf("attestation variant to use %s. If not specified, the default for the cloud provider is used", printFormattedSlice(variant.GetAvailableAttestationTypes())))
return cmd return cmd
@ -103,7 +103,10 @@ func (cg *configGenerateCmd) configGenerate(cmd *cobra.Command, fileHandler file
// createConfig creates a config file for the given provider. // createConfig creates a config file for the given provider.
func createConfigWithAttestationType(provider cloudprovider.Provider, attestationVariant variant.Variant) (*config.Config, error) { func createConfigWithAttestationType(provider cloudprovider.Provider, attestationVariant variant.Variant) (*config.Config, error) {
conf := config.Default() conf, err := config.Default()
if err != nil {
return nil, fmt.Errorf("creating default config: %w", err)
}
conf.RemoveProviderExcept(provider) conf.RemoveProviderExcept(provider)
// set a lower default for QEMU's state disk // set a lower default for QEMU's state disk

View file

@ -79,7 +79,7 @@ func TestConfigGenerateDefault(t *testing.T) {
var readConfig config.Config var readConfig config.Config
err := fileHandler.ReadYAML(constants.ConfigFilename, &readConfig) err := fileHandler.ReadYAML(constants.ConfigFilename, &readConfig)
assert.NoError(err) assert.NoError(err)
assert.Equal(*config.Default(), readConfig) assert.Equal(*config.DefaultWithPanic(), readConfig)
} }
func TestConfigGenerateDefaultGCPSpecific(t *testing.T) { func TestConfigGenerateDefaultGCPSpecific(t *testing.T) {
@ -89,7 +89,7 @@ func TestConfigGenerateDefaultGCPSpecific(t *testing.T) {
fileHandler := file.NewHandler(afero.NewMemMapFs()) fileHandler := file.NewHandler(afero.NewMemMapFs())
cmd := newConfigGenerateCmd() cmd := newConfigGenerateCmd()
wantConf := config.Default() wantConf := config.DefaultWithPanic()
wantConf.RemoveProviderAndAttestationExcept(cloudprovider.GCP) wantConf.RemoveProviderAndAttestationExcept(cloudprovider.GCP)
cg := &configGenerateCmd{log: logger.NewTest(t)} cg := &configGenerateCmd{log: logger.NewTest(t)}
@ -140,7 +140,7 @@ func TestConfigGenerateStdOut(t *testing.T) {
var readConfig config.Config var readConfig config.Config
require.NoError(yaml.NewDecoder(&outBuffer).Decode(&readConfig)) require.NoError(yaml.NewDecoder(&outBuffer).Decode(&readConfig))
assert.Equal(*config.Default(), readConfig) assert.Equal(*config.DefaultWithPanic(), readConfig)
} }
func TestNoValidProviderAttestationCombination(t *testing.T) { func TestNoValidProviderAttestationCombination(t *testing.T) {
@ -163,7 +163,7 @@ func TestNoValidProviderAttestationCombination(t *testing.T) {
} }
func TestValidProviderAttestationCombination(t *testing.T) { func TestValidProviderAttestationCombination(t *testing.T) {
defaultAttestation := config.Default().Attestation defaultAttestation := config.DefaultWithPanic().Attestation
tests := []struct { tests := []struct {
provider cloudprovider.Provider provider cloudprovider.Provider
attestation variant.Variant attestation variant.Variant
@ -213,7 +213,7 @@ func TestValidProviderAttestationCombination(t *testing.T) {
} }
func TestAttestationArgument(t *testing.T) { func TestAttestationArgument(t *testing.T) {
defaultAttestation := config.Default().Attestation defaultAttestation := config.DefaultWithPanic().Attestation
tests := []struct { tests := []struct {
name string name string
provider cloudprovider.Provider provider cloudprovider.Provider

View file

@ -27,7 +27,7 @@ func TestCreate(t *testing.T) {
fsWithDefaultConfig := func(require *require.Assertions, provider cloudprovider.Provider) afero.Fs { fsWithDefaultConfig := func(require *require.Assertions, provider cloudprovider.Provider) afero.Fs {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
file := file.NewHandler(fs) file := file.NewHandler(fs)
require.NoError(file.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.Default(), provider))) require.NoError(file.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), provider)))
return fs return fs
} }
idFile := clusterid.File{IP: "192.0.2.1"} idFile := clusterid.File{IP: "192.0.2.1"}
@ -114,7 +114,7 @@ func TestCreate(t *testing.T) {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
require.NoError(fileHandler.Write(constants.AdminConfFilename, []byte{1}, file.OptNone)) require.NoError(fileHandler.Write(constants.AdminConfFilename, []byte{1}, file.OptNone))
require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.Default(), csp))) require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), csp)))
return fs return fs
}, },
creator: &stubCloudCreator{}, creator: &stubCloudCreator{},
@ -129,7 +129,7 @@ func TestCreate(t *testing.T) {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
require.NoError(fileHandler.Write(constants.MasterSecretFilename, []byte{1}, file.OptNone)) require.NoError(fileHandler.Write(constants.MasterSecretFilename, []byte{1}, file.OptNone))
require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.Default(), csp))) require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), csp)))
return fs return fs
}, },
creator: &stubCloudCreator{}, creator: &stubCloudCreator{},
@ -162,7 +162,7 @@ func TestCreate(t *testing.T) {
setupFs: func(require *require.Assertions, csp cloudprovider.Provider) afero.Fs { setupFs: func(require *require.Assertions, csp cloudprovider.Provider) afero.Fs {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.Default(), csp))) require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), csp)))
return afero.NewReadOnlyFs(fs) return afero.NewReadOnlyFs(fs)
}, },
creator: &stubCloudCreator{}, creator: &stubCloudCreator{},

View file

@ -60,7 +60,7 @@ func newIAMCreateCmd() *cobra.Command {
cmd.PersistentFlags().BoolP("yes", "y", false, "create the IAM configuration without further confirmation") cmd.PersistentFlags().BoolP("yes", "y", false, "create the IAM configuration without further confirmation")
cmd.PersistentFlags().Bool("generate-config", false, "automatically generate a configuration file and fill in the required fields") cmd.PersistentFlags().Bool("generate-config", false, "automatically generate a configuration file and fill in the required fields")
cmd.PersistentFlags().StringP("kubernetes", "k", semver.MajorMinor(config.Default().KubernetesVersion), "Kubernetes version to use in format MAJOR.MINOR - only usable in combination with --generate-config") cmd.PersistentFlags().StringP("kubernetes", "k", semver.MajorMinor(config.DefaultWithPanic().KubernetesVersion), "Kubernetes version to use in format MAJOR.MINOR - only usable in combination with --generate-config")
cmd.AddCommand(newIAMCreateAWSCmd()) cmd.AddCommand(newIAMCreateAWSCmd())
cmd.AddCommand(newIAMCreateAzureCmd()) cmd.AddCommand(newIAMCreateAzureCmd())

View file

@ -275,7 +275,7 @@ func TestIAMCreateAWS(t *testing.T) {
// register persistent flags manually // register persistent flags manually
cmd.Flags().String("config", constants.ConfigFilename, "") cmd.Flags().String("config", constants.ConfigFilename, "")
cmd.Flags().Bool("generate-config", false, "") cmd.Flags().Bool("generate-config", false, "")
cmd.Flags().String("kubernetes", semver.MajorMinor(config.Default().KubernetesVersion), "") cmd.Flags().String("kubernetes", semver.MajorMinor(config.DefaultWithPanic().KubernetesVersion), "")
cmd.Flags().Bool("yes", false, "") cmd.Flags().Bool("yes", false, "")
cmd.Flags().String("name", "constell", "") cmd.Flags().String("name", "constell", "")
cmd.Flags().String("tf-log", "NONE", "") cmd.Flags().String("tf-log", "NONE", "")
@ -554,7 +554,7 @@ func TestIAMCreateAzure(t *testing.T) {
// register persistent flags manually // register persistent flags manually
cmd.Flags().String("config", constants.ConfigFilename, "") cmd.Flags().String("config", constants.ConfigFilename, "")
cmd.Flags().Bool("generate-config", false, "") cmd.Flags().Bool("generate-config", false, "")
cmd.Flags().String("kubernetes", semver.MajorMinor(config.Default().KubernetesVersion), "") cmd.Flags().String("kubernetes", semver.MajorMinor(config.DefaultWithPanic().KubernetesVersion), "")
cmd.Flags().Bool("yes", false, "") cmd.Flags().Bool("yes", false, "")
cmd.Flags().String("name", "constell", "") cmd.Flags().String("name", "constell", "")
cmd.Flags().String("tf-log", "NONE", "") cmd.Flags().String("tf-log", "NONE", "")
@ -861,7 +861,7 @@ func TestIAMCreateGCP(t *testing.T) {
// register persistent flags manually // register persistent flags manually
cmd.Flags().String("config", constants.ConfigFilename, "") cmd.Flags().String("config", constants.ConfigFilename, "")
cmd.Flags().Bool("generate-config", false, "") cmd.Flags().Bool("generate-config", false, "")
cmd.Flags().String("kubernetes", semver.MajorMinor(config.Default().KubernetesVersion), "") cmd.Flags().String("kubernetes", semver.MajorMinor(config.DefaultWithPanic().KubernetesVersion), "")
cmd.Flags().Bool("yes", false, "") cmd.Flags().Bool("yes", false, "")
cmd.Flags().String("name", "constell", "") cmd.Flags().String("name", "constell", "")
cmd.Flags().String("tf-log", "NONE", "") cmd.Flags().String("tf-log", "NONE", "")

View file

@ -156,7 +156,7 @@ func TestInitialize(t *testing.T) {
// File system preparation // File system preparation
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
config := defaultConfigWithExpectedMeasurements(t, config.Default(), tc.provider) config := defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), tc.provider)
if tc.configMutator != nil { if tc.configMutator != nil {
tc.configMutator(config) tc.configMutator(config)
} }
@ -427,7 +427,7 @@ func TestAttestation(t *testing.T) {
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
require.NoError(fileHandler.WriteJSON(constants.ClusterIDsFileName, existingIDFile, file.OptNone)) require.NoError(fileHandler.WriteJSON(constants.ClusterIDsFileName, existingIDFile, file.OptNone))
cfg := config.Default() cfg := config.DefaultWithPanic()
cfg.Image = "image" cfg.Image = "image"
cfg.RemoveProviderAndAttestationExcept(cloudprovider.QEMU) cfg.RemoveProviderAndAttestationExcept(cloudprovider.QEMU)
cfg.Attestation.QEMUVTPM.Measurements[0] = measurements.WithAllBytes(0x00, measurements.Enforce, measurements.PCRMeasurementLength) cfg.Attestation.QEMUVTPM.Measurements[0] = measurements.WithAllBytes(0x00, measurements.Enforce, measurements.PCRMeasurementLength)

View file

@ -214,7 +214,10 @@ func (m *miniUpCmd) prepareConfig(cmd *cobra.Command, fileHandler file.Handler,
} }
} }
config := config.Default() config, err := config.Default()
if err != nil {
return nil, err
}
config.Name = constants.MiniConstellationUID config.Name = constants.MiniConstellationUID
config.RemoveProviderAndAttestationExcept(cloudprovider.QEMU) config.RemoveProviderAndAttestationExcept(cloudprovider.QEMU)
config.StateDiskSizeGB = 8 config.StateDiskSizeGB = 8

View file

@ -153,7 +153,7 @@ func TestRecover(t *testing.T) {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
config := defaultConfigWithExpectedMeasurements(t, config.Default(), cloudprovider.GCP) config := defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), cloudprovider.GCP)
require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, config)) require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, config))
require.NoError(fileHandler.WriteJSON( require.NoError(fileHandler.WriteJSON(

View file

@ -30,6 +30,8 @@ import (
func TestUpgradeApply(t *testing.T) { func TestUpgradeApply(t *testing.T) {
someErr := errors.New("some error") someErr := errors.New("some error")
azureSEVSNP, err := config.DefaultForAzureSEVSNP()
require.NoError(t, err)
testCases := map[string]struct { testCases := map[string]struct {
upgrader stubUpgrader upgrader stubUpgrader
fetcher stubImageFetcher fetcher stubImageFetcher
@ -38,12 +40,12 @@ func TestUpgradeApply(t *testing.T) {
stdin string stdin string
}{ }{
"success": { "success": {
upgrader: stubUpgrader{currentConfig: config.DefaultForAzureSEVSNP()}, upgrader: stubUpgrader{currentConfig: azureSEVSNP},
yesFlag: true, yesFlag: true,
}, },
"nodeVersion some error": { "nodeVersion some error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
nodeVersionErr: someErr, nodeVersionErr: someErr,
}, },
wantErr: true, wantErr: true,
@ -51,14 +53,14 @@ func TestUpgradeApply(t *testing.T) {
}, },
"nodeVersion in progress error": { "nodeVersion in progress error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
nodeVersionErr: kubernetes.ErrInProgress, nodeVersionErr: kubernetes.ErrInProgress,
}, },
yesFlag: true, yesFlag: true,
}, },
"helm other error": { "helm other error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
helmErr: someErr, helmErr: someErr,
}, },
wantErr: true, wantErr: true,
@ -67,7 +69,7 @@ func TestUpgradeApply(t *testing.T) {
}, },
"check terraform error": { "check terraform error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
checkTerraformErr: someErr, checkTerraformErr: someErr,
}, },
fetcher: stubImageFetcher{}, fetcher: stubImageFetcher{},
@ -76,7 +78,7 @@ func TestUpgradeApply(t *testing.T) {
}, },
"abort": { "abort": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
terraformDiff: true, terraformDiff: true,
}, },
fetcher: stubImageFetcher{}, fetcher: stubImageFetcher{},
@ -85,7 +87,7 @@ func TestUpgradeApply(t *testing.T) {
}, },
"clean terraform error": { "clean terraform error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
cleanTerraformErr: someErr, cleanTerraformErr: someErr,
terraformDiff: true, terraformDiff: true,
}, },
@ -95,7 +97,7 @@ func TestUpgradeApply(t *testing.T) {
}, },
"plan terraform error": { "plan terraform error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
planTerraformErr: someErr, planTerraformErr: someErr,
}, },
fetcher: stubImageFetcher{}, fetcher: stubImageFetcher{},
@ -104,7 +106,7 @@ func TestUpgradeApply(t *testing.T) {
}, },
"apply terraform error": { "apply terraform error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
applyTerraformErr: someErr, applyTerraformErr: someErr,
terraformDiff: true, terraformDiff: true,
}, },
@ -114,7 +116,7 @@ func TestUpgradeApply(t *testing.T) {
}, },
"fetch reference error": { "fetch reference error": {
upgrader: stubUpgrader{ upgrader: stubUpgrader{
currentConfig: config.DefaultForAzureSEVSNP(), currentConfig: azureSEVSNP,
}, },
fetcher: stubImageFetcher{fetchReferenceErr: someErr}, fetcher: stubImageFetcher{fetchReferenceErr: someErr},
wantErr: true, wantErr: true,
@ -138,7 +140,7 @@ func TestUpgradeApply(t *testing.T) {
} }
handler := file.NewHandler(afero.NewMemMapFs()) handler := file.NewHandler(afero.NewMemMapFs())
cfg := defaultConfigWithExpectedMeasurements(t, config.Default(), cloudprovider.Azure) cfg := defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), cloudprovider.Azure)
require.NoError(handler.WriteYAML(constants.ConfigFilename, cfg)) require.NoError(handler.WriteYAML(constants.ConfigFilename, cfg))
require.NoError(handler.WriteJSON(constants.ClusterIDsFileName, clusterid.File{})) require.NoError(handler.WriteJSON(constants.ClusterIDsFileName, clusterid.File{}))

View file

@ -261,7 +261,7 @@ func TestUpgradeCheck(t *testing.T) {
require := require.New(t) require := require.New(t)
fileHandler := file.NewHandler(afero.NewMemMapFs()) fileHandler := file.NewHandler(afero.NewMemMapFs())
cfg := defaultConfigWithExpectedMeasurements(t, config.Default(), tc.csp) cfg := defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), tc.csp)
require.NoError(fileHandler.WriteYAML(tc.flags.configPath, cfg)) require.NoError(fileHandler.WriteYAML(tc.flags.configPath, cfg))
checkCmd := upgradeCheckCmd{ checkCmd := upgradeCheckCmd{

View file

@ -183,7 +183,7 @@ func TestVerify(t *testing.T) {
} }
fileHandler := file.NewHandler(afero.NewMemMapFs()) fileHandler := file.NewHandler(afero.NewMemMapFs())
config := defaultConfigWithExpectedMeasurements(t, config.Default(), tc.provider) config := defaultConfigWithExpectedMeasurements(t, config.DefaultWithPanic(), tc.provider)
require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, config)) require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, config))
if tc.idFile != nil { if tc.idFile != nil {
require.NoError(fileHandler.WriteJSON(constants.ClusterIDsFileName, tc.idFile, file.OptNone)) require.NoError(fileHandler.WriteJSON(constants.ClusterIDsFileName, tc.idFile, file.OptNone))

View file

@ -88,7 +88,7 @@ func TestUpgradeRelease(t *testing.T) {
chart, err := loadChartsDir(helmFS, certManagerInfo.path) chart, err := loadChartsDir(helmFS, certManagerInfo.path)
require.NoError(err) require.NoError(err)
err = client.upgradeRelease(context.Background(), 0, config.Default(), chart, tc.allowDestructive) err = client.upgradeRelease(context.Background(), 0, config.DefaultWithPanic(), chart, tc.allowDestructive)
if tc.wantError { if tc.wantError {
tc.assertCorrectError(t, err) tc.assertCorrectError(t, err)
return return

View file

@ -46,7 +46,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}{ }{
"success": { "success": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.2.3" conf.Image = "v1.2.3"
conf.KubernetesVersion = versions.SupportedK8sVersions()[1] conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
return conf return conf
@ -62,7 +62,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}, },
"only k8s upgrade": { "only k8s upgrade": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.2.2" conf.Image = "v1.2.2"
conf.KubernetesVersion = versions.SupportedK8sVersions()[1] conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
return conf return conf
@ -83,7 +83,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}, },
"only image upgrade": { "only image upgrade": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.2.3" conf.Image = "v1.2.3"
conf.KubernetesVersion = versions.SupportedK8sVersions()[0] conf.KubernetesVersion = versions.SupportedK8sVersions()[0]
return conf return conf
@ -104,7 +104,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}, },
"not an upgrade": { "not an upgrade": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.2.2" conf.Image = "v1.2.2"
conf.KubernetesVersion = versions.SupportedK8sVersions()[0] conf.KubernetesVersion = versions.SupportedK8sVersions()[0]
return conf return conf
@ -120,7 +120,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}, },
"upgrade in progress": { "upgrade in progress": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.2.3" conf.Image = "v1.2.3"
conf.KubernetesVersion = versions.SupportedK8sVersions()[1] conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
return conf return conf
@ -139,7 +139,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}, },
"get error": { "get error": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.2.3" conf.Image = "v1.2.3"
return conf return conf
}(), }(),
@ -151,7 +151,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}, },
"image too new valid k8s": { "image too new valid k8s": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.4.2" conf.Image = "v1.4.2"
conf.KubernetesVersion = versions.SupportedK8sVersions()[1] conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
return conf return conf
@ -173,7 +173,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}, },
"apply returns bad object": { "apply returns bad object": {
conf: func() *config.Config { conf: func() *config.Config {
conf := config.Default() conf := config.DefaultWithPanic()
conf.Image = "v1.2.3" conf.Image = "v1.2.3"
conf.KubernetesVersion = versions.SupportedK8sVersions()[1] conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
return conf return conf

View file

@ -213,7 +213,7 @@ func TestTrustedKeyFromSNP(t *testing.T) {
}, },
} }
cfg := config.DefaultForAzureSEVSNP() cfg, err := config.DefaultForAzureSEVSNP()
cfg.FirmwareSignerConfig = config.SNPFirmwareSignerConfig{ cfg.FirmwareSignerConfig = config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: tc.idkeydigests, AcceptedKeyDigests: tc.idkeydigests,
EnforcementPolicy: tc.enforceIDKeyDigest, EnforcementPolicy: tc.enforceIDKeyDigest,
@ -348,7 +348,10 @@ func TestNewSNPReportFromBytes(t *testing.T) {
wantErr: true, wantErr: true,
}, },
} }
cfg, err := config.DefaultForAzureSEVSNP()
if err != nil {
t.Fatal(err)
}
for name, tc := range testCases { for name, tc := range testCases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
@ -363,7 +366,6 @@ func TestNewSNPReportFromBytes(t *testing.T) {
assert.NotNil(report) assert.NotNil(report)
assert.Equal(hex.EncodeToString(report.IDKeyDigest[:]), "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1") assert.Equal(hex.EncodeToString(report.IDKeyDigest[:]), "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1")
// This is a canary for us: If this fails in the future we possibly downgraded a SVN. // This is a canary for us: If this fails in the future we possibly downgraded a SVN.
cfg := config.DefaultForAzureSEVSNP()
assert.True(report.LaunchTCB.isVersion(cfg.BootloaderVersion, cfg.TEEVersion, cfg.SNPVersion, cfg.MicrocodeVersion)) assert.True(report.LaunchTCB.isVersion(cfg.BootloaderVersion, cfg.TEEVersion, cfg.SNPVersion, cfg.MicrocodeVersion))
} }
}) })

View file

@ -39,7 +39,10 @@ import (
// TODO(v2.8 | AB#3130): Update tool to use variant.Variant instead of cloudprovider.Provider // TODO(v2.8 | AB#3130): Update tool to use variant.Variant instead of cloudprovider.Provider
func main() { func main() {
defaultConf := config.Default() defaultConf, err := config.Default()
if err != nil {
log.Fatal(err)
}
log.Printf("Generating measurements for %s\n", defaultConf.Image) log.Printf("Generating measurements for %s\n", defaultConf.Image)
const filePath = "./measurements_enterprise.go" const filePath = "./measurements_enterprise.go"

View file

@ -0,0 +1,29 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "attestationapi",
srcs = ["attestationapi.go"],
importpath = "github.com/edgelesssys/constellation/v2/internal/attestationapi",
visibility = ["//:__subpackages__"],
deps = [
"//internal/kms/storage",
"//internal/kms/storage/awss3",
"//internal/kms/uri",
"//internal/variant",
"//internal/versionsapi",
"//internal/versionsapi/fetcher",
],
)
go_test(
name = "attestationapi_test",
srcs = ["attestationapi_test.go"],
deps = [
":attestationapi",
"//internal/kms/uri",
"//internal/variant",
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
],
)

View file

@ -0,0 +1,149 @@
package attestationapi
import (
"context"
"encoding/json"
"errors"
"fmt"
"path"
"sort"
"time"
"github.com/edgelesssys/constellation/v2/internal/kms/storage"
"github.com/edgelesssys/constellation/v2/internal/kms/storage/awss3"
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/versionsapi/fetcher"
)
const (
Bootloader Type = "bootloader" // Bootloader is the version of the Azure SEVSNP bootloader.
TEE Type = "tee" // TEE is the version of the Azure SEVSNP TEE.
SNP Type = "snp" // SNP is the version of the Azure SEVSNP SNP.
Microcode Type = "microcode" // Microcode is the version of the Azure SEVSNP microcode.
)
// AttestationPath is the path to the attestation versions.
const AttestationPath = "constellation/v1/attestation"
// AzureSEVSNP is the latest version of each component of the Azure SEVSNP.
// used for testing only
var AzureSEVSNP = versionsapi.AzureSEVSNPVersion{
Bootloader: 2,
TEE: 0,
SNP: 6,
Microcode: 93,
}
// Type is the type of the version to be requested.
type Type (string)
// AttestationVersionRepo manages (modifies) the version information for the attestation variants.
type AttestationVersionRepo struct {
*awss3.Storage
}
// NewAttestationVersionRepo returns a new AttestationVersionRepo.
func NewAttestationVersionRepo(ctx context.Context, cfg uri.AWSS3Config) (*AttestationVersionRepo, error) {
s3, err := awss3.New(ctx, cfg)
if err != nil {
return nil, fmt.Errorf("failed to create s3 storage: %w", err)
}
return &AttestationVersionRepo{s3}, nil
}
// UploadAzureSEVSNP uploads the latest version numbers of the Azure SEVSNP.
func (a AttestationVersionRepo) UploadAzureSEVSNP(ctx context.Context, versions versionsapi.AzureSEVSNPVersion, date time.Time) error {
bt, err := json.Marshal(versions)
if err != nil {
return err
}
variant := variant.AzureSEVSNP{}
fname := date.Format("2006-01-02-15-04") + ".json"
err = a.Put(ctx, fmt.Sprintf("%s/%s/%s", AttestationPath, variant.String(), fname), bt)
if err != nil {
return err
}
return a.addVersionToList(ctx, variant, fname)
}
func (a AttestationVersionRepo) addVersionToList(ctx context.Context, attestation variant.Variant, fname string) error {
versions := []string{}
key := path.Join(AttestationPath, attestation.String(), "list")
bt, err := a.Get(ctx, key)
if err == nil {
if err := json.Unmarshal(bt, &versions); err != nil {
return err
}
} else if !errors.Is(err, storage.ErrDEKUnset) {
return err
}
versions = append(versions, fname)
versions = variant.RemoveDuplicate(versions)
sort.Sort(sort.Reverse(sort.StringSlice(versions)))
json, err := json.Marshal(versions)
if err != nil {
return err
}
return a.Put(ctx, key, json)
}
// List returns the list of versions for the given attestation type.
func (a AttestationVersionRepo) List(ctx context.Context, attestation variant.Variant) ([]string, error) {
key := path.Join(AttestationPath, attestation.String(), "list")
bt, err := a.Get(ctx, key)
if err != nil {
return nil, err
}
var versions []string
if err := json.Unmarshal(bt, &versions); err != nil {
return nil, err
}
return versions, nil
}
// DeleteList empties the list of versions for the given attestation type.
func (a AttestationVersionRepo) DeleteList(ctx context.Context, attestation variant.Variant) error {
versions := []string{}
bt, err := json.Marshal(&versions)
if err != nil {
return err
}
return a.Put(ctx, path.Join(AttestationPath, attestation.String(), "list"), bt)
}
func GetVersionByType(res versionsapi.AzureSEVSNPVersion, t Type) uint8 {
switch t {
case Bootloader:
return res.Bootloader
case TEE:
return res.TEE
case SNP:
return res.SNP
case Microcode:
return res.Microcode
default:
return 1
}
}
// GetAzureSEVSNPVersion returns the requested version of the given type.
func GetAzureSEVSNPVersion(ctx context.Context) (res versionsapi.AzureSEVSNPVersion, err error) {
var versions versionsapi.AzureSEVSNPVersionList
fetcher := fetcher.NewFetcher()
versions, err = fetcher.FetchAttestationList(ctx, versions)
if err != nil {
return res, fmt.Errorf("failed fetching versions list: %w", err)
}
if len(versions) < 1 {
return res, errors.New("no versions found in /list")
}
get := versionsapi.AzureSEVSNPVersionGet{Version: versions[0]} // get latest version (as sorted reversely alphanumerically)
get, err = fetcher.FetchAttestationVersion(ctx, get)
if err != nil {
return res, fmt.Errorf("failed fetching version: %w", err)
}
return get.AzureSEVSNPVersion, nil
}

View file

@ -0,0 +1,77 @@
package attestationapi_test
import (
"context"
"flag"
"os"
"testing"
"time"
"github.com/edgelesssys/constellation/v2/internal/attestationapi"
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
awsRegion = flag.String("aws-region", "us-east-1", "Region to use for AWS tests. Required for AWS KMS test.")
awsAccessKeyID = flag.String("aws-access-key-id", "", "ID of the Access key to use for AWS tests. Required for AWS KMS and storage test.")
awsAccessKey = flag.String("aws-access-key", "", "Access key to use for AWS tests. Required for AWS KMS and storage test.")
awsBucket = flag.String("aws-bucket", "", "Name of the S3 bucket to use for AWS storage test. Required for AWS storage test.")
)
func TestMain(m *testing.M) {
flag.Parse()
if *awsAccessKey == "" || *awsAccessKeyID == "" || *awsBucket == "" || *awsRegion == "" {
flag.Usage()
panic("Required flags not set: --aws-access-key, --aws-access-key-id, --aws-bucket, --aws-region")
}
os.Exit(m.Run())
}
var cfg = uri.AWSS3Config{
Bucket: *awsBucket,
AccessKeyID: *awsAccessKeyID,
AccessKey: *awsAccessKey,
Region: *awsRegion,
}
func TestUploadAzureSEVSNPVersions(t *testing.T) {
ctx := context.Background()
sut, err := attestationapi.NewAttestationVersionRepo(ctx, cfg)
require.NoError(t, err)
d := time.Date(2021, 1, 1, 1, 1, 1, 1, time.UTC)
require.NoError(t, sut.UploadAzureSEVSNP(ctx, attestationapi.AzureSEVSNP, d))
}
func TestListVersions(t *testing.T) {
ctx := context.Background()
sut, err := attestationapi.NewAttestationVersionRepo(ctx, cfg)
require.NoError(t, err)
err = sut.DeleteList(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
res, err := sut.List(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
require.Equal(t, []string{}, res)
d := time.Date(2021, 1, 1, 1, 1, 1, 1, time.UTC)
err = sut.UploadAzureSEVSNP(ctx, attestationapi.AzureSEVSNP, d)
require.NoError(t, err)
res, err = sut.List(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
require.Equal(t, []string{"2021-01-01-01-01.json"}, res)
err = sut.DeleteList(ctx, variant.AzureSEVSNP{})
require.NoError(t, err)
}
func TestGetVersion(t *testing.T) {
ctx := context.Background()
res, err := attestationapi.GetAzureSEVSNPVersion(ctx)
require.NoError(t, err)
assert.Equal(t, uint8(2), res.Bootloader)
}

View file

@ -20,6 +20,7 @@ go_library(
deps = [ deps = [
"//internal/attestation/idkeydigest", "//internal/attestation/idkeydigest",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/attestationapi",
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/compatibility", "//internal/compatibility",
"//internal/config/imageversion", "//internal/config/imageversion",

View file

@ -23,6 +23,8 @@ import (
var testCertPEM = `-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n` var testCertPEM = `-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n`
func TestUnmarshalAttestationConfig(t *testing.T) { func TestUnmarshalAttestationConfig(t *testing.T) {
azureSEVSNP, err := DefaultForAzureSEVSNP()
require.NoError(t, err)
testCases := map[string]struct { testCases := map[string]struct {
cfg AttestationCfg cfg AttestationCfg
}{ }{
@ -30,7 +32,7 @@ func TestUnmarshalAttestationConfig(t *testing.T) {
cfg: &AWSNitroTPM{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSNitroTPM{})}, cfg: &AWSNitroTPM{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSNitroTPM{})},
}, },
"AzureSEVSNP": { "AzureSEVSNP": {
cfg: DefaultForAzureSEVSNP(), cfg: azureSEVSNP,
}, },
"AzureTrustedLaunch": { "AzureTrustedLaunch": {
cfg: &AzureTrustedLaunch{Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTrustedLaunch{})}, cfg: &AzureTrustedLaunch{Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTrustedLaunch{})},

View file

@ -8,16 +8,19 @@ package config
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestationapi"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config/snpversion" "github.com/edgelesssys/constellation/v2/internal/config/snpversion"
"github.com/edgelesssys/constellation/v2/internal/config/version" "github.com/edgelesssys/constellation/v2/internal/config/version"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
) )
// AzureSEVSNP is the configuration for Azure SEV-SNP attestation. // AzureSEVSNP is the configuration for Azure SEV-SNP attestation.
@ -47,20 +50,26 @@ type AzureSEVSNP struct {
// DefaultForAzureSEVSNP returns the default configuration for Azure SEV-SNP attestation. // DefaultForAzureSEVSNP returns the default configuration for Azure SEV-SNP attestation.
// Version numbers are hard coded and should be updated with each new release. // Version numbers are hard coded and should be updated with each new release.
func DefaultForAzureSEVSNP() *AzureSEVSNP { func DefaultForAzureSEVSNP() (*AzureSEVSNP, error) {
ctx := context.Background()
version, err := attestationapi.GetAzureSEVSNPVersion(ctx)
if err != nil {
return nil, err
}
return &AzureSEVSNP{ return &AzureSEVSNP{
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}), Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}),
BootloaderVersion: snpversion.GetLatest(snpversion.Bootloader), BootloaderVersion: version.Bootloader,
TEEVersion: snpversion.GetLatest(snpversion.TEE), TEEVersion: version.TEE,
SNPVersion: snpversion.GetLatest(snpversion.SNP), SNPVersion: version.SNP,
MicrocodeVersion: snpversion.GetLatest(snpversion.Microcode), MicrocodeVersion: version.Microcode,
FirmwareSignerConfig: SNPFirmwareSignerConfig{ FirmwareSignerConfig: SNPFirmwareSignerConfig{
AcceptedKeyDigests: idkeydigest.DefaultList(), AcceptedKeyDigests: idkeydigest.DefaultList(),
EnforcementPolicy: idkeydigest.MAAFallback, EnforcementPolicy: idkeydigest.MAAFallback,
}, },
// AMD root key. Received from the AMD Key Distribution System API (KDS). // AMD root key. Received from the AMD Key Distribution System API (KDS).
AMDRootKey: mustParsePEM(`-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n`), AMDRootKey: mustParsePEM(`-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n`),
} }, nil
} }
// GetVariant returns azure-sev-snp as the variant. // GetVariant returns azure-sev-snp as the variant.
@ -97,25 +106,49 @@ func (c AzureSEVSNP) EqualTo(old AttestationCfg) (bool, error) {
} }
// UnmarshalYAML implements a custom unmarshaler to support setting "latest" as version. // UnmarshalYAML implements a custom unmarshaler to support setting "latest" as version.
func (c *AzureSEVSNP) UnmarshalYAML(unmarshal func(any) error) error { func (a *AzureSEVSNP) UnmarshalYAML(unmarshal func(interface{}) error) error {
aux := &fusedAzureSEVSNP{ aux := &fusedAzureSEVSNP{
auxAzureSEVSNP: (*auxAzureSEVSNP)(c), auxAzureSEVSNP: (*auxAzureSEVSNP)(a),
} }
if err := unmarshal(aux); err != nil { if err := unmarshal(aux); err != nil {
return fmt.Errorf("unmarshal AzureSEVSNP: %w", err) return fmt.Errorf("unmarshal AzureSEVSNP: %w", err)
} }
c = (*AzureSEVSNP)(aux.auxAzureSEVSNP) a = (*AzureSEVSNP)(aux.auxAzureSEVSNP)
for _, versionType := range []snpversion.Type{snpversion.Bootloader, snpversion.TEE, snpversion.SNP, snpversion.Microcode} { versions, err := attestationapi.GetAzureSEVSNPVersion(context.Background())
if !convertLatestToNumber(c, versionType, aux) { if err != nil {
if err := convertStringToUint(c, versionType, aux); err != nil { return fmt.Errorf("failed to get AzureSEVSNP versions: %w", err)
return fmt.Errorf("convert %s version to number: %w", versionType, err) }
for _, versionType := range []attestationapi.Type{attestationapi.Bootloader, attestationapi.TEE, attestationapi.SNP, attestationapi.Microcode} {
if !convertLatestToNumber(a, versions, versionType, aux) {
if err := convertStringToUint(a, versionType, aux); err != nil {
return fmt.Errorf("failed to convert %s version to number: %w", versionType, err)
} }
} }
} }
return nil return nil
} }
func getUintAndStringPtrToVersion(c *AzureSEVSNP, versionType attestationapi.Type, aux *fusedAzureSEVSNP) (*uint8, *string) {
var v *uint8
var stringV *string
switch versionType {
case attestationapi.Bootloader:
v = &c.BootloaderVersion
stringV = &aux.BootloaderVersion
case attestationapi.TEE:
v = &c.TEEVersion
stringV = &aux.TEEVersion
case attestationapi.SNP:
v = &c.SNPVersion
stringV = &aux.SNPVersion
case attestationapi.Microcode:
v = &c.MicrocodeVersion
stringV = &aux.MicrocodeVersion
}
return v, stringV
}
// AzureTrustedLaunch is the configuration for Azure Trusted Launch attestation. // AzureTrustedLaunch is the configuration for Azure Trusted Launch attestation.
type AzureTrustedLaunch struct { type AzureTrustedLaunch struct {
// description: | // description: |
@ -180,13 +213,13 @@ type fusedAzureSEVSNP struct {
// Lowest acceptable bootloader version. // Lowest acceptable bootloader version.
BootloaderVersion string `yaml:"bootloaderVersion"` BootloaderVersion string `yaml:"bootloaderVersion"`
// description: | // description: |
// Lowest acceptable bootloader version. // Lowest acceptable TEE version.
TEEVersion string `yaml:"teeVersion"` TEEVersion string `yaml:"teeVersion"`
// description: | // description: |
// Lowest acceptable bootloader version. // Lowest acceptable SEV-SNP version.
SNPVersion string `yaml:"snpVersion"` SNPVersion string `yaml:"snpVersion"`
// description: | // description: |
// Lowest acceptable bootloader version. // Lowest acceptable microcode version.
MicrocodeVersion string `yaml:"microcodeVersion"` MicrocodeVersion string `yaml:"microcodeVersion"`
} }
@ -201,29 +234,11 @@ func convertStringToUint(c *AzureSEVSNP, versionType snpversion.Type, aux *fused
return nil return nil
} }
func convertLatestToNumber(c *AzureSEVSNP, versionType snpversion.Type, aux *fusedAzureSEVSNP) bool { func convertLatestToNumber(c *AzureSEVSNP, versions versionsapi.AzureSEVSNPVersion, versionType version.Type, aux *fusedAzureSEVSNP) bool {
v, stringV := getUintAndStringPtrToVersion(c, versionType, aux) v, stringV := getUintAndStringPtrToVersion(c, versionType, aux)
if strings.ToLower(*stringV) == "latest" { if strings.ToLower(*stringV) == "latest" {
*v = snpversion.GetLatest(versionType) *v = attestationapi.GetVersionByType(versions, versionType)
return true return true
} }
return false return false
} }
func getUintAndStringPtrToVersion(c *AzureSEVSNP, versionType version.Type, aux *fusedAzureSEVSNP) (versionUint *uint8, versionString *string) {
switch versionType {
case version.Bootloader:
versionUint = &c.BootloaderVersion
versionString = &aux.BootloaderVersion
case version.TEE:
versionUint = &c.TEEVersion
versionString = &aux.TEEVersion
case version.SNP:
versionUint = &c.SNPVersion
versionString = &aux.SNPVersion
case version.Microcode:
versionUint = &c.MicrocodeVersion
versionString = &aux.MicrocodeVersion
}
return
}

View file

@ -297,7 +297,11 @@ type AttestationConfig struct {
} }
// Default returns a struct with the default config. // Default returns a struct with the default config.
func Default() *Config { func Default() (*Config, error) {
azureSEVSNP, err := DefaultForAzureSEVSNP()
if err != nil {
return nil, err
}
return &Config{ return &Config{
Version: Version3, Version: Version3,
Image: defaultImage, Image: defaultImage,
@ -357,12 +361,21 @@ func Default() *Config {
// AWS will have aws-sev-snp as attestation variant // AWS will have aws-sev-snp as attestation variant
Attestation: AttestationConfig{ Attestation: AttestationConfig{
AWSNitroTPM: &AWSNitroTPM{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSNitroTPM{})}, AWSNitroTPM: &AWSNitroTPM{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSNitroTPM{})},
AzureSEVSNP: DefaultForAzureSEVSNP(), AzureSEVSNP: azureSEVSNP,
AzureTrustedLaunch: &AzureTrustedLaunch{Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTrustedLaunch{})}, AzureTrustedLaunch: &AzureTrustedLaunch{Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTrustedLaunch{})},
GCPSEVES: &GCPSEVES{Measurements: measurements.DefaultsFor(cloudprovider.GCP, variant.GCPSEVES{})}, GCPSEVES: &GCPSEVES{Measurements: measurements.DefaultsFor(cloudprovider.GCP, variant.GCPSEVES{})},
QEMUVTPM: &QEMUVTPM{Measurements: measurements.DefaultsFor(cloudprovider.QEMU, variant.QEMUVTPM{})}, QEMUVTPM: &QEMUVTPM{Measurements: measurements.DefaultsFor(cloudprovider.QEMU, variant.QEMUVTPM{})},
}, },
}, nil
}
// DefaultWithPanic returns a struct with the default config.
func DefaultWithPanic() *Config {
conf, err := Default()
if err != nil {
panic(err)
} }
return conf
} }
// fromFile returns config file with `name` read from `fileHandler` by parsing // fromFile returns config file with `name` read from `fileHandler` by parsing
@ -404,7 +417,11 @@ func New(fileHandler file.Handler, name string, force bool) (*Config, error) {
// Backwards compatibility: configs without the field `microserviceVersion` are valid in version 2.6. // Backwards compatibility: configs without the field `microserviceVersion` are valid in version 2.6.
// In case the field is not set in an old config we prefill it with the default value. // In case the field is not set in an old config we prefill it with the default value.
if c.MicroserviceVersion == "" { if c.MicroserviceVersion == "" {
c.MicroserviceVersion = Default().MicroserviceVersion azureSEVSNP, err := Default()
if err != nil {
return nil, err
}
c.MicroserviceVersion = azureSEVSNP.MicroserviceVersion
} }
return c, c.Validate(force) return c, c.Validate(force)

View file

@ -33,7 +33,7 @@ func TestMain(m *testing.M) {
func TestDefaultConfig(t *testing.T) { func TestDefaultConfig(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
def := Default() def := DefaultWithPanic()
assert.NotNil(def) assert.NotNil(def)
} }
@ -46,11 +46,11 @@ func TestSettingLatestAsVersion(t *testing.T) {
}{ }{
"mix of latest and uint as version value": { "mix of latest and uint as version value": {
config: func() map[string]interface{} { config: func() map[string]interface{} {
conf := Default() conf := DefaultWithPanic()
// modify versions as string // modify versions as string
m := getConfigAsMap(conf, t) m := getConfigAsMap(conf, t)
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["microcodeVersion"] = "latest" m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["microcodeVersion"] = "latest"
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["teeVersion"] = "latest" m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["teeVersion"] = "Latest"
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["snpVersion"] = "latest" m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["snpVersion"] = "latest"
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["bootloaderVersion"] = 1 m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["bootloaderVersion"] = 1
return m return m
@ -58,14 +58,15 @@ func TestSettingLatestAsVersion(t *testing.T) {
configName: constants.ConfigFilename, configName: constants.ConfigFilename,
wantResult: func() *Config { wantResult: func() *Config {
conf := Default() conf := DefaultWithPanic()
conf.Attestation.AzureSEVSNP.BootloaderVersion = 1 conf.Attestation.AzureSEVSNP.BootloaderVersion = 1
conf.Attestation.AzureSEVSNP.MicrocodeVersion = 93
return conf return conf
}(), }(),
}, },
"refuse invalid version value": { "refuse invalid version value": {
config: func() map[string]interface{} { config: func() map[string]interface{} {
conf := Default() conf := DefaultWithPanic()
m := getConfigAsMap(conf, t) m := getConfigAsMap(conf, t)
m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["microcodeVersion"] = "1a" m["attestation"].(map[string]interface{})["azureSEVSNP"].(map[string]interface{})["microcodeVersion"] = "1a"
return m return m
@ -115,14 +116,14 @@ func TestFromFile(t *testing.T) {
wantErr bool wantErr bool
}{ }{
"default config from default file": { "default config from default file": {
config: Default(), config: DefaultWithPanic(),
configName: constants.ConfigFilename, configName: constants.ConfigFilename,
wantResult: Default(), wantResult: DefaultWithPanic(),
}, },
"default config from different path": { "default config from different path": {
config: Default(), config: DefaultWithPanic(),
configName: "other-config.yaml", configName: "other-config.yaml",
wantResult: Default(), wantResult: DefaultWithPanic(),
}, },
"default config when path empty": { "default config when path empty": {
config: nil, config: nil,
@ -145,14 +146,14 @@ func TestFromFile(t *testing.T) {
}, },
"modify default config": { "modify default config": {
config: func() *Config { config: func() *Config {
conf := Default() conf := DefaultWithPanic()
conf.Provider.GCP.Region = "eu-north1" conf.Provider.GCP.Region = "eu-north1"
conf.Provider.GCP.Zone = "eu-north1-a" conf.Provider.GCP.Zone = "eu-north1-a"
return conf return conf
}(), }(),
configName: constants.ConfigFilename, configName: constants.ConfigFilename,
wantResult: func() *Config { wantResult: func() *Config {
conf := Default() conf := DefaultWithPanic()
conf.Provider.GCP.Region = "eu-north1" conf.Provider.GCP.Region = "eu-north1"
conf.Provider.GCP.Zone = "eu-north1-a" conf.Provider.GCP.Zone = "eu-north1-a"
return conf return conf
@ -191,7 +192,7 @@ func TestNewWithDefaultOptions(t *testing.T) {
}{ }{
"set env works": { "set env works": {
confToWrite: func() *Config { // valid config with all, but clientSecretValue confToWrite: func() *Config { // valid config with all, but clientSecretValue
c := Default() c := DefaultWithPanic()
c.RemoveProviderAndAttestationExcept(cloudprovider.Azure) c.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
c.Image = "v" + constants.VersionInfo() c.Image = "v" + constants.VersionInfo()
c.Provider.Azure.SubscriptionID = "f4278079-288c-4766-a98c-ab9d5dba01a5" c.Provider.Azure.SubscriptionID = "f4278079-288c-4766-a98c-ab9d5dba01a5"
@ -212,7 +213,7 @@ func TestNewWithDefaultOptions(t *testing.T) {
}, },
"set env overwrites": { "set env overwrites": {
confToWrite: func() *Config { confToWrite: func() *Config {
c := Default() c := DefaultWithPanic()
c.RemoveProviderAndAttestationExcept(cloudprovider.Azure) c.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
c.Image = "v" + constants.VersionInfo() c.Image = "v" + constants.VersionInfo()
c.Provider.Azure.SubscriptionID = "f4278079-288c-4766-a98c-ab9d5dba01a5" c.Provider.Azure.SubscriptionID = "f4278079-288c-4766-a98c-ab9d5dba01a5"
@ -276,13 +277,13 @@ func TestValidate(t *testing.T) {
wantErrCount int wantErrCount int
}{ }{
"default config is not valid": { "default config is not valid": {
cnf: Default(), cnf: DefaultWithPanic(),
wantErr: true, wantErr: true,
wantErrCount: defaultErrCount, wantErrCount: defaultErrCount,
}, },
"v0 is one error": { "v0 is one error": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.Version = "v0" cnf.Version = "v0"
return cnf return cnf
}(), }(),
@ -291,7 +292,7 @@ func TestValidate(t *testing.T) {
}, },
"v0 and negative state disk are two errors": { "v0 and negative state disk are two errors": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.Version = "v0" cnf.Version = "v0"
cnf.StateDiskSizeGB = -1 cnf.StateDiskSizeGB = -1
return cnf return cnf
@ -301,7 +302,7 @@ func TestValidate(t *testing.T) {
}, },
"default Azure config is not valid": { "default Azure config is not valid": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.RemoveProviderAndAttestationExcept(cloudprovider.Azure) cnf.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
return cnf return cnf
}(), }(),
@ -310,7 +311,7 @@ func TestValidate(t *testing.T) {
}, },
"Azure config with all required fields is valid": { "Azure config with all required fields is valid": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.RemoveProviderAndAttestationExcept(cloudprovider.Azure) cnf.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
cnf.Image = "v" + constants.VersionInfo() cnf.Image = "v" + constants.VersionInfo()
az := cnf.Provider.Azure az := cnf.Provider.Azure
@ -331,7 +332,7 @@ func TestValidate(t *testing.T) {
}, },
"default GCP config is not valid": { "default GCP config is not valid": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.RemoveProviderAndAttestationExcept(cloudprovider.GCP) cnf.RemoveProviderAndAttestationExcept(cloudprovider.GCP)
return cnf return cnf
}(), }(),
@ -340,7 +341,7 @@ func TestValidate(t *testing.T) {
}, },
"GCP config with all required fields is valid": { "GCP config with all required fields is valid": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.RemoveProviderAndAttestationExcept(cloudprovider.GCP) cnf.RemoveProviderAndAttestationExcept(cloudprovider.GCP)
cnf.Image = "v" + constants.VersionInfo() cnf.Image = "v" + constants.VersionInfo()
gcp := cnf.Provider.GCP gcp := cnf.Provider.GCP
@ -359,7 +360,7 @@ func TestValidate(t *testing.T) {
// TODO: v2.7: remove this test as it should start breaking after v2.6 is released. // TODO: v2.7: remove this test as it should start breaking after v2.6 is released.
"k8s vMAJOR.MINOR is valid in v2.7": { "k8s vMAJOR.MINOR is valid in v2.7": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.KubernetesVersion = "v1.25" cnf.KubernetesVersion = "v1.25"
return cnf return cnf
}(), }(),
@ -369,7 +370,7 @@ func TestValidate(t *testing.T) {
// TODO: v2.7: remove this test as it should start breaking after v2.6 is released. // TODO: v2.7: remove this test as it should start breaking after v2.6 is released.
"k8s MAJOR.MINOR is valid in v2.7": { "k8s MAJOR.MINOR is valid in v2.7": {
cnf: func() *Config { cnf: func() *Config {
cnf := Default() cnf := DefaultWithPanic()
cnf.KubernetesVersion = "1.25" cnf.KubernetesVersion = "1.25"
return cnf return cnf
}(), }(),
@ -403,9 +404,9 @@ func TestHasProvider(t *testing.T) {
assert.False((&Config{}).HasProvider(cloudprovider.Azure)) assert.False((&Config{}).HasProvider(cloudprovider.Azure))
assert.False((&Config{}).HasProvider(cloudprovider.GCP)) assert.False((&Config{}).HasProvider(cloudprovider.GCP))
assert.False((&Config{}).HasProvider(cloudprovider.QEMU)) assert.False((&Config{}).HasProvider(cloudprovider.QEMU))
assert.False(Default().HasProvider(cloudprovider.Unknown)) assert.False(DefaultWithPanic().HasProvider(cloudprovider.Unknown))
assert.True(Default().HasProvider(cloudprovider.Azure)) assert.True(DefaultWithPanic().HasProvider(cloudprovider.Azure))
assert.True(Default().HasProvider(cloudprovider.GCP)) assert.True(DefaultWithPanic().HasProvider(cloudprovider.GCP))
cnfWithAzure := Config{Provider: ProviderConfig{Azure: &AzureConfig{}}} cnfWithAzure := Config{Provider: ProviderConfig{Azure: &AzureConfig{}}}
assert.False(cnfWithAzure.HasProvider(cloudprovider.Unknown)) assert.False(cnfWithAzure.HasProvider(cloudprovider.Unknown))
assert.True(cnfWithAzure.HasProvider(cloudprovider.Azure)) assert.True(cnfWithAzure.HasProvider(cloudprovider.Azure))
@ -422,26 +423,26 @@ func TestConfigRemoveProviderExcept(t *testing.T) {
}{ }{
"except aws": { "except aws": {
removeExcept: cloudprovider.AWS, removeExcept: cloudprovider.AWS,
wantAWS: Default().Provider.AWS, wantAWS: DefaultWithPanic().Provider.AWS,
}, },
"except azure": { "except azure": {
removeExcept: cloudprovider.Azure, removeExcept: cloudprovider.Azure,
wantAzure: Default().Provider.Azure, wantAzure: DefaultWithPanic().Provider.Azure,
}, },
"except gcp": { "except gcp": {
removeExcept: cloudprovider.GCP, removeExcept: cloudprovider.GCP,
wantGCP: Default().Provider.GCP, wantGCP: DefaultWithPanic().Provider.GCP,
}, },
"except qemu": { "except qemu": {
removeExcept: cloudprovider.QEMU, removeExcept: cloudprovider.QEMU,
wantQEMU: Default().Provider.QEMU, wantQEMU: DefaultWithPanic().Provider.QEMU,
}, },
"unknown provider": { "unknown provider": {
removeExcept: cloudprovider.Unknown, removeExcept: cloudprovider.Unknown,
wantAWS: Default().Provider.AWS, wantAWS: DefaultWithPanic().Provider.AWS,
wantAzure: Default().Provider.Azure, wantAzure: DefaultWithPanic().Provider.Azure,
wantGCP: Default().Provider.GCP, wantGCP: DefaultWithPanic().Provider.GCP,
wantQEMU: Default().Provider.QEMU, wantQEMU: DefaultWithPanic().Provider.QEMU,
}, },
} }
@ -449,7 +450,7 @@ func TestConfigRemoveProviderExcept(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
conf := Default() conf := DefaultWithPanic()
conf.RemoveProviderAndAttestationExcept(tc.removeExcept) conf.RemoveProviderAndAttestationExcept(tc.removeExcept)
assert.Equal(tc.wantAWS, conf.Provider.AWS) assert.Equal(tc.wantAWS, conf.Provider.AWS)
@ -481,7 +482,7 @@ func TestConfig_UpdateMeasurements(t *testing.T) {
} }
{ // AWS { // AWS
conf := Default() conf := DefaultWithPanic()
conf.RemoveProviderAndAttestationExcept(cloudprovider.AWS) conf.RemoveProviderAndAttestationExcept(cloudprovider.AWS)
for k := range conf.Attestation.AWSNitroTPM.Measurements { for k := range conf.Attestation.AWSNitroTPM.Measurements {
delete(conf.Attestation.AWSNitroTPM.Measurements, k) delete(conf.Attestation.AWSNitroTPM.Measurements, k)
@ -490,7 +491,7 @@ func TestConfig_UpdateMeasurements(t *testing.T) {
assert.Equal(newMeasurements, conf.Attestation.AWSNitroTPM.Measurements) assert.Equal(newMeasurements, conf.Attestation.AWSNitroTPM.Measurements)
} }
{ // Azure { // Azure
conf := Default() conf := DefaultWithPanic()
conf.RemoveProviderAndAttestationExcept(cloudprovider.Azure) conf.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
for k := range conf.Attestation.AzureSEVSNP.Measurements { for k := range conf.Attestation.AzureSEVSNP.Measurements {
delete(conf.Attestation.AzureSEVSNP.Measurements, k) delete(conf.Attestation.AzureSEVSNP.Measurements, k)
@ -499,7 +500,7 @@ func TestConfig_UpdateMeasurements(t *testing.T) {
assert.Equal(newMeasurements, conf.Attestation.AzureSEVSNP.Measurements) assert.Equal(newMeasurements, conf.Attestation.AzureSEVSNP.Measurements)
} }
{ // GCP { // GCP
conf := Default() conf := DefaultWithPanic()
conf.RemoveProviderAndAttestationExcept(cloudprovider.GCP) conf.RemoveProviderAndAttestationExcept(cloudprovider.GCP)
for k := range conf.Attestation.GCPSEVES.Measurements { for k := range conf.Attestation.GCPSEVES.Measurements {
delete(conf.Attestation.GCPSEVES.Measurements, k) delete(conf.Attestation.GCPSEVES.Measurements, k)
@ -508,7 +509,7 @@ func TestConfig_UpdateMeasurements(t *testing.T) {
assert.Equal(newMeasurements, conf.Attestation.GCPSEVES.Measurements) assert.Equal(newMeasurements, conf.Attestation.GCPSEVES.Measurements)
} }
{ // QEMU { // QEMU
conf := Default() conf := DefaultWithPanic()
conf.RemoveProviderAndAttestationExcept(cloudprovider.QEMU) conf.RemoveProviderAndAttestationExcept(cloudprovider.QEMU)
for k := range conf.Attestation.QEMUVTPM.Measurements { for k := range conf.Attestation.QEMUVTPM.Measurements {
delete(conf.Attestation.QEMUVTPM.Measurements, k) delete(conf.Attestation.QEMUVTPM.Measurements, k)
@ -525,7 +526,7 @@ func TestConfig_IsReleaseImage(t *testing.T) {
}{ }{
"release image v0.0.0": { "release image v0.0.0": {
conf: func() *Config { conf: func() *Config {
conf := Default() conf := DefaultWithPanic()
conf.Image = "v0.0.0" conf.Image = "v0.0.0"
return conf return conf
}(), }(),
@ -533,7 +534,7 @@ func TestConfig_IsReleaseImage(t *testing.T) {
}, },
"branch image": { "branch image": {
conf: func() *Config { conf: func() *Config {
conf := Default() conf := DefaultWithPanic()
conf.Image = "feat-x-vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef" conf.Image = "feat-x-vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef"
return conf return conf
}(), }(),
@ -541,7 +542,7 @@ func TestConfig_IsReleaseImage(t *testing.T) {
}, },
"debug image": { "debug image": {
conf: func() *Config { conf: func() *Config {
conf := Default() conf := DefaultWithPanic()
conf.Image = "debug-vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef" conf.Image = "debug-vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef"
return conf return conf
}(), }(),
@ -687,11 +688,11 @@ func TestIsDebugCluster(t *testing.T) {
expectedResult: false, expectedResult: false,
}, },
"default config": { "default config": {
config: Default(), config: DefaultWithPanic(),
expectedResult: false, expectedResult: false,
}, },
"enabled": { "enabled": {
config: Default(), config: DefaultWithPanic(),
prepareConfig: func(conf *Config) { prepareConfig: func(conf *Config) {
*conf.DebugCluster = true *conf.DebugCluster = true
}, },
@ -754,7 +755,7 @@ func TestValidateProvider(t *testing.T) {
v := validator.New() v := validator.New()
trans := ut.New(en.New()).GetFallback() trans := ut.New(en.New()).GetFallback()
conf := Default() conf := DefaultWithPanic()
conf.Provider = tc.provider conf.Provider = tc.provider
v.RegisterStructValidation(validateProvider, ProviderConfig{}) v.RegisterStructValidation(validateProvider, ProviderConfig{})

View file

@ -242,7 +242,11 @@ func V2ToV3(path string, fileHandler file.Handler) error {
Measurements: cfgV2.Provider.Azure.Measurements, Measurements: cfgV2.Provider.Azure.Measurements,
} }
} else { } else {
cfgV3.Attestation.AzureSEVSNP = config.DefaultForAzureSEVSNP() azureSEVSNP, err := config.DefaultForAzureSEVSNP()
if err != nil {
return err
}
cfgV3.Attestation.AzureSEVSNP = azureSEVSNP
cfgV3.Attestation.AzureSEVSNP.Measurements = cfgV2.Provider.Azure.Measurements cfgV3.Attestation.AzureSEVSNP.Measurements = cfgV2.Provider.Azure.Measurements
cfgV3.Attestation.AzureSEVSNP.FirmwareSignerConfig = config.SNPFirmwareSignerConfig{ cfgV3.Attestation.AzureSEVSNP.FirmwareSignerConfig = config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: cfgV2.Provider.Azure.IDKeyDigest, AcceptedKeyDigests: cfgV2.Provider.Azure.IDKeyDigest,

View file

@ -1,8 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "version",
srcs = ["version.go"],
importpath = "github.com/edgelesssys/constellation/v2/internal/config/version",
visibility = ["//:__subpackages__"],
)

View file

@ -1,33 +0,0 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package version
const (
Bootloader Type = "bootloader" // Bootloader is the version of the Azure SEVSNP bootloader.
TEE Type = "tee" // TEE is the version of the Azure SEVSNP TEE.
SNP Type = "snp" // SNP is the version of the Azure SEVSNP SNP.
Microcode Type = "microcode" // Microcode is the version of the Azure SEVSNP microcode.
)
// Type is the type of the version to be requested.
type Type (string)
// GetVersion returns the version of the given type.
func GetVersion(t Type) uint8 {
switch t {
case Bootloader:
return 2
case TEE:
return 0
case SNP:
return 6
case Microcode:
return 93
default:
return 1
}
}

View file

@ -82,7 +82,7 @@ func GetAvailableAttestationTypes() []Variant {
for _, k := range keys { for _, k := range keys {
res = append(res, providerAttestationMapping[k]...) res = append(res, providerAttestationMapping[k]...)
} }
return removeDuplicate(res) return RemoveDuplicate(res)
} }
// Getter returns an ASN.1 Object Identifier. // Getter returns an ASN.1 Object Identifier.
@ -259,9 +259,10 @@ func (QEMUTDX) Equal(other Getter) bool {
return other.OID().Equal(QEMUTDX{}.OID()) return other.OID().Equal(QEMUTDX{}.OID())
} }
func removeDuplicate(sliceList []Variant) []Variant { // RemoveDuplicate removes duplicate elements from a slice.
allKeys := make(map[Variant]bool) func RemoveDuplicate[T comparable](sliceList []T) []T {
list := []Variant{} allKeys := make(map[T]bool)
list := []T{}
for _, item := range sliceList { for _, item := range sliceList {
if _, value := allKeys[item]; !value { if _, value := allKeys[item]; !value {
allKeys[item] = true allKeys[item] = true

View file

@ -4,6 +4,7 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library( go_library(
name = "versionsapi", name = "versionsapi",
srcs = [ srcs = [
"attestation.go",
"cliinfo.go", "cliinfo.go",
"imageinfo.go", "imageinfo.go",
"latest.go", "latest.go",
@ -16,6 +17,7 @@ go_library(
deps = [ deps = [
"//internal/cloud/cloudprovider", "//internal/cloud/cloudprovider",
"//internal/constants", "//internal/constants",
"//internal/variant",
"@org_golang_x_mod//semver", "@org_golang_x_mod//semver",
], ],
) )

View file

@ -0,0 +1,74 @@
package versionsapi
import (
"fmt"
"net/url"
"path"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/variant"
)
// AttestationPath is the path to the attestation versions.
const AttestationPath = "constellation/v1/attestation" // TODO already in attestationonapi but import cycle otherwise
// AzureSEVSNPVersion tracks the latest version of each component of the Azure SEVSNP.
type AzureSEVSNPVersion struct {
// Bootloader is the latest version of the Azure SEVSNP bootloader.
Bootloader uint8 `json:"bootloader"`
// TEE is the latest version of the Azure SEVSNP TEE.
TEE uint8 `json:"tee"`
// SNP is the latest version of the Azure SEVSNP SNP.
SNP uint8 `json:"snp"`
// Microcode is the latest version of the Azure SEVSNP microcode.
Microcode uint8 `json:"microcode"`
}
type AzureSEVSNPVersionGet struct {
Version string `json:"-"`
AzureSEVSNPVersion
}
func (i AzureSEVSNPVersionGet) URL() (string, error) {
url, err := url.Parse(constants.CDNRepositoryURL)
if err != nil {
return "", fmt.Errorf("parsing CDN URL: %w", err)
}
url.Path = i.JSONPath()
return url.String(), nil
}
func (i AzureSEVSNPVersionGet) JSONPath() string {
return path.Join(AttestationPath, variant.AzureSEVSNP{}.String(), i.Version)
}
func (i AzureSEVSNPVersionGet) ValidateRequest() error {
return nil
}
func (i AzureSEVSNPVersionGet) Validate() error {
return nil
}
type AzureSEVSNPVersionList ([]string)
func (i AzureSEVSNPVersionList) URL() (string, error) {
url, err := url.Parse(constants.CDNRepositoryURL)
if err != nil {
return "", fmt.Errorf("parsing CDN URL: %w", err)
}
url.Path = i.JSONPath()
return url.String(), nil
}
func (i AzureSEVSNPVersionList) JSONPath() string {
return path.Join(AttestationPath, variant.AzureSEVSNP{}.String(), "list")
}
func (i AzureSEVSNPVersionList) ValidateRequest() error {
return nil
}
func (i AzureSEVSNPVersionList) Validate() error {
return nil
}

View file

@ -54,6 +54,14 @@ func (f *Fetcher) FetchCLIInfo(ctx context.Context, cliInfo versionsapi.CLIInfo)
return fetch(ctx, f.httpc, cliInfo) return fetch(ctx, f.httpc, cliInfo)
} }
func (f *Fetcher) FetchAttestationList(ctx context.Context, attestation versionsapi.AzureSEVSNPVersionList) (versionsapi.AzureSEVSNPVersionList, error) {
return fetch(ctx, f.httpc, attestation)
}
func (f *Fetcher) FetchAttestationVersion(ctx context.Context, attestation versionsapi.AzureSEVSNPVersionGet) (versionsapi.AzureSEVSNPVersionGet, error) {
return fetch(ctx, f.httpc, attestation)
}
type apiObject interface { type apiObject interface {
ValidateRequest() error ValidateRequest() error
Validate() error Validate() error

View file

@ -38,6 +38,8 @@ func TestMain(m *testing.M) {
} }
func TestNewUpdateableValidator(t *testing.T) { func TestNewUpdateableValidator(t *testing.T) {
azureSEVSNP, err := config.DefaultForAzureSEVSNP()
require.NoError(t, err)
testCases := map[string]struct { testCases := map[string]struct {
variant variant.Variant variant variant.Variant
config config.AttestationCfg config config.AttestationCfg
@ -45,7 +47,7 @@ func TestNewUpdateableValidator(t *testing.T) {
}{ }{
"azure": { "azure": {
variant: variant.AzureSEVSNP{}, variant: variant.AzureSEVSNP{},
config: config.DefaultForAzureSEVSNP(), config: azureSEVSNP,
}, },
"gcp": { "gcp": {
variant: variant.GCPSEVES{}, variant: variant.GCPSEVES{},