Skip to content

Commit 65157f7

Browse files
Merge pull request openshift#7469 from mresvanis/ocpbugs-18387-azure-cvm-capabilities
OCPBUGS-18387: Add Azure ConfidentialVM capability and DiskEncryptionSet validations
2 parents 453c036 + 190d691 commit 65157f7

File tree

4 files changed

+362
-21
lines changed

4 files changed

+362
-21
lines changed

pkg/asset/installconfig/azure/validation.go

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
azdns "github.com/Azure/azure-sdk-for-go/profiles/2018-03-01/dns/mgmt/dns"
1313
aznetwork "github.com/Azure/azure-sdk-for-go/profiles/2018-03-01/network/mgmt/network"
14+
azenc "github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
1415
"github.com/Azure/go-autorest/autorest/to"
1516
"github.com/pkg/errors"
1617
"github.com/sirupsen/logrus"
@@ -92,6 +93,60 @@ func ValidateDiskEncryptionSet(client API, ic *types.InstallConfig) field.ErrorL
9293
return allErrs
9394
}
9495

96+
func validateConfidentialDiskEncryptionSet(client API, diskEncryptionSet *aztypes.DiskEncryptionSet, desFieldPath *field.Path) error {
97+
resp, requestErr := client.GetDiskEncryptionSet(context.TODO(), diskEncryptionSet.SubscriptionID, diskEncryptionSet.ResourceGroup, diskEncryptionSet.Name)
98+
if requestErr != nil {
99+
return requestErr
100+
} else if resp == nil || resp.EncryptionSetProperties == nil || resp.EncryptionSetProperties.EncryptionType != azenc.DiskEncryptionSetTypeConfidentialVMEncryptedWithCustomerKey {
101+
return errors.Errorf("the disk encryption set should be created with type %s", azenc.DiskEncryptionSetTypeConfidentialVMEncryptedWithCustomerKey)
102+
}
103+
return nil
104+
}
105+
106+
// ValidateSecurityProfileDiskEncryptionSet ensures the security profile disk encryption set exists and is valid.
107+
func ValidateSecurityProfileDiskEncryptionSet(client API, ic *types.InstallConfig) field.ErrorList {
108+
allErrs := field.ErrorList{}
109+
110+
if ic.Platform.Azure.DefaultMachinePlatform != nil &&
111+
ic.Platform.Azure.DefaultMachinePlatform.OSDisk.SecurityProfile != nil &&
112+
ic.Platform.Azure.DefaultMachinePlatform.OSDisk.SecurityProfile.DiskEncryptionSet != nil {
113+
desFieldPath := field.NewPath("platform").Child("azure", "defaultMachinePlatform", "osDisk", "securityProfile", "diskEncryptionSet")
114+
diskEncryptionSet := ic.Platform.Azure.DefaultMachinePlatform.OSDisk.SecurityProfile.DiskEncryptionSet
115+
err := validateConfidentialDiskEncryptionSet(client, diskEncryptionSet, desFieldPath)
116+
if err != nil {
117+
allErrs = append(allErrs, field.Invalid(desFieldPath, diskEncryptionSet, err.Error()))
118+
}
119+
}
120+
121+
if ic.ControlPlane != nil &&
122+
ic.ControlPlane.Platform.Azure != nil &&
123+
ic.ControlPlane.Platform.Azure.OSDisk.SecurityProfile != nil &&
124+
ic.ControlPlane.Platform.Azure.OSDisk.SecurityProfile.DiskEncryptionSet != nil {
125+
desFieldPath := field.NewPath("platform").Child("azure", "osDisk", "securityProfile", "diskEncryptionSet")
126+
diskEncryptionSet := ic.ControlPlane.Platform.Azure.OSDisk.SecurityProfile.DiskEncryptionSet
127+
err := validateConfidentialDiskEncryptionSet(client, diskEncryptionSet, desFieldPath)
128+
if err != nil {
129+
allErrs = append(allErrs, field.Invalid(desFieldPath, diskEncryptionSet, err.Error()))
130+
}
131+
}
132+
133+
for idx, compute := range ic.Compute {
134+
fieldPath := field.NewPath("compute").Index(idx)
135+
if compute.Platform.Azure != nil &&
136+
compute.Platform.Azure.OSDisk.SecurityProfile != nil &&
137+
compute.Platform.Azure.OSDisk.SecurityProfile.DiskEncryptionSet != nil {
138+
desFieldPath := fieldPath.Child("platform", "azure", "osDisk", "securityProfile", "diskEncryptionSet")
139+
diskEncryptionSet := compute.Platform.Azure.OSDisk.SecurityProfile.DiskEncryptionSet
140+
err := validateConfidentialDiskEncryptionSet(client, diskEncryptionSet, desFieldPath)
141+
if err != nil {
142+
allErrs = append(allErrs, field.Invalid(desFieldPath, diskEncryptionSet, err.Error()))
143+
}
144+
}
145+
}
146+
147+
return allErrs
148+
}
149+
95150
func validatePremiumDisk(fieldPath *field.Path, diskType string, instanceType string, capabilities map[string]string) field.ErrorList {
96151
fldPath := fieldPath.Child("osDisk", "diskType")
97152
val, ok := capabilities["PremiumIO"]
@@ -158,6 +213,42 @@ func validateMininumRequirements(fieldPath *field.Path, req resourceRequirements
158213
return allErrs
159214
}
160215

216+
func validateSecurityType(fieldPath *field.Path, securityType aztypes.SecurityTypes, instanceType string, capabilities map[string]string) field.ErrorList {
217+
allErrs := field.ErrorList{}
218+
219+
_, hasTrustedLaunchDisabled := capabilities["TrustedLaunchDisabled"]
220+
confidentialComputingType, hasConfidentialComputingType := capabilities["ConfidentialComputingType"]
221+
isConfidentialComputingTypeSNP := confidentialComputingType == "SNP"
222+
223+
var reason string
224+
supportedSecurityType := true
225+
switch securityType {
226+
case aztypes.SecurityTypesConfidentialVM:
227+
supportedSecurityType = hasConfidentialComputingType && isConfidentialComputingTypeSNP
228+
229+
if !hasConfidentialComputingType {
230+
reason = "no support for Confidential Computing"
231+
} else if !isConfidentialComputingTypeSNP {
232+
reason = "no support for AMD-SEV SNP"
233+
}
234+
case aztypes.SecurityTypesTrustedLaunch:
235+
supportedSecurityType = !(hasTrustedLaunchDisabled || hasConfidentialComputingType)
236+
237+
if hasTrustedLaunchDisabled {
238+
reason = "no support for Trusted Launch"
239+
} else if hasConfidentialComputingType {
240+
reason = "confidential VMs do not support Trusted Launch for VMs"
241+
}
242+
}
243+
244+
if !supportedSecurityType {
245+
errMsg := fmt.Sprintf("this security type is not supported for instance type %s, %s", instanceType, reason)
246+
allErrs = append(allErrs, field.Invalid(fieldPath, securityType, errMsg))
247+
}
248+
249+
return allErrs
250+
}
251+
161252
func validateFamily(fieldPath *field.Path, instanceType, family string) field.ErrorList {
162253
windowsVMFamilies := sets.NewString(
163254
"standardNVSv4Family",
@@ -245,7 +336,7 @@ func validateUltraSSD(client API, fieldPath *field.Path, icZones []string, regio
245336
}
246337

247338
// ValidateInstanceType ensures the instance type has sufficient Vcpu, Memory, and a valid family type.
248-
func ValidateInstanceType(client API, fieldPath *field.Path, region, instanceType, diskType string, req resourceRequirements, ultraSSDEnabled bool, vmNetworkingType string, icZones []string, architecture types.Architecture) field.ErrorList {
339+
func ValidateInstanceType(client API, fieldPath *field.Path, region, instanceType, diskType string, req resourceRequirements, ultraSSDEnabled bool, vmNetworkingType string, icZones []string, architecture types.Architecture, securityType aztypes.SecurityTypes) field.ErrorList {
249340
allErrs := field.ErrorList{}
250341

251342
capabilities, err := client.GetVMCapabilities(context.TODO(), instanceType, region)
@@ -255,6 +346,7 @@ func ValidateInstanceType(client API, fieldPath *field.Path, region, instanceTyp
255346

256347
allErrs = append(allErrs, validateMininumRequirements(fieldPath.Child("type"), req, instanceType, capabilities)...)
257348
allErrs = append(allErrs, validateVMArchitecture(fieldPath.Child("type"), instanceType, architecture, capabilities)...)
349+
allErrs = append(allErrs, validateSecurityType(fieldPath.Child("settings", "securityType"), securityType, instanceType, capabilities)...)
258350

259351
family, _ := client.GetVirtualMachineFamily(context.TODO(), instanceType, region)
260352
if family != "" {
@@ -280,6 +372,8 @@ func ValidateInstanceType(client API, fieldPath *field.Path, region, instanceTyp
280372
func validateInstanceTypes(client API, ic *types.InstallConfig) field.ErrorList {
281373
allErrs := field.ErrorList{}
282374

375+
var securityType aztypes.SecurityTypes
376+
283377
defaultDiskType := aztypes.DefaultDiskType
284378
defaultInstanceType := ""
285379
defaultUltraSSDCapability := "Disabled"
@@ -303,6 +397,9 @@ func validateInstanceTypes(client API, ic *types.InstallConfig) field.ErrorList
303397
if ic.Platform.Azure.DefaultMachinePlatform.Zones != nil {
304398
defaultZones = ic.Platform.Azure.DefaultMachinePlatform.Zones
305399
}
400+
if ic.Platform.Azure.DefaultMachinePlatform.Settings != nil {
401+
securityType = ic.Platform.Azure.DefaultMachinePlatform.Settings.SecurityType
402+
}
306403
}
307404

308405
if ic.ControlPlane != nil && ic.ControlPlane.Platform.Azure != nil {
@@ -314,6 +411,9 @@ func validateInstanceTypes(client API, ic *types.InstallConfig) field.ErrorList
314411
zones := ic.ControlPlane.Platform.Azure.Zones
315412
architecture := ic.ControlPlane.Architecture
316413

414+
if ic.ControlPlane.Platform.Azure.Settings != nil {
415+
securityType = ic.ControlPlane.Platform.Azure.Settings.SecurityType
416+
}
317417
if diskType == "" {
318418
diskType = defaultDiskType
319419
}
@@ -334,7 +434,7 @@ func validateInstanceTypes(client API, ic *types.InstallConfig) field.ErrorList
334434
zones = defaultZones
335435
}
336436
ultraSSDEnabled := strings.EqualFold(ultraSSDCapability, "Enabled")
337-
allErrs = append(allErrs, ValidateInstanceType(client, fieldPath, ic.Azure.Region, instanceType, diskType, controlPlaneReq, ultraSSDEnabled, vmNetworkingType, zones, architecture)...)
437+
allErrs = append(allErrs, ValidateInstanceType(client, fieldPath, ic.Azure.Region, instanceType, diskType, controlPlaneReq, ultraSSDEnabled, vmNetworkingType, zones, architecture, securityType)...)
338438
}
339439

340440
for idx, compute := range ic.Compute {
@@ -347,6 +447,9 @@ func validateInstanceTypes(client API, ic *types.InstallConfig) field.ErrorList
347447
zones := compute.Platform.Azure.Zones
348448
architecture := compute.Architecture
349449

450+
if compute.Platform.Azure.Settings != nil {
451+
securityType = compute.Platform.Azure.Settings.SecurityType
452+
}
350453
if diskType == "" {
351454
diskType = defaultDiskType
352455
}
@@ -368,7 +471,7 @@ func validateInstanceTypes(client API, ic *types.InstallConfig) field.ErrorList
368471
}
369472
ultraSSDEnabled := strings.EqualFold(ultraSSDCapability, "Enabled")
370473
allErrs = append(allErrs, ValidateInstanceType(client, fieldPath.Child("platform", "azure"),
371-
ic.Azure.Region, instanceType, diskType, computeReq, ultraSSDEnabled, vmNetworkingType, zones, architecture)...)
474+
ic.Azure.Region, instanceType, diskType, computeReq, ultraSSDEnabled, vmNetworkingType, zones, architecture, securityType)...)
372475
}
373476
}
374477

@@ -387,7 +490,7 @@ func validateInstanceTypes(client API, ic *types.InstallConfig) field.ErrorList
387490
fieldPath := field.NewPath("platform", "azure", "defaultMachinePlatform")
388491
ultraSSDEnabled := strings.EqualFold(defaultUltraSSDCapability, "Enabled")
389492
allErrs = append(allErrs, ValidateInstanceType(client, fieldPath,
390-
ic.Azure.Region, defaultInstanceType, defaultDiskType, minReq, ultraSSDEnabled, defaultVMNetworkingType, defaultZones, architecture)...)
493+
ic.Azure.Region, defaultInstanceType, defaultDiskType, minReq, ultraSSDEnabled, defaultVMNetworkingType, defaultZones, architecture, securityType)...)
391494
}
392495
return allErrs
393496
}
@@ -525,6 +628,7 @@ func ValidateForProvisioning(client API, ic *types.InstallConfig) error {
525628
allErrs := field.ErrorList{}
526629
allErrs = append(allErrs, validateResourceGroup(client, field.NewPath("platform").Child("azure"), ic.Azure)...)
527630
allErrs = append(allErrs, ValidateDiskEncryptionSet(client, ic)...)
631+
allErrs = append(allErrs, ValidateSecurityProfileDiskEncryptionSet(client, ic)...)
528632
if ic.Azure.CloudName == aztypes.StackCloud {
529633
allErrs = append(allErrs, checkAzureStackClusterOSImageSet(ic.Azure.ClusterOSImage, field.NewPath("platform").Child("azure"))...)
530634
}

0 commit comments

Comments
 (0)