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 Jul 17, 2023
1 parent 1437f81 commit dd02e5a
Show file tree
Hide file tree
Showing 84 changed files with 5,936 additions and 193 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/onsi/ginkgo/v2 v2.9.5
github.com/onsi/gomega v1.27.7
github.com/openshift/api v0.0.0-20230509100629-894b49f57a15
github.com/openshift/api v0.0.0-20230707123100-21c0ce73add5
github.com/openshift/machine-api-operator v0.2.1-0.20230531233206-931f6f67c1c7
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.7.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
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/mresvanis/api v0.0.0-20230706123929-dd9b8275a496 h1:OsDBTmU3l2/HwWVIQfUlv0DEZvFVxO8Bi6F6+W7OLRo=
github.com/mresvanis/api v0.0.0-20230706123929-dd9b8275a496/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
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=
Expand All @@ -467,8 +469,8 @@ 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/api v0.0.0-20230707123100-21c0ce73add5 h1:htabZ4P4mMAPTaTU0H0p++o/fmowJD5lnHR16ZBq3Js=
github.com/openshift/api v0.0.0-20230707123100-21c0ce73add5/go.mod h1:yimSGmjsI+XF1mr+AKBs2//fSXIOhhetHGbMlBEfXbs=
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
146 changes: 126 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,125 @@ 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.SecurityEncryptionType != "" {
osDisk.ManagedDisk.SecurityProfile = &compute.VMDiskSecurityProfile{}

osDisk.ManagedDisk.SecurityProfile.SecurityEncryptionType = compute.SecurityEncryptionTypes(string(vmSpec.OSDisk.ManagedDisk.SecurityProfile.SecurityEncryptionType))

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

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.Settings.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.Settings.ConfidentialVM == 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.Settings.ConfidentialVM.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.Settings.ConfidentialVM.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.Settings.ConfidentialVM.UEFISettings.SecureBoot == machinev1.SecureBootPolicyEnabled {
securityProfile.UefiSettings.SecureBootEnabled = pointer.Bool(true)
}

return securityProfile, nil
}

if vmSpec.SecurityProfile.Settings.SecurityType == machinev1.SecurityTypesTrustedLaunch && vmSpec.SecurityProfile.Settings.TrustedLaunch == 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.Settings.TrustedLaunch != nil &&
(vmSpec.SecurityProfile.Settings.TrustedLaunch.UEFISettings.SecureBoot == machinev1.SecureBootPolicyEnabled ||
vmSpec.SecurityProfile.Settings.TrustedLaunch.UEFISettings.VirtualizedTrustedPlatformModule == machinev1.VirtualizedTrustedPlatformModulePolicyEnabled) {

if vmSpec.SecurityProfile.Settings.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.Settings.TrustedLaunch.UEFISettings.SecureBoot == machinev1.SecureBootPolicyEnabled {
securityProfile.UefiSettings.SecureBootEnabled = pointer.Bool(true)
}

if vmSpec.SecurityProfile.Settings.TrustedLaunch.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 dd02e5a

Please sign in to comment.