* new 2-secops stage * new 3-secops-dev stage --------- Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com>
SecOps Stage
This stage sets up an area dedicated to hosting SecOps projects in the Google Cloud organization.
The design of this stage is fairly simple, as it is only responsible for creating GCP projects that will be linked to SecOps instances as per the following documentation.
After creating the projects please refer to your Google Cloud Security representative for instructions on how to bind your Google SecOps instance to the Google Cloud project/s created in this stage.
The following diagram illustrates the high-level design of resources managed here:
Design overview and choices
This stage will deploy 1 SecOps project for each environment available from the 0-globals input variables, of course such a behaviour might be updated to either deploy a single production instance or different number of environments with respect to the foundations ones.
IAM for day to day operations is already assigned at the folder level to the secops team by the previous stage, but more granularity can be added here at the project level, to grant control of separate services across environments to different actors as well as in the later 3-secops-dev/prod stages.
Workforce Identity Federation
This stage supports configuration of Workforce Identity Federation which lets an external identity provider (IdP) to authenticate and authorize a group of users (usually employees) using IAM, so that the users can access Google Cloud services.
The following example shows an example on how to define a Workforce Identity pool for the organization.
# stage 2 secops wif tfvars
workforce_identity_providers = {
test = {
issuer = "azuread"
display_name = "wif-provider"
description = "Workforce Identity pool"
saml = {
idp_metadata_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>..."
}
}
}
# tftest skip
How to run this stage
This stage is meant to be executed after the resource management stage has run, as it leverages the automation service account and bucket created there, and additional resources configured in the bootstrap stage.
It's of course possible to run this stage in isolation, but that's outside the scope of this document, and you would need to refer to the code for the previous stages for the environmental requirements.
Before running this stage, you need to make sure you have the correct credentials and permissions, and localize variables by assigning values that match your configuration.
Provider and Terraform variables
As all other FAST stages, the mechanism used to pass variable values and pre-built provider files from one stage to the next is also leveraged here.
The commands to link or copy the provider and terraform variable files can be easily derived from the fast-links.sh script in the FAST stages folder, passing it a single argument with the local output files folder (if configured) or the GCS output bucket in the automation project (derived from stage 0 outputs). The following examples demonstrate both cases, and the resulting commands that then need to be copy/pasted and run.
../fast-links.sh ~/fast-config
# File linking commands for security stage
# provider file
ln -s ~/fast-config/fast-test-00/providers/2-secops-providers.tf ./
# input files from other stages
ln -s ~/fast-config/fast-test-00/tfvars/0-globals.auto.tfvars.json ./
ln -s ~/fast-config/fast-test-00/tfvars/0-bootstrap.auto.tfvars.json ./
ln -s ~/fast-config/fast-test-00/tfvars/1-resman.auto.tfvars.json ./
# conventional place for stage tfvars (manually created)
ln -s ~/fast-config/fast-test-00/2-secops.auto.tfvars ./
../fast-links.sh gs://xxx-prod-iac-core-outputs-0
# File linking commands for security stage
# provider file
gcloud storage cp gs://xxx-prod-iac-core-outputs-0/providers/2-secops-providers.tf ./
# input files from other stages
gcloud storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/0-globals.auto.tfvars.json ./
gcloud storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/0-bootstrap.auto.tfvars.json ./
gcloud storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/1-resman.auto.tfvars.json ./
# conventional place for stage tfvars (manually created)
gcloud storage cp gs://xxx-prod-iac-core-outputs-0/2-secops.auto.tfvars ./
Impersonating the automation service account
The preconfigured provider file uses impersonation to run with this stage's automation service account's credentials. The gcp-devops and organization-admins groups have the necessary IAM bindings in place to do that, so make sure the current user is a member of one of those groups.
Variable configuration
Variables in this stage -- like most other FAST stages -- are broadly divided into three separate sets:
- variables which refer to global values for the whole organization (org id, billing account id, prefix, etc.), which are pre-populated via the
0-globals.auto.tfvars.jsonfile linked or copied above - variables which refer to resources managed by previous stages, which are prepopulated here via the
0-bootstrap.auto.tfvars.jsonand1-resman.auto.tfvars.jsonfiles linked or copied above - and finally variables that optionally control this stage's behaviour and customizations, and can to be set in a custom
terraform.tfvarsfile
The latter set is explained in the Customization sections below, and the full list can be found in the Variables table at the bottom of this document.
Note that the outputs_location variable is disabled by default, you need to explicitly set it in your terraform.tfvars file if you want output files to be generated by this stage. This is a sample terraform.tfvars that configures it, refer to the bootstrap stage documentation for more details:
outputs_location = "~/fast-config"
Using delayed billing association for projects
This configuration is possible but unsupported and only exists for development purposes, use at your own risk:
- temporarily switch
billing_account.idtonullin0-globals.auto.tfvars.json - for each project resources in the project modules used in this stage (
dev,prod)- apply using
-target, for exampleterraform apply -target 'module.project["dev"].google_project.project[0]' - untaint the project resource after applying, for example
terraform untaint 'module.project["dev"].google_project.project[0]'
- apply using
- go through the process to associate the billing account with the two projects
- switch
billing_account.idback to the real billing account id - resume applying normally
Running the stage
Once provider and variable values are in place and the correct user is configured, the stage can be run:
terraform init
terraform apply
Customizations
Workforce Identity Federation
This is a minimal configuration that creates a Workforce Identity pool at organization level.
workforce_identity_providers = {
test = {
issuer = "azuread"
display_name = "wif-provider"
description = "Workforce Identity pool"
saml = {
idp_metadata_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>..."
}
}
}
Files
| name | description | modules | resources |
|---|---|---|---|
| identity-providers-defs.tf | Workforce Identity provider definitions. | ||
| identity-providers.tf | Workforce Identity Federation provider definitions. | google_iam_workforce_pool · google_iam_workforce_pool_provider |
|
| main.tf | Module-level locals and resources. | folder · project |
|
| outputs.tf | Module outputs. | google_storage_bucket_object · local_file |
|
| variables-fast.tf | None | ||
| variables.tf | Module variables. |
Variables
| name | description | type | required | default | producer |
|---|---|---|---|---|---|
| automation | Automation resources created by the bootstrap stage. | object({…}) |
✓ | 0-bootstrap |
|
| billing_account | Billing account id. If billing account is not part of the same org set is_org_level to false. |
object({…}) |
✓ | 0-bootstrap |
|
| environments | Environment names. | map(object({…})) |
✓ | 0-globals |
|
| folder_ids | Folder name => id mappings, the 'security' folder name must exist. | object({…}) |
✓ | 1-resman |
|
| organization | Organization details. | object({…}) |
✓ | 0-bootstrap |
|
| prefix | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string |
✓ | 0-bootstrap |
|
| custom_roles | Custom roles defined at the org level, in key => id format. | object({…}) |
null |
0-bootstrap |
|
| essential_contacts | Email used for essential contacts, unset if null. | string |
null |
||
| outputs_location | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string |
null |
||
| stage_config | FAST stage configuration. | object({…}) |
{} |
1-resman |
|
| tag_values | Root-level tag values. | map(string) |
{} |
1-resman |
|
| workforce_identity_providers | Workforce Identity Federation pools. | map(object({…})) |
{} |
Outputs
| name | description | sensitive | consumers |
|---|---|---|---|
| federated_identity_pool | Workforce Identity Federation pool. | ||
| secops_project_ids | SecOps project IDs. | ||
| tfvars | Terraform variable files for the following stages. | ✓ |
