From 489b21f8cc836b47e00ad3664acd914335abb86a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 13 Oct 2025 18:52:54 +0200 Subject: [PATCH] fix ngfw add-on instructions (#3409) --- fast/addons/2-networking-ngfw/.fast-stage.env | 2 +- fast/addons/2-networking-ngfw/README.md | 87 +++++++++++++++---- fast/addons/README.md | 59 +++++++------ fast/stages/0-org-setup/README.md | 2 +- fast/stages/0-org-setup/cicd.tf | 3 +- fast/stages/0-org-setup/data | 1 - .../classic/organization/.config.yaml | 4 +- fast/stages/0-org-setup/variables.tf | 12 +-- .../fast/stages/s0_org_setup/not-simple.yaml | 11 ++- 9 files changed, 122 insertions(+), 59 deletions(-) delete mode 120000 fast/stages/0-org-setup/data diff --git a/fast/addons/2-networking-ngfw/.fast-stage.env b/fast/addons/2-networking-ngfw/.fast-stage.env index df0ad0839..c5d9254f6 100644 --- a/fast/addons/2-networking-ngfw/.fast-stage.env +++ b/fast/addons/2-networking-ngfw/.fast-stage.env @@ -1,5 +1,5 @@ FAST_STAGE_DESCRIPTION="NGFW Enterprise networking add-on" FAST_STAGE_LEVEL=2 FAST_STAGE_NAME=networking-ngfw -FAST_STAGE_DEPS="0-globals 0-org-setup 1-resman 2-networking" +FAST_STAGE_DEPS="0-globals 0-org-setup 2-networking" FAST_STAGE_OPTIONAL="2-security" \ No newline at end of file diff --git a/fast/addons/2-networking-ngfw/README.md b/fast/addons/2-networking-ngfw/README.md index 77bd11d7d..bc534c513 100644 --- a/fast/addons/2-networking-ngfw/README.md +++ b/fast/addons/2-networking-ngfw/README.md @@ -30,22 +30,78 @@ The controlling project is usually one of those already created and managed by t ## How to run this stage -Once the main networking stage has been configured and applied, the following configuration is added the the resource management `fast_addon` variable to create the add-on provider files, and its optional CI/CD resources if those are also required. The add-on name (`networking-ngfw`) is customizable, in case the add-on needs to be run multiple times for example to create different sets of endpoints and NGFW configurations per environment. +Once the main networking stage has been configured and applied, the following configuration is added to the org setup stage. -```hcl -fast_addon = { - networking-ngfw = { - parent_stage = "2-networking" - # cicd_config = { - # identity_provider = "github-test" - # repository = { - # name = "test/ngfw" - # type = "github" - # branch = "main" - # } - # } - } -} +First, the new provider file is declared in the `defaults.yaml` file. + +```yaml +# defaults.yaml (snippet) + +output_files: + # ... + providers: + # ... + 2-networking-ngfw: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 2-networking-ngfw + service_account: $iam_principals:service_accounts/iac-0/iac-networking-rw + +``` + +Then, the GCS folder (shown here) or bucket for the Terraform state is defined in the IaC project. + +```yaml +# projects/iac-0.yaml +buckets: + # ... + iac-stage-state: + description: Terraform state for stage automation. + managed_folders: + # ... + 2-networking-ngfw: + iam: + roles/storage.admin: + - $iam_principals:service_accounts/iac-0/iac-networking-rw + $custom_roles:storage_viewer: + - $iam_principals:service_accounts/iac-0/iac-networking-ro + +``` + +And finally, grant extra roles at the organization level to the networking service accounts. + +```yaml +# organization/.config.yaml +iam_by_principals: + # ... + $iam_principals:service_accounts/iac-0/iac-networking-rw: + - roles/compute.orgFirewallPolicyAdmin + - roles/compute.xpnAdmin + # add the custom role + - $custom_roles:ngfw_enterprise_admin + $iam_principals:service_accounts/iac-0/iac-networking-ro: + - roles/compute.orgFirewallPolicyUser + - roles/compute.viewer + # add the custom role + - $custom_roles:ngfw_enterprise_viewer +``` + +If VPC-SC is used, an additional ingress policy needs to be added to the perimeter to allow the NGFW service agent to reach the Certificate Authority Service. Edit and enable the following policy. + +```yaml +from: + access_levels: + - "*" + identities: + # TODO: change to actual NGFW service identity + - serviceAccount:service-1234567890@gcp-sa-networksecurity.iam.gserviceaccount.com +to: + operations: + - method_selectors: + - "*" + service_name: privateca.googleapis.com + resources: + # TODO: change to project number where CAS lives + - projects/1234567890 ``` ### Provider and Terraform variables @@ -64,7 +120,6 @@ ln -s ~/fast-config/providers/2-networking-ngfw-providers.tf ./ # input files from other stages ln -s ~/fast-config/tfvars/0-globals.auto.tfvars.json ./ ln -s ~/fast-config/tfvars/0-org-setup.auto.tfvars.json ./ -ln -s ~/fast-config/tfvars/1-resman.auto.tfvars.json ./ ln -s ~/fast-config/tfvars/2-networking.auto.tfvars.json ./ # conventional place for stage tfvars (manually created) diff --git a/fast/addons/README.md b/fast/addons/README.md index aadb6960c..8e2746ab6 100644 --- a/fast/addons/README.md +++ b/fast/addons/README.md @@ -4,39 +4,42 @@ Each of the folders contained here is a separate "add-on" that can be used to ad Add-ons can be thought of as additional thin layers on top of a stage, that reuse its IaC resources and leverage the same IAM configuration: the same service accounts are used to run the add-on, and state configuration is stored in the same bucket as their "parent stage" under a different prefix. -The only dedicated resources that can be optionally defined for add-ons are to enable CI/CD functionality, so that a dedicated repository can be used to host the add-on code and pipeline. - -Add-ons are currently only implemented for stage 1 (resource management and VPC-SC), and stage 2 (networking, project factory, security). - ## Add-on configuration -To configure an add-on: +To configure an add-on, once you have identified its "parent stage" (networking, security, etc.) you have to configure the org setup stage so that its providers file, and associated GCS resources to host the state file, are created. The following example configures resources for the NGFW Networking add-on. -- its "parent stage" (the stage the add-on augments) needs to be enabled and applied, so that the IaC and IAM configurations the add-on uses are present -- the `fast_addon` variable in the stage controlling the "parent stage" (boostrap for a stage 1 add-on, resource management for a stage 2 add-on) is configured and the stage applied, so that the add-on provider and optional CI/CD resources are created -- the provider and relevant FAST output variable files are linked or copied in the add-on folder (e.g. via the `fast-links.sh` script) +First, the new provider file is declared in the `defaults.yaml` file. -At this point the add-on can be run, and operate on the same folders, projects and resources controlled by its "parent stage". +```yaml +# defaults.yaml (snippet) -Add-ons typically generate their own FAST output variable files, which can be optionally consumed by downstream stages. +output_files: + # ... + providers: + # ... + 2-networking-ngfw: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 2-networking-ngfw + service_account: $iam_principals:service_accounts/iac-0/iac-networking-rw -This is an example configuration of the `fast_addon` variable in the resource management stage, to enable running the NGFW networking add-on. The CI/CD configuration block is optional, and commented out here. - -```hcl -fast_addon = { - networking-ngfw = { - parent_stage = "2-networking" - # cicd_config = { - # identity_provider = "github-test" - # repository = { - # name = "test/ngfw" - # type = "github" - # branch = "main" - # } - # } - } -} ``` -This configuration will create `tfvars/2-networking-ngfw-providers.tf` and -`tfvars/2-networking-ngfw-r-providers.tf` provider files in the GCS output bucket and local folder (if configured). +Then, the GCS folder (shown here) or bucket for the Terraform state is defined in the IaC project. + +```yaml +# projects/iac-0.yaml +buckets: + # ... + iac-stage-state: + description: Terraform state for stage automation. + managed_folders: + # ... + 2-networking-ngfw: + iam: + roles/storage.admin: + - $iam_principals:service_accounts/iac-0/iac-networking-rw + $custom_roles:storage_viewer: + - $iam_principals:service_accounts/iac-0/iac-networking-ro +``` + +Once the org setup stage is ready and applied, the add-on can be run using the generated provider files. The `fast-links.sh` can be used to link or copy the relevant files to the add-on, in the same way it's used for regular stages. diff --git a/fast/stages/0-org-setup/README.md b/fast/stages/0-org-setup/README.md index 4eea4a287..ef0b6cc21 100644 --- a/fast/stages/0-org-setup/README.md +++ b/fast/stages/0-org-setup/README.md @@ -654,7 +654,7 @@ Define values for the `var.environments` variable in a tfvars file. | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} | -| [factories_config](variables.tf#L37) | Configuration for the resource factories or external data. | object({…}) | | {} | +| [factories_config](variables.tf#L37) | Configuration for the resource factories or external data. | object({…}) | | {} | | [org_policies_imports](variables.tf#L52) | List of org policies to import. These need to also be defined in data files. | list(string) | | [] | ## Outputs diff --git a/fast/stages/0-org-setup/cicd.tf b/fast/stages/0-org-setup/cicd.tf index 410042a70..20a59593b 100644 --- a/fast/stages/0-org-setup/cicd.tf +++ b/fast/stages/0-org-setup/cicd.tf @@ -26,7 +26,8 @@ locals { } cicd_project_ids = { for k, v in merge( - var.context.project_ids, module.factory.project_ids + var.context.project_ids, + module.factory.project_ids ) : "$project_ids:${k}" => v } cicd_workflows = { diff --git a/fast/stages/0-org-setup/data b/fast/stages/0-org-setup/data deleted file mode 120000 index bbbb65f5a..000000000 --- a/fast/stages/0-org-setup/data +++ /dev/null @@ -1 +0,0 @@ -datasets/classic \ No newline at end of file diff --git a/fast/stages/0-org-setup/datasets/classic/organization/.config.yaml b/fast/stages/0-org-setup/datasets/classic/organization/.config.yaml index 71c916172..d1bb3e90a 100644 --- a/fast/stages/0-org-setup/datasets/classic/organization/.config.yaml +++ b/fast/stages/0-org-setup/datasets/classic/organization/.config.yaml @@ -14,7 +14,7 @@ # TODO: data access logs -# yaml-language-server: $schema=../../../schemas/organization.schema.json +# yaml-language-server: $schema=../../schemas/organization.schema.json id: $defaults:organization/id contacts: @@ -83,7 +83,7 @@ iam_by_principals: - roles/compute.xpnAdmin $iam_principals:service_accounts/iac-0/iac-networking-ro: - roles/compute.orgFirewallPolicyUser - - roles/compute.xpnAdmin + - roles/compute.viewer $iam_principals:service_accounts/iac-0/iac-security-rw: - roles/cloudasset.viewer $iam_principals:service_accounts/iac-0/iac-vpcsc-rw: diff --git a/fast/stages/0-org-setup/variables.tf b/fast/stages/0-org-setup/variables.tf index 725e59c6b..99b2057ae 100644 --- a/fast/stages/0-org-setup/variables.tf +++ b/fast/stages/0-org-setup/variables.tf @@ -37,13 +37,13 @@ variable "context" { variable "factories_config" { description = "Configuration for the resource factories or external data." type = object({ - billing_accounts = optional(string, "data/billing-accounts") + billing_accounts = optional(string, "datasets/classic/billing-accounts") cicd = optional(string) - defaults = optional(string, "data/defaults.yaml") - folders = optional(string, "data/folders") - organization = optional(string, "data/organization") - project_templates = optional(string, "data/templates") - projects = optional(string, "data/projects") + defaults = optional(string, "datasets/classic/defaults.yaml") + folders = optional(string, "datasets/classic/folders") + organization = optional(string, "datasets/classic/organization") + project_templates = optional(string, "datasets/classic/templates") + projects = optional(string, "datasets/classic/projects") }) nullable = false default = {} diff --git a/tests/fast/stages/s0_org_setup/not-simple.yaml b/tests/fast/stages/s0_org_setup/not-simple.yaml index 21773b6e5..78f2f91be 100644 --- a/tests/fast/stages/s0_org_setup/not-simple.yaml +++ b/tests/fast/stages/s0_org_setup/not-simple.yaml @@ -2399,10 +2399,15 @@ values: condition: [] members: - group:fabric-fast-owners@google.com - - serviceAccount:iac-networking-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com - serviceAccount:iac-networking-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com org_id: '1234567890' role: roles/compute.xpnAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/compute.viewer"]: + condition: [] + members: + - serviceAccount:iac-networking-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/compute.viewer module.organization-iam[0].google_organization_iam_binding.authoritative["roles/essentialcontacts.admin"]: condition: [] members: @@ -2772,7 +2777,7 @@ counts: google_logging_project_bucket_config: 3 google_org_policy_custom_constraint: 1 google_org_policy_policy: 37 - google_organization_iam_binding: 35 + google_organization_iam_binding: 36 google_organization_iam_custom_role: 9 google_project: 3 google_project_iam_binding: 16 @@ -2793,5 +2798,5 @@ counts: google_tags_tag_value_iam_binding: 4 local_file: 9 modules: 46 - resources: 310 + resources: 311 terraform_data: 2