From 9fa186fe9d75a84f50901df718d7eaab2000b543 Mon Sep 17 00:00:00 2001 From: Zef Delgadillo Date: Thu, 17 Sep 2020 15:16:41 -0400 Subject: [PATCH] feat: Add Dataflow to Shared VPC API service accounts --- examples/shared_vpc/main.tf | 1 + modules/shared_vpc_access/README.md | 3 ++- modules/shared_vpc_access/main.tf | 4 ++++ test/fixtures/full/main.tf | 1 + test/fixtures/shared_vpc_no_subnets/main.tf | 1 + test/integration/dynamic_shared_vpc/controls/svpc.rb | 9 +++++++++ test/integration/full/controls/shared-vpc.rb | 8 ++++++++ .../integration/shared_vpc_no_subnets/controls/gcloud.rb | 8 ++++++++ 8 files changed, 34 insertions(+), 1 deletion(-) diff --git a/examples/shared_vpc/main.tf b/examples/shared_vpc/main.tf index eb31a6b6..f0d96039 100644 --- a/examples/shared_vpc/main.tf +++ b/examples/shared_vpc/main.tf @@ -121,6 +121,7 @@ module "service-project" { "compute.googleapis.com", "container.googleapis.com", "dataproc.googleapis.com", + "dataflow.googleapis.com", ] disable_services_on_destroy = "false" diff --git a/modules/shared_vpc_access/README.md b/modules/shared_vpc_access/README.md index c452a78b..90c24aea 100644 --- a/modules/shared_vpc_access/README.md +++ b/modules/shared_vpc_access/README.md @@ -1,7 +1,7 @@ # Shared VPC Access This module grants IAM permissions on host project and subnets to appropriate API service accounts based on activated -APIs. For now only GKE and Dataproc APIs are supported. +APIs. For now only GKE, Dataproc and Dataflow APIs are supported. ## Example Usage ```hcl @@ -13,6 +13,7 @@ module "shared_vpc_access" { "compute.googleapis.com", "container.googleapis.com", "dataproc.googleapis.com", + "dataflow.googleapis.com", ] shared_vpc_subnets = [ "projects/pf-ci-shared2/regions/us-west1/subnetworks/shared-network-subnet-01", diff --git a/modules/shared_vpc_access/main.tf b/modules/shared_vpc_access/main.tf index d3d92f7e..487366e6 100644 --- a/modules/shared_vpc_access/main.tf +++ b/modules/shared_vpc_access/main.tf @@ -22,6 +22,7 @@ locals { apis = { "container.googleapis.com" : format("service-%s@container-engine-robot.iam.gserviceaccount.com", data.google_project.service_project.number), "dataproc.googleapis.com" : format("service-%s@dataproc-accounts.iam.gserviceaccount.com", data.google_project.service_project.number), + "dataflow.googleapis.com" : format("service-%s@dataflow-service-producer-prod.iam.gserviceaccount.com", data.google_project.service_project.number), } gke_shared_vpc_enabled = contains(var.active_apis, "container.googleapis.com") active_apis = setintersection(keys(local.apis), var.active_apis) @@ -31,7 +32,9 @@ locals { /****************************************** if "container.googleapis.com" compute.networkUser role granted to GKE service account for GKE on shared VPC subnets if "dataproc.googleapis.com" compute.networkUser role granted to dataproc service account for dataproc on shared VPC subnets + if "dataflow.googleapis.com" compute.networkUser role granted to dataflow service account for Dataflow on shared VPC subnets See: https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-shared-vpc + https://cloud.google.com/dataflow/docs/concepts/security-and-permissions#cloud_dataflow_service_account *****************************************/ resource "google_compute_subnetwork_iam_member" "service_shared_vpc_subnet_users" { provider = google-beta @@ -55,6 +58,7 @@ resource "google_compute_subnetwork_iam_member" "service_shared_vpc_subnet_users /****************************************** if "container.googleapis.com" compute.networkUser role granted to GKE service account for GKE on shared VPC Project if no subnets defined if "dataproc.googleapis.com" compute.networkUser role granted to dataproc service account for dataproc on shared VPC Project if no subnets defined + if "dataflow.googleapis.com" compute.networkUser role granted to dataflow service account for Dataflow on shared VPC Project if no subnets defined *****************************************/ resource "google_project_iam_member" "service_shared_vpc_user" { for_each = length(var.shared_vpc_subnets) == 0 ? local.active_apis : [] diff --git a/test/fixtures/full/main.tf b/test/fixtures/full/main.tf index 7d1ccf92..aacb49e8 100644 --- a/test/fixtures/full/main.tf +++ b/test/fixtures/full/main.tf @@ -121,6 +121,7 @@ module "project-factory" { activate_apis = [ "compute.googleapis.com", "container.googleapis.com", + "dataflow.googleapis.com", ] default_service_account = "delete" diff --git a/test/fixtures/shared_vpc_no_subnets/main.tf b/test/fixtures/shared_vpc_no_subnets/main.tf index 8c6d60dd..e8b8796c 100644 --- a/test/fixtures/shared_vpc_no_subnets/main.tf +++ b/test/fixtures/shared_vpc_no_subnets/main.tf @@ -60,6 +60,7 @@ module "project-factory" { activate_apis = [ "compute.googleapis.com", "container.googleapis.com", + "dataflow.googleapis.com", ] disable_services_on_destroy = "false" diff --git a/test/integration/dynamic_shared_vpc/controls/svpc.rb b/test/integration/dynamic_shared_vpc/controls/svpc.rb index 823bc91b..45f2cd19 100644 --- a/test/integration/dynamic_shared_vpc/controls/svpc.rb +++ b/test/integration/dynamic_shared_vpc/controls/svpc.rb @@ -124,6 +124,15 @@ end end + describe "roles/compute.networkUser" do + it "service project with explicit subnets includes the dataflow service account in the roles/compute.networkUser IAM binding" do + expect(bindings).to include( + members: including("serviceAccount:service-#{service_project_number}@dataflow-service-producer-prod.iam.gserviceaccount.com" + ), + role: "roles/compute.networkUser", + ) + end + end end describe command("gcloud beta compute networks subnets get-iam-policy #{shared_vpc_subnet_name_02} --region #{shared_vpc_subnet_region_02} --project #{shared_vpc} --format=json") do diff --git a/test/integration/full/controls/shared-vpc.rb b/test/integration/full/controls/shared-vpc.rb index 37e62dc9..b970c084 100644 --- a/test/integration/full/controls/shared-vpc.rb +++ b/test/integration/full/controls/shared-vpc.rb @@ -74,6 +74,14 @@ ) end + it "does not include the dataflow service account in the roles/compute.networkUser IAM binding" do + expect(bindings).not_to include( + members: including("serviceAccount:service-#{project_number}@dataflow-service-producer-prod.iam.gserviceaccount.com" + ), + role: "roles/compute.networkUser", + ) + end + it "does not overwrite the membership of roles/compute.networkUser" do expect(bindings).to include( members: including("serviceAccount:#{extra_service_account_email}"), diff --git a/test/integration/shared_vpc_no_subnets/controls/gcloud.rb b/test/integration/shared_vpc_no_subnets/controls/gcloud.rb index f848021c..f561e16e 100644 --- a/test/integration/shared_vpc_no_subnets/controls/gcloud.rb +++ b/test/integration/shared_vpc_no_subnets/controls/gcloud.rb @@ -62,6 +62,14 @@ role: "roles/compute.networkUser", ) end + + it "includes the Dataflow service account in the roles/compute.networkUser IAM binding" do + expect(bindings).to include( + members: including("serviceAccount:service-#{project_number}@dataflow-service-producer-prod.iam.gserviceaccount.com" + ), + role: "roles/compute.networkUser", + ) + end end end end