diff --git a/resources/common/format_func.go b/resources/common/format_func.go index 56cb5265..f7f8ae1b 100644 --- a/resources/common/format_func.go +++ b/resources/common/format_func.go @@ -22,3 +22,14 @@ func AlphanumericFormatFunc(s string) string { } return reg.ReplaceAllString(s, "") } + +func LowercaseAlphanumericAndDashFormatFunc(s string) string { + s = strings.ToLower(s) + // remove all illegal chars + s = regexp.MustCompile("[^-a-z\\d]+").ReplaceAllString(s, "") + // remove dashes and numbers in the beginning of the string + s = regexp.MustCompile("^[-0-9]+").ReplaceAllString(s, "") + // remove dashes from the end of the string + s = regexp.MustCompile("-+$").ReplaceAllString(s, "") + return s +} diff --git a/resources/output/virtual_machine/gcp_virtual_machine.go b/resources/output/virtual_machine/gcp_virtual_machine.go index 7fca9882..13c9214f 100644 --- a/resources/output/virtual_machine/gcp_virtual_machine.go +++ b/resources/output/virtual_machine/gcp_virtual_machine.go @@ -11,13 +11,14 @@ import ( type GoogleComputeInstance struct { *common.GcpResource `hcl:",squash" default:"name=google_compute_instance"` - MachineType string `hcl:"machine_type"` - BootDisk GoogleBootDisk `hcl:"boot_disk"` - Zone string `hcl:"zone" hcle:"omitempty"` - Tags []string `hcl:"tags" hcle:"omitempty"` - MetadataStartupScript string `hcl:"metadata_startup_script" hcle:"omitempty"` - NetworkInterface []GoogleNetworkInterface `hcl:"network_interface,blocks" json:"network_interface"` - Metadata map[string]string `hcl:"metadata" hcle:"omitempty"` + MachineType string `hcl:"machine_type"` + BootDisk GoogleBootDisk `hcl:"boot_disk"` + Zone string `hcl:"zone" hcle:"omitempty"` + Tags []string `hcl:"tags" hcle:"omitempty"` + MetadataStartupScript string `hcl:"metadata_startup_script" hcle:"omitempty"` + NetworkInterface []GoogleNetworkInterface `hcl:"network_interface,blocks" json:"network_interface"` + Metadata map[string]string `hcl:"metadata" hcle:"omitempty"` + ServiceAccount GoogleComputeInstanceServiceAccount `hcl:"service_account"` } type GoogleBootDisk struct { @@ -41,6 +42,11 @@ type GoogleNetworkInterfaceAccessConfig struct { NatIp string `hcl:"nat_ip,expr" hcle:"omitempty" json:"nat_ip"` } +type GoogleComputeInstanceServiceAccount struct { + Email string `hcl:"email,expr"` + Scopes []string `hcl:"scopes"` +} + func GetLatestGcpImage(ref *resourcespb.ImageReference) (string, error) { switch ref.Os { case resourcespb.ImageReference_UBUNTU: diff --git a/resources/types/gcp/kubernetes_cluster.go b/resources/types/gcp/kubernetes_cluster.go index 9bdefc3d..49661250 100644 --- a/resources/types/gcp/kubernetes_cluster.go +++ b/resources/types/gcp/kubernetes_cluster.go @@ -153,7 +153,7 @@ func (r GcpKubernetesCluster) Translate(ctx resources.MultyContext) ([]output.Tf } func (r GcpKubernetesCluster) getServiceAccountId() string { - return common.UniqueId(r.Args.Name, "-sa-", common.AlphanumericFormatFunc) + return common.UniqueId(r.Args.Name, "-sa-", common.LowercaseAlphanumericAndDashFormatFunc) } func (r GcpKubernetesCluster) GetMainResourceName() (string, error) { diff --git a/resources/types/gcp/virtual_machine.go b/resources/types/gcp/virtual_machine.go index 2e10d7c3..06f3193d 100644 --- a/resources/types/gcp/virtual_machine.go +++ b/resources/types/gcp/virtual_machine.go @@ -9,6 +9,7 @@ import ( "github.com/multycloud/multy/resources" "github.com/multycloud/multy/resources/common" "github.com/multycloud/multy/resources/output" + "github.com/multycloud/multy/resources/output/iam" "github.com/multycloud/multy/resources/output/subnet" "github.com/multycloud/multy/resources/output/virtual_machine" "github.com/multycloud/multy/resources/types" @@ -117,6 +118,13 @@ func (r GcpVirtualMachine) Translate(resources.MultyContext) ([]output.TfBlock, } } + serviceAccountId := r.getServiceAccountId() + serviceAccount := &iam.GoogleServiceAccount{ + GcpResource: common.NewGcpResource(serviceAccountId, "", r.Args.GetGcpOverride().GetProject()), + AccountId: serviceAccountId, + DisplayName: fmt.Sprintf("Service Account for VM %s", r.Args.Name), + } + vm := &virtual_machine.GoogleComputeInstance{ GcpResource: common.NewGcpResource(r.ResourceId, r.Args.Name, r.Args.GetGcpOverride().GetProject()), MachineType: size, @@ -129,10 +137,18 @@ func (r GcpVirtualMachine) Translate(resources.MultyContext) ([]output.TfBlock, }, Metadata: m, NetworkInterface: []virtual_machine.GoogleNetworkInterface{networkInterface}, + ServiceAccount: virtual_machine.GoogleComputeInstanceServiceAccount{ + Email: fmt.Sprintf("%s.%s.email", output.GetResourceName(iam.GoogleServiceAccount{}), serviceAccountId), + Scopes: []string{"cloud-platform"}, + }, } - return []output.TfBlock{vm}, nil + return []output.TfBlock{serviceAccount, vm}, nil } func (r GcpVirtualMachine) GetMainResourceName() (string, error) { return output.GetResourceName(virtual_machine.GoogleComputeInstance{}), nil } + +func (r GcpVirtualMachine) getServiceAccountId() string { + return common.UniqueId(fmt.Sprintf("%s-%s", r.Args.Name, r.ResourceId), "-sa-", common.LowercaseAlphanumericAndDashFormatFunc) +} diff --git a/test/_configs/virtual_machine/virtual_machine/main.tf b/test/_configs/virtual_machine/virtual_machine/main.tf index 73cbd3b4..c41cc69d 100644 --- a/test/_configs/virtual_machine/virtual_machine/main.tf +++ b/test/_configs/virtual_machine/virtual_machine/main.tf @@ -257,6 +257,12 @@ resource "azurerm_linux_virtual_machine" "vm_azure" { } computer_name = "testvm" } +resource "google_service_account" "test-vm-vmgcp-sa-dvl7" { + project = "multy-project" + account_id = "test-vm-vmgcp-sa-dvl7" + display_name = "Service Account for VM test-vm" + provider = "google.europe-west1" +} resource "google_compute_instance" "vm_gcp" { name = "test-vm" machine_type = "e2-micro" @@ -273,6 +279,10 @@ resource "google_compute_instance" "vm_gcp" { metadata = { "user-data" = "echo 'Hello World'" } provider = "google.europe-west1" project = "multy-project" + service_account { + email = google_service_account.test-vm-vmgcp-sa-dvl7.email + scopes = ["cloud-platform"] + } } provider "aws" { region = "eu-west-1" diff --git a/test/_configs/virtual_machine/virtual_machine_images/main.tf b/test/_configs/virtual_machine/virtual_machine_images/main.tf index ca3c3059..2de166c7 100644 --- a/test/_configs/virtual_machine/virtual_machine_images/main.tf +++ b/test/_configs/virtual_machine/virtual_machine_images/main.tf @@ -326,7 +326,12 @@ resource "google_compute_subnetwork" "subnet_gcp" { provider = "google.europe-west1" project = "multy-project" } - +resource "google_service_account" "test-vm-vm2gcp-sa-w48h" { + project = "multy-project" + account_id = "test-vm-vm2gcp-sa-w48h" + display_name = "Service Account for VM test-vm" + provider = "google.europe-west1" +} resource "google_compute_instance" "vm_gcp" { name = "test-vm" machine_type = "e2-medium" @@ -343,6 +348,10 @@ resource "google_compute_instance" "vm_gcp" { metadata = { "user-data" = "echo 'Hello World'" } provider = "google.europe-west1" project = "multy-project" + service_account { + email = google_service_account.test-vm-vmgcp-sa-dvl7.email + scopes = ["cloud-platform"] + } } resource "google_compute_network" "example_vn_gcp" { name = "example_gcp" @@ -353,6 +362,12 @@ resource "google_compute_network" "example_vn_gcp" { provider = "google.europe-west1" project = "multy-project" } +resource "google_service_account" "test-vm-vmgcp-sa-dvl7" { + project = "multy-project" + account_id = "test-vm-vmgcp-sa-dvl7" + display_name = "Service Account for VM test-vm" + provider = "google.europe-west1" +} resource "google_compute_instance" "vm2_gcp" { name = "test-vm" machine_type = "e2-micro" @@ -369,6 +384,10 @@ resource "google_compute_instance" "vm2_gcp" { metadata = {} provider = "google.europe-west1" project = "multy-project" + service_account { + email = google_service_account.test-vm-vm2gcp-sa-w48h.email + scopes = ["cloud-platform"] + } } provider "google" { region = "europe-west1" diff --git a/test/_configs/virtual_machine/virtual_machine_public_ip/main.tf b/test/_configs/virtual_machine/virtual_machine_public_ip/main.tf index 00f052ff..59668c57 100644 --- a/test/_configs/virtual_machine/virtual_machine_public_ip/main.tf +++ b/test/_configs/virtual_machine/virtual_machine_public_ip/main.tf @@ -265,6 +265,13 @@ resource "google_compute_subnetwork" "subnet_gcp" { project = "multy-project" } +resource "google_service_account" "test-vm-vmgcp-sa-dvl7" { + project = "multy-project" + account_id = "test-vm-vmgcp-sa-dvl7" + display_name = "Service Account for VM test-vm" + provider = "google.europe-west1" +} + resource "google_compute_instance" "vm_gcp" { name = "test-vm" machine_type = "e2-standard-2" @@ -287,6 +294,10 @@ resource "google_compute_instance" "vm_gcp" { } provider = "google.europe-west1" project = "multy-project" + service_account { + email = google_service_account.test-vm-vmgcp-sa-dvl7.email + scopes = ["cloud-platform"] + } } resource "google_compute_network" "example_vn_gcp" {