mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-26 07:16:08 -05:00
create on Azure: Allow toggling between CVMs / Trusted Launch VMs (#401)
This commit is contained in:
parent
45beec15f5
commit
716ba52588
@ -32,6 +32,7 @@ func (c *Client) CreateInstances(ctx context.Context, input CreateInstancesInput
|
||||
Image: input.Image,
|
||||
UserAssingedIdentity: input.UserAssingedIdentity,
|
||||
LoadBalancerBackendAddressPool: azure.BackendAddressPoolWorkerName + "-" + c.uid,
|
||||
ConfidentialVM: input.ConfidentialVM,
|
||||
}
|
||||
|
||||
// Create control plane scale set
|
||||
@ -45,6 +46,7 @@ func (c *Client) CreateInstances(ctx context.Context, input CreateInstancesInput
|
||||
Image: input.Image,
|
||||
UserAssingedIdentity: input.UserAssingedIdentity,
|
||||
LoadBalancerBackendAddressPool: azure.BackendAddressPoolControlPlaneName + "-" + c.uid,
|
||||
ConfidentialVM: input.ConfidentialVM,
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@ -99,6 +101,7 @@ type CreateInstancesInput struct {
|
||||
StateDiskType string
|
||||
Image string
|
||||
UserAssingedIdentity string
|
||||
ConfidentialVM bool
|
||||
}
|
||||
|
||||
// CreateInstancesVMs creates instances based on standalone VMs.
|
||||
@ -216,6 +219,7 @@ func (c *Client) createScaleSet(ctx context.Context, input CreateScaleSetInput)
|
||||
ResourceGroup: c.resourceGroup,
|
||||
LoadBalancerName: c.loadBalancerName,
|
||||
LoadBalancerBackendAddressPool: input.LoadBalancerBackendAddressPool,
|
||||
ConfidentialVM: input.ConfidentialVM,
|
||||
}.Azure()
|
||||
|
||||
_, err = c.scaleSetsAPI.BeginCreateOrUpdate(
|
||||
@ -295,6 +299,7 @@ type CreateScaleSetInput struct {
|
||||
Image string
|
||||
UserAssingedIdentity string
|
||||
LoadBalancerBackendAddressPool string
|
||||
ConfidentialVM bool
|
||||
}
|
||||
|
||||
// CreateResourceGroup creates a resource group.
|
||||
|
@ -147,6 +147,7 @@ func TestCreateInstances(t *testing.T) {
|
||||
InstanceType: "type",
|
||||
Image: "image",
|
||||
UserAssingedIdentity: "identity",
|
||||
ConfidentialVM: true,
|
||||
},
|
||||
},
|
||||
"error when creating scale set": {
|
||||
@ -161,6 +162,7 @@ func TestCreateInstances(t *testing.T) {
|
||||
InstanceType: "type",
|
||||
Image: "image",
|
||||
UserAssingedIdentity: "identity",
|
||||
ConfidentialVM: true,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@ -176,6 +178,7 @@ func TestCreateInstances(t *testing.T) {
|
||||
InstanceType: "type",
|
||||
Image: "image",
|
||||
UserAssingedIdentity: "identity",
|
||||
ConfidentialVM: true,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@ -190,6 +193,7 @@ func TestCreateInstances(t *testing.T) {
|
||||
InstanceType: "type",
|
||||
Image: "image",
|
||||
UserAssingedIdentity: "identity",
|
||||
ConfidentialVM: true,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
package azure
|
||||
|
||||
// InstanceTypes are valid Azure instance types.
|
||||
var InstanceTypes = []string{
|
||||
// CVMInstanceTypes are valid Azure CVM instance types.
|
||||
var CVMInstanceTypes = []string{
|
||||
// CVMs (3rd Generation EPYC 7763v processors)
|
||||
// DCasv5-series
|
||||
"Standard_DC2as_v5",
|
||||
@ -42,3 +42,45 @@ var InstanceTypes = []string{
|
||||
"Standard_EC64ads_v5",
|
||||
"Standard_EC96ads_v5",
|
||||
}
|
||||
|
||||
// TrustedLaunchInstanceTypes are valid Azure Trusted Launch instance types.
|
||||
var TrustedLaunchInstanceTypes = []string{
|
||||
// Trusted Launch (2nd Generation AMD EPYC 7452 or 3rd Generation EPYC 7763v processors)
|
||||
// Dav4-series
|
||||
"Standard_D2a_v4",
|
||||
"Standard_D4a_v4",
|
||||
"Standard_D8a_v4",
|
||||
"Standard_D16a_v4",
|
||||
"Standard_D32a_v4",
|
||||
"Standard_D48a_v4",
|
||||
"Standard_D64a_v4",
|
||||
"Standard_D96a_v4",
|
||||
// Dasv4-series
|
||||
"Standard_D2as_v4",
|
||||
"Standard_D4as_v4",
|
||||
"Standard_D8as_v4",
|
||||
"Standard_D16as_v4",
|
||||
"Standard_D32as_v4",
|
||||
"Standard_D48as_v4",
|
||||
"Standard_D64as_v4",
|
||||
"Standard_D96as_v4",
|
||||
// Eav4-series
|
||||
"Standard_E2a_v4",
|
||||
"Standard_E4a_v4",
|
||||
"Standard_E8a_v4",
|
||||
"Standard_E16a_v4",
|
||||
"Standard_E32a_v4",
|
||||
"Standard_E48a_v4",
|
||||
"Standard_E64a_v4",
|
||||
"Standard_E96a_v4",
|
||||
// Easv4-series
|
||||
"Standard_E2as_v4",
|
||||
"Standard_E4as_v4",
|
||||
"Standard_E8as_v4",
|
||||
"Standard_E16as_v4",
|
||||
"Standard_E20as_v4",
|
||||
"Standard_E32as_v4",
|
||||
"Standard_E48as_v4",
|
||||
"Standard_E64as_v4",
|
||||
"Standard_E96as_v4",
|
||||
}
|
||||
|
@ -27,10 +27,20 @@ type ScaleSet struct {
|
||||
UserAssignedIdentity string
|
||||
LoadBalancerName string
|
||||
LoadBalancerBackendAddressPool string
|
||||
ConfidentialVM bool
|
||||
}
|
||||
|
||||
// Azure returns the Azure representation of ScaleSet.
|
||||
func (s ScaleSet) Azure() armcomputev2.VirtualMachineScaleSet {
|
||||
securityType := armcomputev2.SecurityTypesTrustedLaunch
|
||||
var diskSecurityProfile *armcomputev2.VMDiskSecurityProfile
|
||||
if s.ConfidentialVM {
|
||||
securityType = armcomputev2.SecurityTypesConfidentialVM
|
||||
diskSecurityProfile = &armcomputev2.VMDiskSecurityProfile{
|
||||
SecurityEncryptionType: to.Ptr(armcomputev2.SecurityEncryptionTypesVMGuestStateOnly),
|
||||
}
|
||||
}
|
||||
|
||||
return armcomputev2.VirtualMachineScaleSet{
|
||||
Name: to.Ptr(s.Name),
|
||||
Location: to.Ptr(s.Location),
|
||||
@ -70,9 +80,7 @@ func (s ScaleSet) Azure() armcomputev2.VirtualMachineScaleSet {
|
||||
},
|
||||
OSDisk: &armcomputev2.VirtualMachineScaleSetOSDisk{
|
||||
ManagedDisk: &armcomputev2.VirtualMachineScaleSetManagedDiskParameters{
|
||||
SecurityProfile: &armcomputev2.VMDiskSecurityProfile{
|
||||
SecurityEncryptionType: to.Ptr(armcomputev2.SecurityEncryptionTypesVMGuestStateOnly),
|
||||
},
|
||||
SecurityProfile: diskSecurityProfile,
|
||||
},
|
||||
CreateOption: to.Ptr(armcomputev2.DiskCreateOptionTypesFromImage),
|
||||
},
|
||||
@ -111,7 +119,7 @@ func (s ScaleSet) Azure() armcomputev2.VirtualMachineScaleSet {
|
||||
},
|
||||
},
|
||||
SecurityProfile: &armcomputev2.SecurityProfile{
|
||||
SecurityType: to.Ptr(armcomputev2.SecurityTypesConfidentialVM),
|
||||
SecurityType: to.Ptr(securityType),
|
||||
UefiSettings: &armcomputev2.UefiSettings{VTpmEnabled: to.Ptr(true), SecureBootEnabled: to.Ptr(true)},
|
||||
},
|
||||
DiagnosticsProfile: &armcomputev2.DiagnosticsProfile{
|
||||
|
@ -23,6 +23,7 @@ func TestFirewallPermissions(t *testing.T) {
|
||||
Password: "password",
|
||||
Image: "image",
|
||||
UserAssignedIdentity: "user-identity",
|
||||
ConfidentialVM: true,
|
||||
}
|
||||
|
||||
scaleSetAzure := scaleSet.Azure()
|
||||
|
@ -171,6 +171,7 @@ func (c *Creator) createAzure(ctx context.Context, cl azureclient, config *confi
|
||||
StateDiskType: config.Provider.Azure.StateDiskType,
|
||||
Image: config.Provider.Azure.Image,
|
||||
UserAssingedIdentity: config.Provider.Azure.UserAssignedIdentity,
|
||||
ConfidentialVM: *config.Provider.Azure.ConfidentialVM,
|
||||
}
|
||||
if err := cl.CreateInstances(ctx, createInput); err != nil {
|
||||
return state.ConstellationState{}, err
|
||||
|
@ -40,12 +40,15 @@ func NewCreateCmd() *cobra.Command {
|
||||
must(cmd.RegisterFlagCompletionFunc("instance-type", instanceTypeCompletion))
|
||||
|
||||
cmd.SetHelpTemplate(cmd.HelpTemplate() + fmt.Sprintf(`
|
||||
Azure instance types:
|
||||
Azure Confidential VM instance types:
|
||||
%v
|
||||
|
||||
Azure Trusted Launch instance types:
|
||||
%v
|
||||
|
||||
GCP instance types:
|
||||
%v
|
||||
`, formatInstanceTypes(azure.InstanceTypes), formatInstanceTypes(gcp.InstanceTypes)))
|
||||
`, formatInstanceTypes(azure.CVMInstanceTypes), formatInstanceTypes(azure.TrustedLaunchInstanceTypes), formatInstanceTypes(gcp.InstanceTypes)))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@ -78,6 +81,10 @@ func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler,
|
||||
cmd.Println("Configured image does not look like a released production image. Double check image before deploying to production.")
|
||||
}
|
||||
|
||||
if config.IsAzureNonCVM() {
|
||||
cmd.Println("Disabling Confidential VMs is insecure. Use only for evaluation purposes.")
|
||||
}
|
||||
|
||||
if !flags.yes {
|
||||
// Ask user to confirm action.
|
||||
cmd.Printf("The following Constellation cluster will be created:\n")
|
||||
@ -186,7 +193,7 @@ func defaultInstanceType(provider cloudprovider.Provider) string {
|
||||
case cloudprovider.GCP:
|
||||
return gcp.InstanceTypes[0]
|
||||
case cloudprovider.Azure:
|
||||
return azure.InstanceTypes[0]
|
||||
return azure.CVMInstanceTypes[0]
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@ -244,7 +251,10 @@ func instanceTypeCompletion(cmd *cobra.Command, args []string, toComplete string
|
||||
case "gcp":
|
||||
return gcp.InstanceTypes, cobra.ShellCompDirectiveNoFileComp
|
||||
case "azure":
|
||||
return azure.InstanceTypes, cobra.ShellCompDirectiveNoFileComp
|
||||
var azureInstanceTypes []string
|
||||
azureInstanceTypes = append(azureInstanceTypes, azure.CVMInstanceTypes...)
|
||||
azureInstanceTypes = append(azureInstanceTypes, azure.TrustedLaunchInstanceTypes...)
|
||||
return azureInstanceTypes, cobra.ShellCompDirectiveNoFileComp
|
||||
default:
|
||||
return []string{}, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ func TestInstanceTypeCompletion(t *testing.T) {
|
||||
}{
|
||||
"azure": {
|
||||
args: []string{"azure"},
|
||||
wantResult: azure.InstanceTypes,
|
||||
wantResult: append(append([]string{}, azure.CVMInstanceTypes...), azure.TrustedLaunchInstanceTypes...),
|
||||
wantShellCD: cobra.ShellCompDirectiveNoFileComp,
|
||||
},
|
||||
"gcp": {
|
||||
|
@ -41,12 +41,18 @@ func validInstanceTypeForProvider(cmd *cobra.Command, insType string, provider c
|
||||
cmd.SilenceUsage = false
|
||||
return fmt.Errorf("%s isn't a valid GCP instance type", insType)
|
||||
case cloudprovider.Azure:
|
||||
for _, instanceType := range azure.InstanceTypes {
|
||||
for _, instanceType := range azure.CVMInstanceTypes {
|
||||
if insType == instanceType {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
cmd.SetUsageTemplate("Azure instance types:\n" + formatInstanceTypes(azure.InstanceTypes))
|
||||
for _, instanceType := range azure.TrustedLaunchInstanceTypes {
|
||||
if insType == instanceType {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
cmd.SetUsageTemplate("Azure CVM instance types:\n" + formatInstanceTypes(azure.CVMInstanceTypes) +
|
||||
"\n\nAzure Trusted Launch instance types:\n" + formatInstanceTypes(azure.TrustedLaunchInstanceTypes))
|
||||
cmd.SilenceUsage = false
|
||||
return fmt.Errorf("%s isn't a valid Azure instance type", insType)
|
||||
default:
|
||||
|
@ -142,6 +142,9 @@ type AzureConfig struct {
|
||||
// description: |
|
||||
// Authorize spawned VMs to access Azure API. See: https://docs.edgeless.systems/constellation/latest/#/getting-started/install?id=azure
|
||||
UserAssignedIdentity string `yaml:"userAssignedIdentity" validate:"required"`
|
||||
// description: |
|
||||
// Use VMs with security type Confidential VM. If set to false, Trusted Launch VMs will be used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview
|
||||
ConfidentialVM *bool `yaml:"confidentialVM" validate:"required"`
|
||||
}
|
||||
|
||||
// GCPConfig are GCP specific configuration values used by the CLI.
|
||||
@ -230,6 +233,7 @@ func Default() *Config {
|
||||
StateDiskType: "StandardSSD_LRS", // TODO: Replace with Premium_LRS when we replace the default VM size (Standard_D2a_v4) since the size does not support Premium_LRS
|
||||
Measurements: copyPCRMap(azurePCRs),
|
||||
EnforcedMeasurements: []uint32{8, 9, 11, 12},
|
||||
ConfidentialVM: func() *bool { b := true; return &b }(),
|
||||
},
|
||||
GCP: &GCPConfig{
|
||||
Project: "",
|
||||
@ -357,6 +361,11 @@ func (c *Config) IsImageDebug() bool {
|
||||
}
|
||||
}
|
||||
|
||||
// IsAzureNonCVM checks whether the chosen provider is azure and confidential VMs are disabled.
|
||||
func (c *Config) IsAzureNonCVM() bool {
|
||||
return c.Provider.Azure != nil && c.Provider.Azure.ConfidentialVM != nil && !*c.Provider.Azure.ConfidentialVM
|
||||
}
|
||||
|
||||
// FromFile returns config file with `name` read from `fileHandler` by parsing
|
||||
// it as YAML.
|
||||
func FromFile(fileHandler file.Handler, name string) (*Config, error) {
|
||||
|
@ -168,7 +168,7 @@ func init() {
|
||||
FieldName: "azure",
|
||||
},
|
||||
}
|
||||
AzureConfigDoc.Fields = make([]encoder.Doc, 8)
|
||||
AzureConfigDoc.Fields = make([]encoder.Doc, 9)
|
||||
AzureConfigDoc.Fields[0].Name = "subscription"
|
||||
AzureConfigDoc.Fields[0].Type = "string"
|
||||
AzureConfigDoc.Fields[0].Note = ""
|
||||
@ -209,6 +209,11 @@ func init() {
|
||||
AzureConfigDoc.Fields[7].Note = ""
|
||||
AzureConfigDoc.Fields[7].Description = "Authorize spawned VMs to access Azure API. See: https://docs.edgeless.systems/constellation/latest/#/getting-started/install?id=azure"
|
||||
AzureConfigDoc.Fields[7].Comments[encoder.LineComment] = "Authorize spawned VMs to access Azure API. See: https://docs.edgeless.systems/constellation/latest/#/getting-started/install?id=azure"
|
||||
AzureConfigDoc.Fields[8].Name = "confidentialVM"
|
||||
AzureConfigDoc.Fields[8].Type = "bool"
|
||||
AzureConfigDoc.Fields[8].Note = ""
|
||||
AzureConfigDoc.Fields[8].Description = "Use Azure VMs with security type Confidential VM. If set to false, Trusted Launch VMs will be used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview"
|
||||
AzureConfigDoc.Fields[8].Comments[encoder.LineComment] = "Use Azure VMs with security type Confidential VM. If set to false, Trusted Launch VMs will be used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview"
|
||||
|
||||
GCPConfigDoc.Type = "GCPConfig"
|
||||
GCPConfigDoc.Comments[encoder.LineComment] = "GCPConfig are GCP specific configuration values used by the CLI."
|
||||
|
Loading…
x
Reference in New Issue
Block a user