diff --git a/fast/stages/1-resman/README.md b/fast/stages/1-resman/README.md index 533b66b4f..d85829e00 100644 --- a/fast/stages/1-resman/README.md +++ b/fast/stages/1-resman/README.md @@ -273,29 +273,29 @@ A full reference of IAM roles managed by this stage [is available here](./IAM.md | [cicd_repositories](variables.tf#L20) | CI/CD repository configuration. Identity providers reference keys in the `automation.federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | | | [custom_roles](variables-fast.tf#L53) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [factories_config](variables.tf#L122) | Configuration for the resource factories or external data. | object({…}) | | {} | | -| [fast_features](variables.tf#L133) | Selective control for top-level FAST features. | object({…}) | | {} | | -| [folder_iam](variables.tf#L145) | Authoritative IAM for top-level folders. | object({…}) | | {} | | +| [fast_features](variables.tf#L133) | Selective control for top-level FAST features. | object({…}) | | {} | | +| [folder_iam](variables.tf#L146) | Authoritative IAM for top-level folders. | object({…}) | | {} | | | [groups](variables-fast.tf#L67) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | 0-bootstrap | | [locations](variables-fast.tf#L82) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap | -| [outputs_location](variables.tf#L159) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | +| [outputs_location](variables.tf#L160) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | | [root_node](variables-fast.tf#L132) | Root node for the hierarchy, if running in tenant mode. | string | | null | 0-bootstrap | -| [tag_names](variables.tf#L165) | Customized names for resource management tags. | object({…}) | | {} | | -| [tags](variables.tf#L179) | Custom secure tags by key name. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | | -| [top_level_folders](variables.tf#L200) | Additional top-level folders. Keys are used for service account and bucket names, values implement the folders module interface with the addition of the 'automation' attribute. | map(object({…})) | | {} | | +| [tag_names](variables.tf#L166) | Customized names for resource management tags. | object({…}) | | {} | | +| [tags](variables.tf#L180) | Custom secure tags by key name. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | | +| [top_level_folders](variables.tf#L201) | Additional top-level folders. Keys are used for service account and bucket names, values implement the folders module interface with the addition of the 'automation' attribute. | map(object({…})) | | {} | | ## Outputs | name | description | sensitive | consumers | |---|---|:---:|---| -| [cicd_repositories](outputs.tf#L374) | WIF configuration for CI/CD repositories. | | | -| [dataplatform](outputs.tf#L388) | Data for the Data Platform stage. | | | -| [folder_ids](outputs.tf#L404) | Folder ids. | | | -| [gcve](outputs.tf#L409) | Data for the GCVE stage. | | 03-gcve | -| [gke_multitenant](outputs.tf#L430) | Data for the GKE multitenant stage. | | 03-gke-multitenant | -| [networking](outputs.tf#L451) | Data for the networking stage. | | | -| [project_factories](outputs.tf#L460) | Data for the project factories stage. | | | -| [providers](outputs.tf#L479) | Terraform provider files for this stage and dependent stages. | ✓ | 02-networking · 02-security · 03-dataplatform · 03-network-security | -| [sandbox](outputs.tf#L486) | Data for the sandbox stage. | | xx-sandbox | -| [security](outputs.tf#L500) | Data for the networking stage. | | 02-security | -| [tfvars](outputs.tf#L511) | Terraform variable files for the following stages. | ✓ | | +| [cicd_repositories](outputs.tf#L376) | WIF configuration for CI/CD repositories. | | | +| [dataplatform](outputs.tf#L390) | Data for the Data Platform stage. | | | +| [folder_ids](outputs.tf#L406) | Folder ids. | | | +| [gcve](outputs.tf#L411) | Data for the GCVE stage. | | 03-gcve | +| [gke_multitenant](outputs.tf#L432) | Data for the GKE multitenant stage. | | 03-gke-multitenant | +| [networking](outputs.tf#L453) | Data for the networking stage. | | | +| [project_factories](outputs.tf#L462) | Data for the project factories stage. | | | +| [providers](outputs.tf#L481) | Terraform provider files for this stage and dependent stages. | ✓ | 02-networking · 02-security · 03-dataplatform · 03-network-security | +| [sandbox](outputs.tf#L488) | Data for the sandbox stage. | | xx-sandbox | +| [security](outputs.tf#L502) | Data for the networking stage. | | 02-security | +| [tfvars](outputs.tf#L513) | Terraform variable files for the following stages. | ✓ | | diff --git a/fast/stages/1-resman/branch-networking.tf b/fast/stages/1-resman/branch-networking.tf index ca2791d70..1fb575a71 100644 --- a/fast/stages/1-resman/branch-networking.tf +++ b/fast/stages/1-resman/branch-networking.tf @@ -18,20 +18,28 @@ locals { # FAST-specific IAM - _network_folder_fast_iam = { - # read-write (apply) automation service account - "roles/logging.admin" = [module.branch-network-sa.iam_email] - "roles/owner" = [module.branch-network-sa.iam_email] - "roles/resourcemanager.folderAdmin" = [module.branch-network-sa.iam_email] - "roles/resourcemanager.projectCreator" = [module.branch-network-sa.iam_email] - "roles/compute.xpnAdmin" = [module.branch-network-sa.iam_email] - # read-only (plan) automation service account - "roles/viewer" = [module.branch-network-r-sa.iam_email] - "roles/resourcemanager.folderViewer" = [module.branch-network-r-sa.iam_email] - # nsec service account - "roles/serviceusage.serviceUsageAdmin" = [module.branch-nsec-sa.iam_email] - (var.custom_roles["network_firewall_policies_admin"]) = [module.branch-nsec-sa.iam_email] - } + _network_folder_fast_iam = merge( + { + # read-write (apply) automation service account + "roles/logging.admin" = [module.branch-network-sa.iam_email] + "roles/owner" = [module.branch-network-sa.iam_email] + "roles/resourcemanager.folderAdmin" = [module.branch-network-sa.iam_email] + "roles/resourcemanager.projectCreator" = [module.branch-network-sa.iam_email] + "roles/compute.xpnAdmin" = [module.branch-network-sa.iam_email] + # read-only (plan) automation service account + "roles/viewer" = [module.branch-network-r-sa.iam_email] + "roles/resourcemanager.folderViewer" = [module.branch-network-r-sa.iam_email] + }, + var.fast_features.nsec != true ? {} : { + # nsec service account + "roles/serviceusage.serviceUsageAdmin" = [ + try(module.branch-nsec-sa[0].iam_email, null) + ] + (var.custom_roles["network_firewall_policies_admin"]) = [ + try(module.branch-nsec-sa[0].iam_email, null) + ] + } + ) # deep-merge FAST-specific IAM with user-provided bindings in var.folder_iam _network_folder_iam = merge( var.folder_iam.network, diff --git a/fast/stages/1-resman/branch-nsec.tf b/fast/stages/1-resman/branch-nsec.tf index 0fb0299c3..cb1c56cd1 100644 --- a/fast/stages/1-resman/branch-nsec.tf +++ b/fast/stages/1-resman/branch-nsec.tf @@ -18,8 +18,14 @@ # automation service account +moved { + from = module.branch-nsec-sa + to = module.branch-nsec-sa[0] +} + module "branch-nsec-sa" { source = "../../../modules/iam-service-account" + count = var.fast_features.nsec ? 1 : 0 project_id = var.automation.project_id name = "prod-resman-nsec-0" display_name = "Terraform resman network security service account." @@ -40,8 +46,14 @@ module "branch-nsec-sa" { # automation read-only service account +moved { + from = module.branch-nsec-r-sa + to = module.branch-nsec-r-sa[0] +} + module "branch-nsec-r-sa" { source = "../../../modules/iam-service-account" + count = var.fast_features.nsec ? 1 : 0 project_id = var.automation.project_id name = "prod-resman-nsec-0r" display_name = "Terraform resman network security service account (read-only)." @@ -61,8 +73,14 @@ module "branch-nsec-r-sa" { # automation bucket +moved { + from = module.branch-nsec-gcs + to = module.branch-nsec-gcs[0] +} + module "branch-nsec-gcs" { source = "../../../modules/gcs" + count = var.fast_features.nsec ? 1 : 0 project_id = var.automation.project_id name = "prod-resman-nsec-0" prefix = var.prefix @@ -70,7 +88,7 @@ module "branch-nsec-gcs" { storage_class = local.gcs_storage_class versioning = true iam = { - "roles/storage.objectAdmin" = [module.branch-nsec-sa.iam_email] - "roles/storage.objectViewer" = [module.branch-nsec-r-sa.iam_email] + "roles/storage.objectAdmin" = [module.branch-nsec-sa[0].iam_email] + "roles/storage.objectViewer" = [module.branch-nsec-r-sa[0].iam_email] } } diff --git a/fast/stages/1-resman/iam.tf b/fast/stages/1-resman/iam.tf index b396541ad..44706fe97 100644 --- a/fast/stages/1-resman/iam.tf +++ b/fast/stages/1-resman/iam.tf @@ -24,14 +24,6 @@ locals { member = module.branch-network-sa.iam_email role = "roles/compute.orgFirewallPolicyAdmin" } - sa_net_nsec_fw_policy_admin = { - member = module.branch-nsec-sa.iam_email - role = "roles/compute.orgFirewallPolicyAdmin" - } - sa_net_nsec_ngfw_enterprise_admin = { - member = module.branch-nsec-sa.iam_email - role = local.custom_roles["ngfw_enterprise_admin"], - } sa_net_xpn_admin = { member = module.branch-network-sa.iam_email role = "roles/compute.xpnAdmin" @@ -46,6 +38,17 @@ locals { # role = "roles/accesscontextmanager.policyAdmin" # } }, + # optional network security + var.fast_features.nsec != true ? {} : { + sa_net_nsec_fw_policy_admin = { + member = module.branch-nsec-sa[0].iam_email + role = "roles/compute.orgFirewallPolicyAdmin" + } + sa_net_nsec_ngfw_enterprise_admin = { + member = module.branch-nsec-sa[0].iam_email + role = local.custom_roles["ngfw_enterprise_admin"], + } + }, # optional billing roles for network and security local.billing_mode != "org" ? {} : { sa_net_billing = { diff --git a/fast/stages/1-resman/main.tf b/fast/stages/1-resman/main.tf index de21be519..80beb5b49 100644 --- a/fast/stages/1-resman/main.tf +++ b/fast/stages/1-resman/main.tf @@ -33,8 +33,8 @@ locals { gke-dev-r = try(module.branch-gke-dev-r-sa[0].email, null) gke-prod = try(module.branch-gke-prod-sa[0].email, null) gke-prod-r = try(module.branch-gke-prod-r-sa[0].email, null) - nsec = module.branch-nsec-sa.email - nsec-r = module.branch-nsec-r-sa.email + nsec = try(module.branch-nsec-sa[0].email, null) + nsec-r = try(module.branch-nsec-r-sa[0].email, null) networking = module.branch-network-sa.email networking-r = module.branch-network-r-sa.email project-factory = module.branch-pf-sa.email diff --git a/fast/stages/1-resman/outputs.tf b/fast/stages/1-resman/outputs.tf index a552c05ba..f640c3392 100644 --- a/fast/stages/1-resman/outputs.tf +++ b/fast/stages/1-resman/outputs.tf @@ -245,18 +245,6 @@ locals { name = "security" sa = module.branch-security-r-sa.email }) - "3-network-security" = templatefile(local._tpl_providers, { - backend_extra = null - bucket = module.branch-nsec-gcs.name - name = "network-security" - sa = module.branch-nsec-sa.email - }) - "3-network-security-r" = templatefile(local._tpl_providers, { - backend_extra = null - bucket = module.branch-network-gcs.name - name = "network-security" - sa = module.branch-nsec-r-sa.email - }) }, { for k, v in module.top-level-sa : @@ -345,6 +333,20 @@ locals { sa = module.branch-gcve-prod-r-sa[0].email }) }, + !var.fast_features.nsec ? {} : { + "3-network-security" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-nsec-gcs[0].name + name = "network-security" + sa = module.branch-nsec-sa[0].email + }) + "3-network-security-r" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-nsec-gcs[0].name + name = "network-security" + sa = module.branch-nsec-r-sa[0].email + }) + }, !var.fast_features.sandbox ? {} : { "9-sandbox" = templatefile(local._tpl_providers, { backend_extra = null diff --git a/fast/stages/1-resman/variables.tf b/fast/stages/1-resman/variables.tf index c111404f8..2d10a8d60 100644 --- a/fast/stages/1-resman/variables.tf +++ b/fast/stages/1-resman/variables.tf @@ -136,6 +136,7 @@ variable "fast_features" { data_platform = optional(bool, false) gke = optional(bool, false) gcve = optional(bool, false) + nsec = optional(bool, false) sandbox = optional(bool, false) }) default = {} diff --git a/tests/fast/stages/s1_resman/checklist.yaml b/tests/fast/stages/s1_resman/checklist.yaml index 2a1c0e3f5..c3208c0ba 100644 --- a/tests/fast/stages/s1_resman/checklist.yaml +++ b/tests/fast/stages/s1_resman/checklist.yaml @@ -416,18 +416,18 @@ values: counts: google_folder: 57 - google_folder_iam_binding: 76 - google_organization_iam_member: 16 - google_project_iam_member: 12 - google_service_account: 12 - google_service_account_iam_binding: 12 - google_storage_bucket: 6 - google_storage_bucket_iam_binding: 12 - google_storage_bucket_iam_member: 12 - google_storage_bucket_object: 13 + google_folder_iam_binding: 74 + google_organization_iam_member: 14 + google_project_iam_member: 10 + google_service_account: 10 + google_service_account_iam_binding: 10 + google_storage_bucket: 5 + google_storage_bucket_iam_binding: 10 + google_storage_bucket_iam_member: 10 + google_storage_bucket_object: 11 google_tags_tag_binding: 5 google_tags_tag_key: 2 google_tags_tag_value: 9 google_tags_tag_value_iam_binding: 2 - modules: 76 - resources: 246 + modules: 73 + resources: 229 diff --git a/tests/fast/stages/s1_resman/simple.yaml b/tests/fast/stages/s1_resman/simple.yaml index 25823e40d..6a2bd8830 100644 --- a/tests/fast/stages/s1_resman/simple.yaml +++ b/tests/fast/stages/s1_resman/simple.yaml @@ -42,18 +42,18 @@ values: counts: google_folder: 5 - google_folder_iam_binding: 30 - google_organization_iam_member: 16 - google_project_iam_member: 12 - google_service_account: 12 - google_service_account_iam_binding: 12 - google_storage_bucket: 6 - google_storage_bucket_iam_binding: 12 - google_storage_bucket_iam_member: 12 - google_storage_bucket_object: 13 + google_folder_iam_binding: 28 + google_organization_iam_member: 14 + google_project_iam_member: 10 + google_service_account: 10 + google_service_account_iam_binding: 10 + google_storage_bucket: 5 + google_storage_bucket_iam_binding: 10 + google_storage_bucket_iam_member: 10 + google_storage_bucket_object: 11 google_tags_tag_binding: 5 google_tags_tag_key: 2 google_tags_tag_value: 9 google_tags_tag_value_iam_binding: 2 - modules: 24 - resources: 148 + modules: 21 + resources: 131