config: pass VM service account from iam create to cluster create via config

This commit is contained in:
Leonard Cohnen 2025-02-20 20:14:03 +01:00
parent bd65ad3697
commit d46fb388a1
14 changed files with 81 additions and 53 deletions

View File

@ -231,6 +231,7 @@ func gcpTerraformVars(conf *config.Config, imageRef string) *terraform.GCPCluste
InternalLoadBalancer: conf.InternalLoadBalancer,
CCTechnology: ccTech,
AdditionalLabels: conf.Tags,
IAMServiceAccountVM: conf.Provider.GCP.IAMServiceAccountVM,
}
}

View File

@ -256,6 +256,7 @@ func TestValidateInputs(t *testing.T) {
ClientX509CertURL: "client_cert",
}))
cfg.Provider.GCP.ServiceAccountKeyPath = "saKey.json"
cfg.Provider.GCP.IAMServiceAccountVM = "example@example.com"
}
require.NoError(fh.WriteYAML(constants.ConfigFilename, cfg))

View File

@ -141,11 +141,12 @@ func (c *gcpIAMCreator) printOutputValues(cmd *cobra.Command, _ cloudcmd.IAMOutp
cmd.Printf("serviceAccountKeyPath:\t%s\n\n", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename))
}
func (c *gcpIAMCreator) writeOutputValuesToConfig(conf *config.Config, _ cloudcmd.IAMOutput) {
func (c *gcpIAMCreator) writeOutputValuesToConfig(conf *config.Config, out cloudcmd.IAMOutput) {
conf.Provider.GCP.Project = c.flags.projectID
conf.Provider.GCP.ServiceAccountKeyPath = constants.GCPServiceAccountKeyFilename // File was created in workspace, so only the filename is needed.
conf.Provider.GCP.Region = c.flags.region
conf.Provider.GCP.Zone = c.flags.zone
conf.Provider.GCP.IAMServiceAccountVM = out.GCPOutput.IAMServiceAccountVM
for groupName, group := range conf.NodeGroups {
group.Zone = c.flags.zone
conf.NodeGroups[groupName] = group

View File

@ -539,6 +539,7 @@ func defaultConfigWithExpectedMeasurements(t *testing.T, conf *config.Config, cs
conf.Provider.GCP.Project = "test-project"
conf.Provider.GCP.Zone = "test-zone"
conf.Provider.GCP.ServiceAccountKeyPath = "test-key-path"
conf.Provider.GCP.IAMServiceAccountVM = "example@example.com"
conf.Attestation.GCPSEVSNP.Measurements[4] = measurements.WithAllBytes(0x44, measurements.Enforce, measurements.PCRMeasurementLength)
conf.Attestation.GCPSEVSNP.Measurements[9] = measurements.WithAllBytes(0x11, measurements.Enforce, measurements.PCRMeasurementLength)
conf.Attestation.GCPSEVSNP.Measurements[12] = measurements.WithAllBytes(0xcc, measurements.Enforce, measurements.PCRMeasurementLength)

View File

@ -141,6 +141,8 @@ type GCPClusterVariables struct {
InternalLoadBalancer bool `hcl:"internal_load_balancer" cty:"internal_load_balancer"`
// CCTechnology is the confidential computing technology to use on the VMs. (`SEV` or `SEV_SNP`)
CCTechnology string `hcl:"cc_technology" cty:"cc_technology"`
// IAMServiceAccountControlPlane is the IAM service account mail address to attach to VMs.
IAMServiceAccountVM string `hcl:"iam_service_account_vm" cty:"iam_service_account_vm"`
// AdditionalLables are (optional) additional labels that should be applied to created resources.
AdditionalLabels cloudprovider.Tags `hcl:"additional_labels" cty:"additional_labels"`
}

View File

@ -124,6 +124,7 @@ func TestGCPClusterVariables(t *testing.T) {
},
CustomEndpoint: "example.com",
CCTechnology: "SEV_SNP",
IAMServiceAccountVM: "example@example.com",
}
// test that the variables are correctly rendered
@ -154,6 +155,7 @@ node_groups = {
custom_endpoint = "example.com"
internal_load_balancer = false
cc_technology = "SEV_SNP"
iam_service_account_vm = "example@example.com"
additional_labels = null
`
got := vars.String()
@ -166,6 +168,7 @@ func TestGCPIAMVariables(t *testing.T) {
Region: "eu-central-1",
Zone: "eu-central-1a",
ServiceAccountID: "my-service-account",
IAMServiceAccountVM: "my-service-account-vm",
}
// test that the variables are correctly rendered
@ -173,6 +176,7 @@ func TestGCPIAMVariables(t *testing.T) {
region = "eu-central-1"
zone = "eu-central-1a"
service_account_id = "my-service-account"
service_account_id_vm = "my-service-account-vm"
`
got := vars.String()
assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences

View File

@ -188,6 +188,9 @@ type GCPConfig struct {
// Path of service account key file. For required service account roles, see https://docs.edgeless.systems/constellation/getting-started/install#authorization
ServiceAccountKeyPath string `yaml:"serviceAccountKeyPath" validate:"required"`
// description: |
// GCP service account mail address. This is being attached to the VMs for authorization.
IAMServiceAccountVM string `yaml:"IAMServiceAccountVM" validate:"required"`
// description: |
// Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage
DeployCSIDriver *bool `yaml:"deployCSIDriver" validate:"required"`
// description: |
@ -349,6 +352,7 @@ func Default() *Config {
Region: "",
Zone: "",
ServiceAccountKeyPath: "",
IAMServiceAccountVM: "",
DeployCSIDriver: toPtr(true),
UseMarketplaceImage: toPtr(false),
},

View File

@ -241,7 +241,7 @@ func init() {
FieldName: "gcp",
},
}
GCPConfigDoc.Fields = make([]encoder.Doc, 6)
GCPConfigDoc.Fields = make([]encoder.Doc, 7)
GCPConfigDoc.Fields[0].Name = "project"
GCPConfigDoc.Fields[0].Type = "string"
GCPConfigDoc.Fields[0].Note = ""
@ -262,16 +262,21 @@ func init() {
GCPConfigDoc.Fields[3].Note = ""
GCPConfigDoc.Fields[3].Description = "Path of service account key file. For required service account roles, see https://docs.edgeless.systems/constellation/getting-started/install#authorization"
GCPConfigDoc.Fields[3].Comments[encoder.LineComment] = "Path of service account key file. For required service account roles, see https://docs.edgeless.systems/constellation/getting-started/install#authorization"
GCPConfigDoc.Fields[4].Name = "deployCSIDriver"
GCPConfigDoc.Fields[4].Type = "bool"
GCPConfigDoc.Fields[4].Name = "IAMServiceAccountVM"
GCPConfigDoc.Fields[4].Type = "string"
GCPConfigDoc.Fields[4].Note = ""
GCPConfigDoc.Fields[4].Description = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
GCPConfigDoc.Fields[4].Comments[encoder.LineComment] = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
GCPConfigDoc.Fields[5].Name = "useMarketplaceImage"
GCPConfigDoc.Fields[4].Description = "GCP service account mail address. This is being attached to the VMs for authorization."
GCPConfigDoc.Fields[4].Comments[encoder.LineComment] = "GCP service account mail address. This is being attached to the VMs for authorization."
GCPConfigDoc.Fields[5].Name = "deployCSIDriver"
GCPConfigDoc.Fields[5].Type = "bool"
GCPConfigDoc.Fields[5].Note = ""
GCPConfigDoc.Fields[5].Description = "Use the specified GCP Marketplace image offering."
GCPConfigDoc.Fields[5].Comments[encoder.LineComment] = "Use the specified GCP Marketplace image offering."
GCPConfigDoc.Fields[5].Description = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
GCPConfigDoc.Fields[5].Comments[encoder.LineComment] = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
GCPConfigDoc.Fields[6].Name = "useMarketplaceImage"
GCPConfigDoc.Fields[6].Type = "bool"
GCPConfigDoc.Fields[6].Note = ""
GCPConfigDoc.Fields[6].Description = "Use the specified GCP Marketplace image offering."
GCPConfigDoc.Fields[6].Comments[encoder.LineComment] = "Use the specified GCP Marketplace image offering."
OpenStackConfigDoc.Type = "OpenStackConfig"
OpenStackConfigDoc.Comments[encoder.LineComment] = "OpenStackConfig holds config information for OpenStack based Constellation deployments."

View File

@ -328,10 +328,10 @@ func TestFromFile(t *testing.T) {
}
func TestValidate(t *testing.T) {
const defaultErrCount = 33 // expect this number of error messages by default because user-specific values are not set and multiple providers are defined by default
const defaultErrCount = 34 // expect this number of error messages by default because user-specific values are not set and multiple providers are defined by default
const azErrCount = 7
const awsErrCount = 8
const gcpErrCount = 8
const gcpErrCount = 9
// TODO(AB#3132,3u13r): refactor config validation tests
// Note that the `cnf.Image = ""` is a hack to align `bazel test` with `go test` behavior
@ -464,6 +464,7 @@ func TestValidate(t *testing.T) {
gcp.Project = "test-project"
gcp.Zone = "test-zone"
gcp.ServiceAccountKeyPath = "test-key-path"
gcp.IAMServiceAccountVM = "example@example.com"
cnf.Provider = ProviderConfig{}
cnf.Provider.GCP = gcp
cnf.Attestation.GCPSEVSNP.Measurements = measurements.M{

View File

@ -81,6 +81,7 @@ module "gcp_infrastructure" {
project = local.project_id
internal_load_balancer = false
cc_technology = local.cc_technology
iam_service_account_vm = module.gcp_iam.service_account_mail_vm
}
data "constellation_attestation" "foo" {

View File

@ -182,6 +182,7 @@ module "instance_group" {
init_secret_hash = local.init_secret_hash
custom_endpoint = var.custom_endpoint
cc_technology = var.cc_technology
iam_service_account_vm = var.iam_service_account_vm
}
resource "google_compute_address" "loadbalancer_ip_internal" {

View File

@ -77,17 +77,11 @@ resource "google_compute_instance_template" "template" {
on_host_maintenance = "TERMINATE"
}
# Define all IAM access via the service account and not via scopes:
# See: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance_template#nested_service_account
service_account {
scopes = [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/servicecontrol",
"https://www.googleapis.com/auth/service.management.readonly",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring.write",
"https://www.googleapis.com/auth/trace.append",
"https://www.googleapis.com/auth/cloud-platform",
]
email = var.iam_service_account_vm
scopes = ["cloud-platform"]
}
shielded_instance_config {

View File

@ -108,3 +108,9 @@ variable "cc_technology" {
error_message = "The confidential computing technology has to be 'SEV' or 'SEV_SNP'."
}
}
variable "iam_service_account_vm" {
type = string
default = ""
description = "IAM service account used for the VMs"
}

View File

@ -75,3 +75,9 @@ variable "additional_labels" {
default = {}
description = "Additional labels that should be given to created recources."
}
variable "iam_service_account_vm" {
type = string
default = ""
description = "IAM service account used for the VMs"
}