Skip to content

Commit

Permalink
Add support for confidential VMs
Browse files Browse the repository at this point in the history
Signed-off-by: Michail Resvanis <mresvani@redhat.com>
  • Loading branch information
mresvanis committed Jun 20, 2023
1 parent d43ee8a commit e12d9d5
Show file tree
Hide file tree
Showing 31 changed files with 3,236 additions and 42 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,5 @@ require (
sigs.k8s.io/kustomize/kyaml v0.14.2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)

replace github.com/openshift/api => github.com/mresvanis/api v0.0.0-20230619135815-3f4e0b1780c0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mresvanis/api v0.0.0-20230619135815-3f4e0b1780c0 h1:csqc7fj96lZ/JjXT8orkfWpkyzgLoNw2rcoTGrBzLyo=
github.com/mresvanis/api v0.0.0-20230619135815-3f4e0b1780c0/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
Expand All @@ -467,8 +469,6 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4=
github.com/openshift/api v0.0.0-20230509100629-894b49f57a15 h1:0aKQixYOtjKB3NKhNzFeQ1t0oDOkacpaAN1ztfZufB8=
github.com/openshift/api v0.0.0-20230509100629-894b49f57a15/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k=
github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb h1:Nij5OnaECrkmcRQMAE9LMbQXPo95aqFnf+12B7SyFVI=
github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb/go.mod h1:Rhb3moCqeiTuGHAbXBOlwPubUMlOZEkrEWTRjIF3jzs=
github.com/openshift/library-go v0.0.0-20230508110756-9b7abe2c9cbf h1:ZpFAN2qprgp7jEhGPrOAwP8mmuYC9BRYzvDefg+k4GM=
Expand Down
149 changes: 129 additions & 20 deletions pkg/cloud/azure/services/virtualmachines/virtualmachines.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

"golang.org/x/crypto/ssh"
"k8s.io/klog/v2"
"k8s.io/utils/pointer"
)

const (
Expand Down Expand Up @@ -235,16 +236,11 @@ func (s *Service) deriveVirtualMachineParameters(vmSpec *Spec, nic network.Inter
}
}

var diskEncryptionSet *compute.DiskEncryptionSetParameters
if vmSpec.OSDisk.ManagedDisk.DiskEncryptionSet != nil {
diskEncryptionSet = &compute.DiskEncryptionSetParameters{ID: to.StringPtr(vmSpec.OSDisk.ManagedDisk.DiskEncryptionSet.ID)}
}
osDisk := generateOSDisk(vmSpec)

var securityProfile *compute.SecurityProfile
if vmSpec.SecurityProfile != nil {
securityProfile = &compute.SecurityProfile{
EncryptionAtHost: vmSpec.SecurityProfile.EncryptionAtHost,
}
securityProfile, err := generateSecurityProfile(vmSpec, osDisk)
if err != nil {
return nil, err
}

priority, evictionPolicy, billingProfile, err := getSpotVMOptions(s.Scope.MachineConfig.SpotVMOptions)
Expand All @@ -267,17 +263,8 @@ func (s *Service) deriveVirtualMachineParameters(vmSpec *Spec, nic network.Inter
},
StorageProfile: &compute.StorageProfile{
ImageReference: imageReference,
OsDisk: &compute.OSDisk{
Name: to.StringPtr(fmt.Sprintf("%s_OSDisk", vmSpec.Name)),
OsType: compute.OperatingSystemTypes(vmSpec.OSDisk.OSType),
CreateOption: compute.DiskCreateOptionTypesFromImage,
DiskSizeGB: to.Int32Ptr(vmSpec.OSDisk.DiskSizeGB),
ManagedDisk: &compute.ManagedDiskParameters{
StorageAccountType: compute.StorageAccountTypes(vmSpec.OSDisk.ManagedDisk.StorageAccountType),
DiskEncryptionSet: diskEncryptionSet,
},
},
DataDisks: &dataDisks,
OsDisk: osDisk,
DataDisks: &dataDisks,
},
SecurityProfile: securityProfile,
OsProfile: osProfile,
Expand Down Expand Up @@ -436,6 +423,128 @@ func generateImagePlan(image machinev1.Image) *compute.Plan {
}
}

func generateOSDisk(vmSpec *Spec) *compute.OSDisk {
osDisk := &compute.OSDisk{
Name: to.StringPtr(fmt.Sprintf("%s_OSDisk", vmSpec.Name)),
OsType: compute.OperatingSystemTypes(vmSpec.OSDisk.OSType),
CreateOption: compute.DiskCreateOptionTypesFromImage,
ManagedDisk: &compute.ManagedDiskParameters{},
DiskSizeGB: to.Int32Ptr(vmSpec.OSDisk.DiskSizeGB),
}

if vmSpec.OSDisk.ManagedDisk.StorageAccountType != "" {
osDisk.ManagedDisk.StorageAccountType = compute.StorageAccountTypes(vmSpec.OSDisk.ManagedDisk.StorageAccountType)
}
if vmSpec.OSDisk.ManagedDisk.DiskEncryptionSet != nil {
osDisk.ManagedDisk.DiskEncryptionSet = &compute.DiskEncryptionSetParameters{ID: to.StringPtr(vmSpec.OSDisk.ManagedDisk.DiskEncryptionSet.ID)}
}
if vmSpec.OSDisk.ManagedDisk.SecurityProfile != nil {
osDisk.ManagedDisk.SecurityProfile = &compute.VMDiskSecurityProfile{}

if vmSpec.OSDisk.ManagedDisk.SecurityProfile.DiskEncryptionSet != nil {
osDisk.ManagedDisk.SecurityProfile.DiskEncryptionSet = &compute.DiskEncryptionSetParameters{ID: pointer.String(vmSpec.OSDisk.ManagedDisk.SecurityProfile.DiskEncryptionSet.ID)}
}
if vmSpec.OSDisk.ManagedDisk.SecurityProfile.SecurityEncryptionType != "" {
osDisk.ManagedDisk.SecurityProfile.SecurityEncryptionType = compute.SecurityEncryptionTypes(string(vmSpec.OSDisk.ManagedDisk.SecurityProfile.SecurityEncryptionType))
}
}

return osDisk
}

func generateSecurityProfile(vmSpec *Spec, osDisk *compute.OSDisk) (*compute.SecurityProfile, error) {
if vmSpec.SecurityProfile == nil {
return nil, nil
}

securityProfile := &compute.SecurityProfile{
EncryptionAtHost: vmSpec.SecurityProfile.EncryptionAtHost,
}

if osDisk.ManagedDisk != nil &&
osDisk.ManagedDisk.SecurityProfile != nil &&
osDisk.ManagedDisk.SecurityProfile.SecurityEncryptionType != "" {

if vmSpec.SecurityProfile.SecurityType != machinev1.SecurityTypesConfidentialVM {
return nil, apierrors.InvalidMachineConfiguration("failed to generate security profile for vm %s. "+
"SecurityType should be set to %s when SecurityEncryptionType is defined.",
vmSpec.Name, compute.SecurityTypesConfidentialVM)
}

if vmSpec.SecurityProfile.UEFISettings == nil {
return nil, apierrors.InvalidMachineConfiguration("failed to generate security profile for vm %s. "+
"UEFISettings should be set when SecurityEncryptionType is defined.", vmSpec.Name)
}

if vmSpec.SecurityProfile.UEFISettings.VirtualizedTrustedPlatformModule == "" ||
vmSpec.SecurityProfile.UEFISettings.VirtualizedTrustedPlatformModule != machinev1.VirtualizedTrustedPlatformModulePolicyEnabled {
return nil, apierrors.InvalidMachineConfiguration("failed to generate security profile for vm %s. "+
"VirtualizedTrustedPlatformModule should be enabled when SecurityEncryptionType is defined.", vmSpec.Name)
}

if osDisk.ManagedDisk.SecurityProfile.SecurityEncryptionType == compute.SecurityEncryptionTypesDiskWithVMGuestState {
if vmSpec.SecurityProfile.EncryptionAtHost != nil && *vmSpec.SecurityProfile.EncryptionAtHost {
return nil, apierrors.InvalidMachineConfiguration("failed to generate security profile for vm %s. "+
"EncryptionAtHost cannot be set to true when SecurityEncryptionType is set to %s.",
vmSpec.Name, compute.SecurityEncryptionTypesDiskWithVMGuestState)
}
if vmSpec.SecurityProfile.UEFISettings.SecureBoot == "" ||
vmSpec.SecurityProfile.UEFISettings.SecureBoot != machinev1.SecureBootPolicyEnabled {
return nil, apierrors.InvalidMachineConfiguration("failed to generate security profile for vm %s. "+
"SecureBoot should be enabled when SecurityEncryptionType is set to %s.",
vmSpec.Name, compute.SecurityEncryptionTypesDiskWithVMGuestState)
}
}

securityProfile.SecurityType = compute.SecurityTypesConfidentialVM

securityProfile.UefiSettings = &compute.UefiSettings{
SecureBootEnabled: pointer.Bool(false),
VTpmEnabled: pointer.Bool(true),
}

if vmSpec.SecurityProfile.UEFISettings.SecureBoot == machinev1.SecureBootPolicyEnabled {
securityProfile.UefiSettings.SecureBootEnabled = pointer.Bool(true)
}

return securityProfile, nil
}

if vmSpec.SecurityProfile.SecurityType == machinev1.SecurityTypesTrustedLaunch && vmSpec.SecurityProfile.UEFISettings == nil {
return nil, apierrors.InvalidMachineConfiguration("failed to generate security profile for vm %s. "+
"UEFISettings should be set when SecurityType is set to %s.",
vmSpec.Name, compute.SecurityTypesTrustedLaunch)
}

if vmSpec.SecurityProfile.UEFISettings != nil &&
(vmSpec.SecurityProfile.UEFISettings.SecureBoot == machinev1.SecureBootPolicyEnabled ||
vmSpec.SecurityProfile.UEFISettings.VirtualizedTrustedPlatformModule == machinev1.VirtualizedTrustedPlatformModulePolicyEnabled) {

if vmSpec.SecurityProfile.SecurityType != machinev1.SecurityTypesTrustedLaunch {
return nil, apierrors.InvalidMachineConfiguration("failed to generate security profile for vm %s. "+
"SecurityType should be set to %s when UEFISettings are defined.",
vmSpec.Name, compute.SecurityTypesTrustedLaunch)
}

securityProfile.SecurityType = compute.SecurityTypesTrustedLaunch

securityProfile.UefiSettings = &compute.UefiSettings{
SecureBootEnabled: pointer.Bool(false),
VTpmEnabled: pointer.Bool(false),
}

if vmSpec.SecurityProfile.UEFISettings.SecureBoot == machinev1.SecureBootPolicyEnabled {
securityProfile.UefiSettings.SecureBootEnabled = pointer.Bool(true)
}

if vmSpec.SecurityProfile.UEFISettings.VirtualizedTrustedPlatformModule == machinev1.VirtualizedTrustedPlatformModulePolicyEnabled {
securityProfile.UefiSettings.VTpmEnabled = pointer.Bool(true)
}
}

return securityProfile, nil
}

func generateDataDisks(vmSpec *Spec) ([]compute.DataDisk, error) {
seenDataDiskLuns := make(map[int32]struct{})
seenDataDiskNames := make(map[string]struct{})
Expand Down
Loading

0 comments on commit e12d9d5

Please sign in to comment.