From 1b8eed32a835997c88f0ce18ea89e11dda4356c3 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Fri, 15 Dec 2023 10:40:36 +0100 Subject: [PATCH] small fixes --- .../factories/project-factory/README.md | 6 ++-- .../factories/project-factory/factory.tf | 10 +++---- .../factories/project-factory/variables.tf | 12 ++++---- modules/project/README.md | 28 +++++++++---------- modules/project/shared-vpc.tf | 26 ++++++++--------- modules/project/variables.tf | 19 +++++++------ 6 files changed, 50 insertions(+), 51 deletions(-) diff --git a/blueprints/factories/project-factory/README.md b/blueprints/factories/project-factory/README.md index f49e3f94f4..67081df2e2 100644 --- a/blueprints/factories/project-factory/README.md +++ b/blueprints/factories/project-factory/README.md @@ -108,11 +108,11 @@ shared_vpc_service_config: - cloudrun "roles/container.hostServiceAgentUser": - container-engine - service_identity_subnets_iam: + service_identity_subnet_iam: europe-west1/prod-default-ew1: - cloudservices - container-engine - subnets_iam: + network_subnet_users: europe-west1/prod-default-ew1: - group:team-1@example.com @@ -134,7 +134,7 @@ services: | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [factory_data_path](variables.tf#L91) | Path to folder with YAML project description data files. | string | ✓ | | -| [data_defaults](variables.tf#L17) | Optional default values used when corresponding project data from files are missing. | object({…}) | | {} | +| [data_defaults](variables.tf#L17) | Optional default values used when corresponding project data from files are missing. | object({…}) | | {} | | [data_merges](variables.tf#L49) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} | | [data_overrides](variables.tf#L69) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | diff --git a/blueprints/factories/project-factory/factory.tf b/blueprints/factories/project-factory/factory.tf index bb90a82da8..4028186caf 100644 --- a/blueprints/factories/project-factory/factory.tf +++ b/blueprints/factories/project-factory/factory.tf @@ -79,11 +79,11 @@ locals { try(v.shared_vpc_service_config, null) != null ? merge( { - host_project_iam = [] - service_identity_iam = {} - service_identity_subnets_iam = {} - service_iam_grants = [] - subnets_iam = {} + network_users = [] + service_identity_iam = {} + service_identity_subnet_iam = {} + service_iam_grants = [] + network_subnet_users = {} }, v.shared_vpc_service_config ) diff --git a/blueprints/factories/project-factory/variables.tf b/blueprints/factories/project-factory/variables.tf index 08e7e8d71b..d37f939928 100644 --- a/blueprints/factories/project-factory/variables.tf +++ b/blueprints/factories/project-factory/variables.tf @@ -28,12 +28,12 @@ variable "data_defaults" { service_perimeter_standard = optional(string) services = optional(list(string), []) shared_vpc_service_config = optional(object({ - host_project = string - host_project_iam = optional(list(string), []) - service_identity_iam = optional(map(list(string)), {}) - service_identity_subnets_iam = optional(map(list(string)), {}) - service_iam_grants = optional(list(string), []) - subnets_iam = optional(map(list(string)), {}) + host_project = string + network_users = optional(list(string), []) + service_identity_iam = optional(map(list(string)), {}) + service_identity_subnet_iam = optional(map(list(string)), {}) + service_iam_grants = optional(list(string), []) + network_subnet_users = optional(map(list(string)), {}) }), { host_project = null }) tag_bindings = optional(map(string), {}) # non-project resources diff --git a/modules/project/README.md b/modules/project/README.md index dd570aa4c8..129d9bf360 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -233,7 +233,7 @@ The module allows managing Shared VPC status for both hosts and service projects Project service association for VPC host projects can be - authoritatively managed in the host project by enabling Shared VPC and specifying the set of service projects, or -- additively managed in service projects by by enabling Shared VPC in the host project and then "attaching" each service project independently +- additively managed in service projects by enabling Shared VPC in the host project and then "attaching" each service project independently IAM bindings in the host project for API service identities can be managed from service projects in two different ways: @@ -317,9 +317,9 @@ module "service-project" { # tftest modules=2 resources=9 inventory=shared-vpc-auto-grants.yaml e2e ``` -The 'networkUser' role for identities other than API services (e.g. users, groups or service accounts) can be managed via the `host_project_iam` attribute, by specifying the list of identities. +The `compute.networkUser` role for identities other than API services (e.g. users, groups or service accounts) can be managed via the `network_users` attribute, by specifying the list of identities. -Note that this configuration grants the 'networkUser' role at project level which results in the identity being able to configure resources on all the VPCs and subnets belonging to the host project without further restrictions. It is possible, or better recommended, to restrict which subnets can be used on the newly created project using an Org Policy. The latter applied at project level can restrict access to a list of subnets from the host project. For more information on the Org Policy configuration check the corresponding [Organization Policy section](#organization-policies). The following example details this configuration. +Note that this configuration grants the role at project level which results in the identities being able to configure resources on all the VPCs and subnets belonging to the host project. The most reliable way to restrict which subnets can be used on the newly created project is via the `compute.restrictSharedVpcSubnetworks` organization policy. For more information on the Org Policy configuration check the corresponding [Organization Policy section](#organization-policies). The following example details this configuration. ```hcl module "host-project" { @@ -352,8 +352,8 @@ module "service-project" { "container.googleapis.com", ] shared_vpc_service_config = { - host_project = module.host-project.project_id - host_project_iam = ["group:team-1@example.com"] + host_project = module.host-project.project_id + network_users = ["group:team-1@example.com"] # reuse the list of services from the module's outputs service_iam_grants = module.service-project.services } @@ -361,9 +361,7 @@ module "service-project" { # tftest modules=2 resources=11 inventory=shared-vpc-host-project-iam.yaml e2e ``` -In specific cases it might make sense to selectively grant the `compute.networkUser` role for all kind of identities at the subnet level, although you can restrict access via org policies this is also supported by this module. - -In this example, Compute service identity and `team-1@example.com` Google Group will be granted compute.networkUser in the `gce` subnet defined in `europe-west1` region via the `service_identity_subnets_iam` and `subnets_iam` attributes. +In specific cases it might make sense to selectively grant the `compute.networkUser` role for service identities at the subnet level, and while that is best done via org policies it's also supported by this module. In this example, Compute service identity and `team-1@example.com` Google Group will be granted compute.networkUser in the `gce` subnet defined in `europe-west1` region via the `service_identity_subnet_iam` and `network_subnet_users` attributes. ```hcl module "host-project" { @@ -388,10 +386,10 @@ module "service-project" { ] shared_vpc_service_config = { host_project = module.host-project.project_id - service_identity_subnets_iam = { + service_identity_subnet_iam = { "europe-west1/gce" = ["compute"] } - subnets_iam = { + network_subnet_users = { "europe-west1/gce" = ["group:team-1@example.com"] } } @@ -439,10 +437,10 @@ module "service-project" { service_identity_iam = { "roles/container.hostServiceAgentUser" = ["container-engine"] } - service_identity_subnets_iam = { + service_identity_subnet_iam = { "europe-west1/gce" = ["cloudservices", "container-engine"] } - subnets_iam = { + network_subnet_users = { "europe-west1/gce" = ["group:team-1@example.com"] } } @@ -1027,9 +1025,9 @@ module "bucket" { | [service_perimeter_standard](variables.tf#L280) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | string | | null | | [services](variables.tf#L286) | Service APIs to enable. | list(string) | | [] | | [shared_vpc_host_config](variables.tf#L292) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…}) | | null | -| [shared_vpc_service_config](variables.tf#L301) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} | -| [skip_delete](variables.tf#L328) | Allows the underlying resources to be destroyed without destroying the project itself. | bool | | false | -| [tag_bindings](variables.tf#L334) | Tag bindings for this project, in key => tag value id format. | map(string) | | null | +| [shared_vpc_service_config](variables.tf#L301) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} | +| [skip_delete](variables.tf#L329) | Allows the underlying resources to be destroyed without destroying the project itself. | bool | | false | +| [tag_bindings](variables.tf#L335) | Tag bindings for this project, in key => tag value id format. | map(string) | | null | ## Outputs diff --git a/modules/project/shared-vpc.tf b/modules/project/shared-vpc.tf index b6c175de59..6e93b4d507 100644 --- a/modules/project/shared-vpc.tf +++ b/modules/project/shared-vpc.tf @@ -55,8 +55,8 @@ locals { "${b.role}:${b.service}" => b } # normalize the service identity subnet IAM bindings - _svpc_service_subnets_iam = flatten([ - for subnet, services in local._svpc.service_identity_subnets_iam : [ + _svpc_service_subnet_iam = flatten([ + for subnet, services in local._svpc.service_identity_subnet_iam : [ for service in services : [{ region = split("/", subnet)[0] subnet = split("/", subnet)[1] @@ -64,16 +64,16 @@ locals { }] ] ]) - svpc_service_subnets_iam = { - for v in local._svpc_service_subnets_iam : + svpc_service_subnet_iam = { + for v in local._svpc_service_subnet_iam : "${v.region}:${v.subnet}:${v.service}" => v } - # normalize the service identity subnet IAM bindings - _svpc_subnets_iam = ( - local._svpc.subnets_iam == null || local._svpc.host_project == null + # normalize the network user subnet IAM binding + _svpc_network_user_subnet_iam = ( + local._svpc.network_subnet_users == null || local._svpc.host_project == null ? [] : flatten([ - for subnet, members in local._svpc.subnets_iam : [ + for subnet, members in local._svpc.network_subnet_users : [ for member in members : { region = split("/", subnet)[0] subnet = split("/", subnet)[1] @@ -82,8 +82,8 @@ locals { ] ]) ) - svpc_subnets_iam = { - for v in local._svpc_subnets_iam : + svpc_network_user_subnet_iam = { + for v in local._svpc_network_user_subnet_iam : "${v.region}:${v.subnet}:${v.member}" => v } } @@ -130,7 +130,7 @@ resource "google_project_iam_member" "shared_vpc_host_robots" { } resource "google_project_iam_member" "shared_vpc_host_iam" { - for_each = toset(var.shared_vpc_service_config.host_project_iam) + for_each = toset(var.shared_vpc_service_config.network_users) project = var.shared_vpc_service_config.host_project role = "roles/compute.networkUser" member = each.value @@ -138,7 +138,7 @@ resource "google_project_iam_member" "shared_vpc_host_iam" { } resource "google_compute_subnetwork_iam_member" "shared_vpc_host_robots" { - for_each = local.svpc_service_subnets_iam + for_each = local.svpc_service_subnet_iam project = var.shared_vpc_service_config.host_project region = each.value.region subnetwork = each.value.subnet @@ -159,7 +159,7 @@ resource "google_compute_subnetwork_iam_member" "shared_vpc_host_robots" { } resource "google_compute_subnetwork_iam_member" "shared_vpc_host_subnets_iam" { - for_each = local.svpc_subnets_iam + for_each = local.svpc_network_user_subnet_iam project = var.shared_vpc_service_config.host_project region = each.value.region subnetwork = each.value.subnet diff --git a/modules/project/variables.tf b/modules/project/variables.tf index 713fcee5c2..064dd275d0 100644 --- a/modules/project/variables.tf +++ b/modules/project/variables.tf @@ -302,12 +302,12 @@ variable "shared_vpc_service_config" { description = "Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config)." # the list of valid service identities is in service-agents.yaml type = object({ - host_project = string - host_project_iam = optional(list(string), []) - service_identity_iam = optional(map(list(string)), {}) - service_identity_subnets_iam = optional(map(list(string)), {}) - service_iam_grants = optional(list(string), []) - subnets_iam = optional(map(list(string)), {}) + host_project = string + network_users = optional(list(string), []) + service_identity_iam = optional(map(list(string)), {}) + service_identity_subnet_iam = optional(map(list(string)), {}) + service_iam_grants = optional(list(string), []) + network_subnet_users = optional(map(list(string)), {}) }) default = { host_project = null @@ -316,12 +316,13 @@ variable "shared_vpc_service_config" { validation { condition = var.shared_vpc_service_config.host_project != null || ( var.shared_vpc_service_config.host_project == null && - length(var.shared_vpc_service_config.host_project_iam) == 0 && + length(var.shared_vpc_service_config.network_users) == 0 && length(var.shared_vpc_service_config.service_iam_grants) == 0 && length(var.shared_vpc_service_config.service_identity_iam) == 0 && - length(var.shared_vpc_service_config.subnets_iam) == 0 + length(var.shared_vpc_service_config.service_identity_subnet_iam) == 0 && + length(var.shared_vpc_service_config.network_subnet_users) == 0 ) - error_message = "You need to provide host_project when providing shared vpc host and subnets iam permissions." + error_message = "You need to provide host_project when providing Shared VPC host and subnet IAM permissions." } }