diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c18e5d835f..5c60b26dc9 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -688,67 +688,80 @@ func TestValidInstanceTypeForProvider(t *testing.T) { testCases := map[string]struct { variant variant.Variant instanceTypes []string + providerConfig ProviderConfig expectedResult bool }{ "empty all": { variant: variant.Dummy{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty aws": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty azure only CVMs": { variant: variant.AzureSEVSNP{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty azure with non-CVMs": { variant: variant.AzureTrustedLaunch{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty gcp": { variant: variant.GCPSEVES{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "azure only CVMs (SNP)": { variant: variant.AzureSEVSNP{}, instanceTypes: instancetypes.AzureSNPInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "azure only CVMs (TDX)": { variant: variant.AzureTDX{}, instanceTypes: instancetypes.AzureTDXInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "azure trusted launch VMs": { variant: variant.AzureTrustedLaunch{}, instanceTypes: instancetypes.AzureTrustedLaunchInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "gcp": { variant: variant.GCPSEVES{}, instanceTypes: instancetypes.GCPInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "gcp sev-snp": { variant: variant.GCPSEVSNP{}, instanceTypes: instancetypes.GCPInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "put gcp when azure is set": { variant: variant.AzureSEVSNP{}, instanceTypes: instancetypes.GCPInstanceTypes, expectedResult: false, + providerConfig: ProviderConfig{}, }, "put azure when gcp is set": { variant: variant.GCPSEVES{}, instanceTypes: instancetypes.AzureSNPInstanceTypes, expectedResult: false, + providerConfig: ProviderConfig{}, }, // Testing every possible instance type for AWS is not feasible, so we just test a few based on known supported / unsupported families // Also serves as a test for checkIfInstanceInValidAWSFamilys @@ -756,31 +769,79 @@ func TestValidInstanceTypeForProvider(t *testing.T) { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c5.xlarge", "c5a.2xlarge", "c5a.16xlarge", "u-12tb1.112xlarge"}, expectedResult: false, // False because 2 two of the instances are not valid + providerConfig: ProviderConfig{}, }, "aws one valid instance one with too little vCPUs": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c5.medium"}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "aws graviton sub-family unsupported": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"m6g.xlarge", "r6g.2xlarge", "x2gd.xlarge", "g5g.8xlarge"}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "aws combined two valid instances as one string": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c5.xlarge, c5a.2xlarge"}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "aws only CVMs": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c6a.xlarge", "m6a.xlarge", "r6a.xlarge"}, expectedResult: true, + providerConfig: ProviderConfig{}, }, "aws nitroTPM VMs": { variant: variant.AWSNitroTPM{}, instanceTypes: []string{"c5.xlarge", "c5a.2xlarge", "c5a.16xlarge", "u-12tb1.112xlarge"}, expectedResult: true, + providerConfig: ProviderConfig{}, + }, + "stackit valid flavors": { + variant: variant.QEMUVTPM{}, + instanceTypes: []string{ + "m1a.2cd", + "m1a.4cd", + "m1a.8cd", + "m1a.16cd", + "m1a.30cd", + }, + expectedResult: true, + providerConfig: ProviderConfig{OpenStack: &OpenStackConfig{Cloud: "stackit"}}, + }, + "stackit not valid flavors": { + variant: variant.QEMUVTPM{}, + instanceTypes: []string{ + // removed the c which indicates a confidential flavor + "m1a.2d", + "m1a.4d", + "m1a.8d", + "m1a.16d", + "m1a.30d", + }, + expectedResult: false, + providerConfig: ProviderConfig{OpenStack: &OpenStackConfig{Cloud: "stackit"}}, + }, + "openstack cloud named test": { + variant: variant.QEMUVTPM{}, + instanceTypes: []string{ + "foo.bar", + "foo.bar1", + }, + expectedResult: true, + providerConfig: ProviderConfig{OpenStack: &OpenStackConfig{Cloud: "test"}}, + }, + "Qemutdx valid instance type": { + variant: variant.QEMUTDX{}, + instanceTypes: []string{ + "foo.bar", + }, + expectedResult: true, + providerConfig: ProviderConfig{QEMU: &QEMUConfig{}}, }, } for name, tc := range testCases { @@ -788,7 +849,7 @@ func TestValidInstanceTypeForProvider(t *testing.T) { assert := assert.New(t) for _, instanceType := range tc.instanceTypes { assert.Equal( - tc.expectedResult, validInstanceTypeForProvider(instanceType, tc.variant), + tc.expectedResult, validInstanceTypeForProvider(instanceType, tc.variant, tc.providerConfig), instanceType, ) } diff --git a/internal/config/validation.go b/internal/config/validation.go index 4ea1576b2c..ebd39512f9 100644 --- a/internal/config/validation.go +++ b/internal/config/validation.go @@ -520,7 +520,7 @@ func (c *Config) translateMoreThanOneProviderError(ut ut.Translator, fe validato return t } -func validInstanceTypeForProvider(insType string, attestation variant.Variant) bool { +func validInstanceTypeForProvider(insType string, attestation variant.Variant, provider ProviderConfig) bool { switch attestation { case variant.AWSSEVSNP{}, variant.AWSNitroTPM{}: return isSupportedAWSInstanceType(insType, attestation.Equal(variant.AWSNitroTPM{})) @@ -549,6 +549,17 @@ func validInstanceTypeForProvider(insType string, attestation variant.Variant) b } } case variant.QEMUVTPM{}, variant.QEMUTDX{}: + // only allow confidential instances on stackit cloud using QEMU vTPM + if provider.OpenStack != nil { + if cloud := provider.OpenStack.Cloud; strings.ToLower(cloud) == "stackit" { + for _, instanceType := range instancetypes.STACKITInstanceTypes { + if insType == instanceType { + return true + } + } + return false + } + } return true } return false @@ -789,7 +800,7 @@ func (c *Config) validateNodeGroupZoneField(fl validator.FieldLevel) bool { } func (c *Config) validateInstanceType(fl validator.FieldLevel) bool { - return validInstanceTypeForProvider(fl.Field().String(), c.GetAttestationConfig().GetVariant()) + return validInstanceTypeForProvider(fl.Field().String(), c.GetAttestationConfig().GetVariant(), c.Provider) } func (c *Config) validateStateDiskTypeField(fl validator.FieldLevel) bool {