diff --git a/api/v1beta1/gcpmachine_types.go b/api/v1beta1/gcpmachine_types.go index dc7c3c012..fb0cbfc1f 100644 --- a/api/v1beta1/gcpmachine_types.go +++ b/api/v1beta1/gcpmachine_types.go @@ -137,9 +137,22 @@ const ( ConfidentialComputePolicyDisabled ConfidentialComputePolicy = "Disabled" ) -// Confidential VM supports Compute Engine machine types in the following series: +// ConfidentialVMTechnology represents the confidential computing technology used by a GCP confidential machine. +type ConfidentialVMTechnology string + +const ( + // ConfidentialVMTechnologySEV sets AMD SEV as the VM instance's confidential computing technology of choice. + ConfidentialVMTechnologySEV ConfidentialVMTechnology = "sev" + // ConfidentialVMTechnologySEVSNP sets AMD SEV-SNP as the VM instance's confidential computing technology of choice. + ConfidentialVMTechnologySEVSNP ConfidentialVMTechnology = "sev-snp" +) + +// Confidential VM Technology support depends on the configured machine types. // reference: https://cloud.google.com/compute/confidential-vm/docs/os-and-machine-type#machine-type -var confidentialComputeSupportedMachineSeries = []string{"n2d", "c2d"} +var ( + confidentialMachineSeriesSupportingSev = []string{"n2d", "c2d", "c3d"} + confidentialMachineSeriesSupportingSevsnp = []string{"n2d"} +) // HostMaintenancePolicy represents the desired behavior ase of a host maintenance event. type HostMaintenancePolicy string @@ -343,6 +356,20 @@ type GCPMachineSpec struct { // +optional ConfidentialCompute *ConfidentialComputePolicy `json:"confidentialCompute,omitempty"` + // ConfidentialInstanceType determines the required type of confidential computing technology. + // To set a ConfidentialInstanceType ConfidentialCompute must be first set to "Enabled". + // If ConfidentialCompute is "Enabled" and ConfidentialInstanceType isn't provided, the default ConfidentialInstanceType will be set. At this moment, the default for this case is "sev". + // If ConfidentialCompute is "Enabled" and ConfidentialInstanceType is provided, the provided ConfidentialInstanceType will be set. + // If ConfidentialCompute is "Disabled" and ConfidentialInstanceType isn't provided, confidential computing technology won't be enabled and the instance will be run normally. + // Setting ConfidentialCompute to "Disabled" and ConfidentialInstanceType to a valid value isn't supported. That will raise an error. + // Valid ConfidentialInstanceType values are "sev" and "sev-snp". + // Note that supported ConfidentialInstanceType values will depend on the configured instance machine types. + // "sev" is supported in "n2d", "c2d" and "c3d" machines. + // "sev-snp" is supported in "n2d" machines. + // +kubebuilder:validation:Enum=sev;sev-snp; + // +optional + ConfidentialInstanceType *ConfidentialVMTechnology `json:"confidentialInstanceType,omitempty"` + // RootDiskEncryptionKey defines the KMS key to be used to encrypt the root disk. // +optional RootDiskEncryptionKey *CustomerEncryptionKey `json:"rootDiskEncryptionKey,omitempty"` diff --git a/api/v1beta1/gcpmachine_webhook.go b/api/v1beta1/gcpmachine_webhook.go index 423befd5b..39ec8d7e3 100644 --- a/api/v1beta1/gcpmachine_webhook.go +++ b/api/v1beta1/gcpmachine_webhook.go @@ -115,9 +115,26 @@ func validateConfidentialCompute(spec GCPMachineSpec) error { } machineSeries := strings.Split(spec.InstanceType, "-")[0] - if !slices.Contains(confidentialComputeSupportedMachineSeries, machineSeries) { - return fmt.Errorf("ConfidentialCompute require instance type in the following series: %s", confidentialComputeSupportedMachineSeries) + if spec.ConfidentialInstanceType == nil || *spec.ConfidentialInstanceType == "" { + if !slices.Contains(confidentialMachineSeriesSupportingSev, machineSeries) { + return fmt.Errorf("ConfidentialCompute requires any of the following machine series: %s. %s was found instead", strings.Join(confidentialMachineSeriesSupportingSev, ", "), spec.InstanceType) + } + } else { + switch *spec.ConfidentialInstanceType { + case ConfidentialVMTechnologySEV: + if !slices.Contains(confidentialMachineSeriesSupportingSev, machineSeries) { + return fmt.Errorf("ConfidentialInstanceType %s requires any of the following machine series: %s. %s was found instead", *spec.ConfidentialInstanceType, strings.Join(confidentialMachineSeriesSupportingSev, ", "), spec.InstanceType) + } + case ConfidentialVMTechnologySEVSNP: + if !slices.Contains(confidentialMachineSeriesSupportingSevsnp, machineSeries) { + return fmt.Errorf("ConfidentialInstanceType %s requires any of the following machine series: %s. %s was found instead", *spec.ConfidentialInstanceType, strings.Join(confidentialMachineSeriesSupportingSevsnp, ", "), spec.InstanceType) + } + default: + return fmt.Errorf("invalid ConfidentialInstanceType %s", *spec.ConfidentialInstanceType) + } } + } else if (spec.ConfidentialCompute == nil || *spec.ConfidentialCompute != ConfidentialComputePolicyEnabled) && spec.ConfidentialInstanceType != nil && *spec.ConfidentialInstanceType != "" { + return fmt.Errorf("ConfidentialCompute is Disabled but a ConfidentialInstanceType value was provided. ConfidentialCompute must be set to %s to configure a ConfidentialInstanceType", ConfidentialComputePolicyEnabled) } return nil } diff --git a/api/v1beta1/gcpmachine_webhook_test.go b/api/v1beta1/gcpmachine_webhook_test.go index 28b236121..4e42c457a 100644 --- a/api/v1beta1/gcpmachine_webhook_test.go +++ b/api/v1beta1/gcpmachine_webhook_test.go @@ -25,8 +25,12 @@ import ( func TestGCPMachine_ValidateCreate(t *testing.T) { g := NewWithT(t) confidentialComputeEnabled := ConfidentialComputePolicyEnabled + confidentialComputeDisabled := ConfidentialComputePolicyDisabled + foobar := ConfidentialVMTechnology("foobar") onHostMaintenanceTerminate := HostMaintenancePolicyTerminate onHostMaintenanceMigrate := HostMaintenancePolicyMigrate + confidentialInstanceTypeSEV := ConfidentialVMTechnologySEV + confidentialInstanceTypeSEVSNP := ConfidentialVMTechnologySEVSNP tests := []struct { name string *GCPMachine @@ -85,6 +89,78 @@ func TestGCPMachine_ValidateCreate(t *testing.T) { }, wantErr: true, }, + { + name: "GCPMachine with explicit ConfidentialInstanceType and ConfidentialCompute Disabled - invalid", + GCPMachine: &GCPMachine{ + Spec: GCPMachineSpec{ + InstanceType: "n2d-standard-4", + ConfidentialCompute: &confidentialComputeDisabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEV, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + wantErr: true, + }, + { + name: "GCPMachine with explicit ConfidentialInstanceType and OnHostMaintenance Migrate - invalid", + GCPMachine: &GCPMachine{ + Spec: GCPMachineSpec{ + InstanceType: "n2d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEVSNP, + OnHostMaintenance: &onHostMaintenanceMigrate, + }, + }, + wantErr: true, + }, + { + name: "GCPMachine with SEVSNP ConfidentialInstanceType and unsupported machine type - invalid", + GCPMachine: &GCPMachine{ + Spec: GCPMachineSpec{ + InstanceType: "c2d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEVSNP, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + wantErr: true, + }, + { + name: "GCPMachine with SEVSNP ConfidentialInstanceType and supported machine type - valid", + GCPMachine: &GCPMachine{ + Spec: GCPMachineSpec{ + InstanceType: "n2d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEVSNP, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + wantErr: false, + }, + { + name: "GCPMachine with explicit SEV ConfidentialInstanceType and supported machine type - valid", + GCPMachine: &GCPMachine{ + Spec: GCPMachineSpec{ + InstanceType: "c3d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEV, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + wantErr: false, + }, + { + name: "GCPMachine with unknown ConfidentialInstanceType and ConfidentialCompute Enabled - invalid", + GCPMachine: &GCPMachine{ + Spec: GCPMachineSpec{ + InstanceType: "n2d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &foobar, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + wantErr: true, + }, { name: "GCPMachine with RootDiskEncryptionKey KeyType Managed and Managed field set", GCPMachine: &GCPMachine{ diff --git a/api/v1beta1/gcpmachinetemplate_webhook_test.go b/api/v1beta1/gcpmachinetemplate_webhook_test.go index d42defb27..50d2ab29d 100644 --- a/api/v1beta1/gcpmachinetemplate_webhook_test.go +++ b/api/v1beta1/gcpmachinetemplate_webhook_test.go @@ -25,8 +25,11 @@ import ( func TestGCPMachineTemplate_ValidateCreate(t *testing.T) { g := NewWithT(t) confidentialComputeEnabled := ConfidentialComputePolicyEnabled + confidentialComputeDisabled := ConfidentialComputePolicyDisabled onHostMaintenanceTerminate := HostMaintenancePolicyTerminate onHostMaintenanceMigrate := HostMaintenancePolicyMigrate + confidentialInstanceTypeSEV := ConfidentialVMTechnologySEV + confidentialInstanceTypeSEVSNP := ConfidentialVMTechnologySEVSNP tests := []struct { name string template *GCPMachineTemplate @@ -105,6 +108,102 @@ func TestGCPMachineTemplate_ValidateCreate(t *testing.T) { }, wantErr: true, }, + { + name: "GCPMachine with explicit ConfidentialInstanceType and ConfidentialCompute Disabled - invalid", + template: &GCPMachineTemplate{ + Spec: GCPMachineTemplateSpec{ + Template: GCPMachineTemplateResource{ + Spec: GCPMachineSpec{ + InstanceType: "n2d-standard-4", + ConfidentialCompute: &confidentialComputeDisabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEVSNP, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "GCPMachine with explicit ConfidentialInstanceType and OnHostMaintenance Migrate - invalid", + template: &GCPMachineTemplate{ + Spec: GCPMachineTemplateSpec{ + Template: GCPMachineTemplateResource{ + Spec: GCPMachineSpec{ + InstanceType: "n2d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEVSNP, + OnHostMaintenance: &onHostMaintenanceMigrate, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "GCPMachine with SEVSNP ConfidentialInstanceType and unsupported machine type - invalid", + template: &GCPMachineTemplate{ + Spec: GCPMachineTemplateSpec{ + Template: GCPMachineTemplateResource{ + Spec: GCPMachineSpec{ + InstanceType: "c3d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEVSNP, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "GCPMachine with SEVSNP ConfidentialInstanceType and supported machine type - valid", + template: &GCPMachineTemplate{ + Spec: GCPMachineTemplateSpec{ + Template: GCPMachineTemplateResource{ + Spec: GCPMachineSpec{ + InstanceType: "n2d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEVSNP, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "GCPMachine with explicit SEV ConfidentialInstanceType and supported machine type - valid", + template: &GCPMachineTemplate{ + Spec: GCPMachineTemplateSpec{ + Template: GCPMachineTemplateResource{ + Spec: GCPMachineSpec{ + InstanceType: "c3d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEV, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "GCPMachine with explicit SEV ConfidentialInstanceType and supported machine type - valid", + template: &GCPMachineTemplate{ + Spec: GCPMachineTemplateSpec{ + Template: GCPMachineTemplateResource{ + Spec: GCPMachineSpec{ + InstanceType: "c3d-standard-4", + ConfidentialCompute: &confidentialComputeEnabled, + ConfidentialInstanceType: &confidentialInstanceTypeSEV, + OnHostMaintenance: &onHostMaintenanceTerminate, + }, + }, + }, + }, + wantErr: false, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 3c8560ad9..51fe30659 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -500,6 +500,11 @@ func (in *GCPMachineSpec) DeepCopyInto(out *GCPMachineSpec) { *out = new(ConfidentialComputePolicy) **out = **in } + if in.ConfidentialInstanceType != nil { + in, out := &in.ConfidentialInstanceType, &out.ConfidentialInstanceType + *out = new(ConfidentialVMTechnology) + **out = **in + } if in.RootDiskEncryptionKey != nil { in, out := &in.RootDiskEncryptionKey, &out.RootDiskEncryptionKey *out = new(CustomerEncryptionKey) diff --git a/cloud/scope/machine.go b/cloud/scope/machine.go index ce5d02d55..271bc3d2a 100644 --- a/cloud/scope/machine.go +++ b/cloud/scope/machine.go @@ -451,6 +451,19 @@ func (m *MachineScope) InstanceSpec(log logr.Logger) *compute.Instance { EnableConfidentialCompute: enabled, } } + if m.GCPMachine.Spec.ConfidentialInstanceType != nil { + if instance.ConfidentialInstanceConfig == nil { + instance.ConfidentialInstanceConfig = &compute.ConfidentialInstanceConfig{} + } + switch *m.GCPMachine.Spec.ConfidentialInstanceType { + case infrav1.ConfidentialVMTechnologySEV: + instance.ConfidentialInstanceConfig.ConfidentialInstanceType = "SEV" + case infrav1.ConfidentialVMTechnologySEVSNP: + instance.ConfidentialInstanceConfig.ConfidentialInstanceType = "SEV_SNP" + default: + log.Error(errors.New("Invalid value"), "Unknown ConfidentialInstanceType value", "Spec.ConfidentialInstanceType", *m.GCPMachine.Spec.ConfidentialInstanceType) + } + } instance.Disks = append(instance.Disks, m.InstanceImageSpec()) instance.Disks = append(instance.Disks, m.InstanceAdditionalDiskSpec()...) diff --git a/cloud/services/compute/instances/reconcile_test.go b/cloud/services/compute/instances/reconcile_test.go index 74b33ba8b..6c979e487 100644 --- a/cloud/services/compute/instances/reconcile_test.go +++ b/cloud/services/compute/instances/reconcile_test.go @@ -495,6 +495,159 @@ func TestService_createOrGetInstance(t *testing.T) { Zone: "us-central1-c", }, }, + { + name: "instance does not exist (should create instance) with confidential compute disabled and any confidential instance type specified", + scope: func() Scope { + machineScope.GCPMachine = getFakeGCPMachine() + hostMaintenancePolicyTerminate := infrav1.HostMaintenancePolicyTerminate + machineScope.GCPMachine.Spec.OnHostMaintenance = &hostMaintenancePolicyTerminate + confidentialInstTypeSEV := infrav1.ConfidentialVMTechnologySEV + machineScope.GCPMachine.Spec.ConfidentialInstanceType = &confidentialInstTypeSEV + return machineScope + }, + mockInstance: &cloud.MockInstances{ + ProjectRouter: &cloud.SingleProjectRouter{ID: "proj-id"}, + Objects: map[meta.Key]*cloud.MockInstancesObj{}, + }, + want: &compute.Instance{ + Name: "my-machine", + CanIpForward: true, + Disks: []*compute.AttachedDisk{ + { + AutoDelete: true, + Boot: true, + InitializeParams: &compute.AttachedDiskInitializeParams{ + DiskType: "zones/us-central1-c/diskTypes/pd-standard", + SourceImage: "projects/my-proj/global/images/family/capi-ubuntu-1804-k8s-v1-19", + ResourceManagerTags: map[string]string{}, + Labels: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + Labels: map[string]string{ + "capg-role": "node", + "capg-cluster-my-cluster": "owned", + "foo": "bar", + }, + MachineType: "zones/us-central1-c/machineTypes", + Metadata: &compute.Metadata{ + Items: []*compute.MetadataItems{ + { + Key: "user-data", + Value: ptr.To[string]("Zm9vCg=="), + }, + }, + }, + NetworkInterfaces: []*compute.NetworkInterface{ + { + Network: "projects/my-proj/global/networks/default", + }, + }, + Params: &compute.InstanceParams{ + ResourceManagerTags: map[string]string{}, + }, + SelfLink: "https://www.googleapis.com/compute/v1/projects/proj-id/zones/us-central1-c/instances/my-machine", + ConfidentialInstanceConfig: &compute.ConfidentialInstanceConfig{ + ConfidentialInstanceType: "SEV", + }, + Scheduling: &compute.Scheduling{ + OnHostMaintenance: strings.ToUpper(string(infrav1.HostMaintenancePolicyTerminate)), + }, + ServiceAccounts: []*compute.ServiceAccount{ + { + Email: "default", + Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"}, + }, + }, + Tags: &compute.Tags{ + Items: []string{ + "my-cluster-node", + "my-cluster", + }, + }, + Zone: "us-central1-c", + }, + }, + { + name: "instance does not exist (should create instance) with confidential compute enabled and any confidential instance type specified", + scope: func() Scope { + machineScope.GCPMachine = getFakeGCPMachine() + hostMaintenancePolicyTerminate := infrav1.HostMaintenancePolicyTerminate + machineScope.GCPMachine.Spec.OnHostMaintenance = &hostMaintenancePolicyTerminate + confidentialInstTypeSEVSNP := infrav1.ConfidentialVMTechnologySEVSNP + machineScope.GCPMachine.Spec.ConfidentialInstanceType = &confidentialInstTypeSEVSNP + confidentialComputePolicyEnabled := infrav1.ConfidentialComputePolicyEnabled + machineScope.GCPMachine.Spec.ConfidentialCompute = &confidentialComputePolicyEnabled + return machineScope + }, + mockInstance: &cloud.MockInstances{ + ProjectRouter: &cloud.SingleProjectRouter{ID: "proj-id"}, + Objects: map[meta.Key]*cloud.MockInstancesObj{}, + }, + want: &compute.Instance{ + Name: "my-machine", + CanIpForward: true, + Disks: []*compute.AttachedDisk{ + { + AutoDelete: true, + Boot: true, + InitializeParams: &compute.AttachedDiskInitializeParams{ + DiskType: "zones/us-central1-c/diskTypes/pd-standard", + SourceImage: "projects/my-proj/global/images/family/capi-ubuntu-1804-k8s-v1-19", + ResourceManagerTags: map[string]string{}, + Labels: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + Labels: map[string]string{ + "capg-role": "node", + "capg-cluster-my-cluster": "owned", + "foo": "bar", + }, + MachineType: "zones/us-central1-c/machineTypes", + Metadata: &compute.Metadata{ + Items: []*compute.MetadataItems{ + { + Key: "user-data", + Value: ptr.To[string]("Zm9vCg=="), + }, + }, + }, + NetworkInterfaces: []*compute.NetworkInterface{ + { + Network: "projects/my-proj/global/networks/default", + }, + }, + Params: &compute.InstanceParams{ + ResourceManagerTags: map[string]string{}, + }, + SelfLink: "https://www.googleapis.com/compute/v1/projects/proj-id/zones/us-central1-c/instances/my-machine", + ConfidentialInstanceConfig: &compute.ConfidentialInstanceConfig{ + EnableConfidentialCompute: true, + ConfidentialInstanceType: "SEV_SNP", + }, + Scheduling: &compute.Scheduling{ + OnHostMaintenance: strings.ToUpper(string(infrav1.HostMaintenancePolicyTerminate)), + }, + ServiceAccounts: []*compute.ServiceAccount{ + { + Email: "default", + Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"}, + }, + }, + Tags: &compute.Tags{ + Items: []string{ + "my-cluster-node", + "my-cluster", + }, + }, + Zone: "us-central1-c", + }, + }, { name: "instance does not exist (should create instance) with MIGRATE OnHostMaintenance", scope: func() Scope { diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml index 5dbe18c8a..e5fce153a 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml @@ -200,6 +200,22 @@ spec: - Enabled - Disabled type: string + confidentialInstanceType: + description: |- + ConfidentialInstanceType determines the required type of confidential computing technology. + To set a ConfidentialInstanceType ConfidentialCompute must be first set to "Enabled". + If ConfidentialCompute is "Enabled" and ConfidentialInstanceType isn't provided, the default ConfidentialInstanceType will be set. At this moment, the default for this case is "sev". + If ConfidentialCompute is "Enabled" and ConfidentialInstanceType is provided, the provided ConfidentialInstanceType will be set. + If ConfidentialCompute is "Disabled" and ConfidentialInstanceType isn't provided, confidential computing technology won't be enabled and the instance will be run normally. + Setting ConfidentialCompute to "Disabled" and ConfidentialInstanceType to a valid value isn't supported. That will raise an error. + Valid ConfidentialInstanceType values are "sev" and "sev-snp". + Note that supported ConfidentialInstanceType values will depend on the configured instance machine types. + "sev" is supported in "n2d", "c2d" and "c3d" machines. + "sev-snp" is supported in "n2d" machines. + enum: + - sev + - sev-snp + type: string image: description: |- Image is the full reference to a valid image to be used for this machine. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml index ece5bc8d8..0f7c3d6fb 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml @@ -215,6 +215,22 @@ spec: - Enabled - Disabled type: string + confidentialInstanceType: + description: |- + ConfidentialInstanceType determines the required type of confidential computing technology. + To set a ConfidentialInstanceType ConfidentialCompute must be first set to "Enabled". + If ConfidentialCompute is "Enabled" and ConfidentialInstanceType isn't provided, the default ConfidentialInstanceType will be set. At this moment, the default for this case is "sev". + If ConfidentialCompute is "Enabled" and ConfidentialInstanceType is provided, the provided ConfidentialInstanceType will be set. + If ConfidentialCompute is "Disabled" and ConfidentialInstanceType isn't provided, confidential computing technology won't be enabled and the instance will be run normally. + Setting ConfidentialCompute to "Disabled" and ConfidentialInstanceType to a valid value isn't supported. That will raise an error. + Valid ConfidentialInstanceType values are "sev" and "sev-snp". + Note that supported ConfidentialInstanceType values will depend on the configured instance machine types. + "sev" is supported in "n2d", "c2d" and "c3d" machines. + "sev-snp" is supported in "n2d" machines. + enum: + - sev + - sev-snp + type: string image: description: |- Image is the full reference to a valid image to be used for this machine.