diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b8bdd3ab..decff9ae9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,12 +6,15 @@ All notable changes to this project will be documented in this file.
- add support for IAM and Cloud Build triggers to source repository module
- add `id` output to service account module
+- add support for secrets to cloud function module
**FAST**
- add support for Cloud Source Repositories in stage 0 and 1 CI/CD
- fix Gitlab workflow indentation
- remove unsupported attributes and add supported ones to the Gitlab mapping used for Workload Identity Federation pools
+- add roles for CI/CD source repositories to stage 1 service account on automation project
+- fixes to CI/CD source repositories in stage 1
## [16.0.0] - 2022-06-06
diff --git a/fast/stages/00-bootstrap/README.md b/fast/stages/00-bootstrap/README.md
index c217a50f7..3fcfb66c1 100644
--- a/fast/stages/00-bootstrap/README.md
+++ b/fast/stages/00-bootstrap/README.md
@@ -457,15 +457,15 @@ The remaining configuration is manual, as it regards the repositories themselves
| name | description | sensitive | consumers |
|---|---|:---:|---|
-| [automation](outputs.tf#L81) | Automation resources. | | |
-| [billing_dataset](outputs.tf#L86) | BigQuery dataset prepared for billing export. | | |
-| [cicd_repositories](outputs.tf#L91) | CI/CD repository configurations. | | |
-| [custom_roles](outputs.tf#L103) | Organization-level custom roles. | | |
-| [federated_identity](outputs.tf#L108) | Workload Identity Federation pool and providers. | | |
-| [outputs_bucket](outputs.tf#L118) | GCS bucket where generated output files are stored. | | |
-| [project_ids](outputs.tf#L123) | Projects created by this stage. | | |
-| [providers](outputs.tf#L142) | Terraform provider files for this stage and dependent stages. | ✓ | stage-01 |
-| [service_accounts](outputs.tf#L132) | Automation service accounts created by this stage. | | |
-| [tfvars](outputs.tf#L151) | Terraform variable files for the following stages. | ✓ | |
+| [automation](outputs.tf#L82) | Automation resources. | | |
+| [billing_dataset](outputs.tf#L87) | BigQuery dataset prepared for billing export. | | |
+| [cicd_repositories](outputs.tf#L92) | CI/CD repository configurations. | | |
+| [custom_roles](outputs.tf#L104) | Organization-level custom roles. | | |
+| [federated_identity](outputs.tf#L109) | Workload Identity Federation pool and providers. | | |
+| [outputs_bucket](outputs.tf#L119) | GCS bucket where generated output files are stored. | | |
+| [project_ids](outputs.tf#L124) | Projects created by this stage. | | |
+| [providers](outputs.tf#L143) | Terraform provider files for this stage and dependent stages. | ✓ | stage-01 |
+| [service_accounts](outputs.tf#L133) | Automation service accounts created by this stage. | | |
+| [tfvars](outputs.tf#L152) | Terraform variable files for the following stages. | ✓ | |
diff --git a/fast/stages/00-bootstrap/automation.tf b/fast/stages/00-bootstrap/automation.tf
index 0874fc4ff..bba34d06f 100644
--- a/fast/stages/00-bootstrap/automation.tf
+++ b/fast/stages/00-bootstrap/automation.tf
@@ -38,12 +38,18 @@ module "automation-project" {
"roles/owner" = [
module.automation-tf-bootstrap-sa.iam_email
]
+ "roles/cloudbuild.builds.editor" = [
+ module.automation-tf-resman-sa.iam_email
+ ]
"roles/iam.serviceAccountAdmin" = [
module.automation-tf-resman-sa.iam_email
]
"roles/iam.workloadIdentityPoolAdmin" = [
module.automation-tf-resman-sa.iam_email
]
+ "roles/source.admin" = [
+ module.automation-tf-resman-sa.iam_email
+ ]
"roles/storage.admin" = [
module.automation-tf-resman-sa.iam_email
]
diff --git a/fast/stages/00-bootstrap/outputs.tf b/fast/stages/00-bootstrap/outputs.tf
index cfb2460b8..910458651 100644
--- a/fast/stages/00-bootstrap/outputs.tf
+++ b/fast/stages/00-bootstrap/outputs.tf
@@ -57,6 +57,7 @@ locals {
federated_identity_providers = local.wif_providers
outputs_bucket = module.automation-tf-output-gcs.name
project_id = module.automation-project.project_id
+ project_number = module.automation-project.number
}
custom_roles = local.custom_roles
}
diff --git a/fast/stages/01-resman/README.md b/fast/stages/01-resman/README.md
index 8ec133ce0..a054106f6 100644
--- a/fast/stages/01-resman/README.md
+++ b/fast/stages/01-resman/README.md
@@ -178,30 +178,30 @@ Due to its simplicity, this stage lends itself easily to customizations: adding
| name | description | type | required | default | producer |
|---|---|:---:|:---:|:---:|:---:|
-| [automation](variables.tf#L20) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 00-bootstrap |
-| [billing_account](variables.tf#L37) | Billing account id and organization id ('nnnnnnnn' or null). | object({…}) | ✓ | | 00-bootstrap |
-| [organization](variables.tf#L140) | Organization details. | object({…}) | ✓ | | 00-bootstrap |
-| [prefix](variables.tf#L164) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 00-bootstrap |
-| [cicd_repositories](variables.tf#L46) | 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.tf#L116) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 00-bootstrap |
-| [groups](variables.tf#L125) | Group names to grant organization-level permissions. | map(string) | | {…} | 00-bootstrap |
-| [organization_policy_configs](variables.tf#L150) | Organization policies customization. | object({…}) | | null | |
-| [outputs_location](variables.tf#L158) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable | string | | null | |
-| [tag_names](variables.tf#L175) | Customized names for resource management tags. | object({…}) | | {…} | |
-| [team_folders](variables.tf#L192) | Team folders to be created. Format is described in a code comment. | map(object({…})) | | null | |
+| [automation](variables.tf#L20) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 00-bootstrap |
+| [billing_account](variables.tf#L38) | Billing account id and organization id ('nnnnnnnn' or null). | object({…}) | ✓ | | 00-bootstrap |
+| [organization](variables.tf#L141) | Organization details. | object({…}) | ✓ | | 00-bootstrap |
+| [prefix](variables.tf#L165) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 00-bootstrap |
+| [cicd_repositories](variables.tf#L47) | 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.tf#L117) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 00-bootstrap |
+| [groups](variables.tf#L126) | Group names to grant organization-level permissions. | map(string) | | {…} | 00-bootstrap |
+| [organization_policy_configs](variables.tf#L151) | Organization policies customization. | object({…}) | | null | |
+| [outputs_location](variables.tf#L159) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable | string | | null | |
+| [tag_names](variables.tf#L176) | Customized names for resource management tags. | object({…}) | | {…} | |
+| [team_folders](variables.tf#L193) | Team folders to be created. Format is described in a code comment. | map(object({…})) | | null | |
## Outputs
| name | description | sensitive | consumers |
|---|---|:---:|---|
-| [cicd_repositories](outputs.tf#L143) | WIF configuration for CI/CD repositories. | | |
-| [dataplatform](outputs.tf#L155) | Data for the Data Platform stage. | | |
-| [networking](outputs.tf#L171) | Data for the networking stage. | | |
-| [project_factories](outputs.tf#L180) | Data for the project factories stage. | | |
-| [providers](outputs.tf#L196) | Terraform provider files for this stage and dependent stages. | ✓ | 02-networking · 02-security · 03-dataplatform · xx-sandbox · xx-teams |
-| [sandbox](outputs.tf#L203) | Data for the sandbox stage. | | xx-sandbox |
-| [security](outputs.tf#L213) | Data for the networking stage. | | 02-security |
-| [teams](outputs.tf#L223) | Data for the teams stage. | | |
-| [tfvars](outputs.tf#L236) | Terraform variable files for the following stages. | ✓ | |
+| [cicd_repositories](outputs.tf#L145) | WIF configuration for CI/CD repositories. | | |
+| [dataplatform](outputs.tf#L159) | Data for the Data Platform stage. | | |
+| [networking](outputs.tf#L175) | Data for the networking stage. | | |
+| [project_factories](outputs.tf#L184) | Data for the project factories stage. | | |
+| [providers](outputs.tf#L200) | Terraform provider files for this stage and dependent stages. | ✓ | 02-networking · 02-security · 03-dataplatform · xx-sandbox · xx-teams |
+| [sandbox](outputs.tf#L207) | Data for the sandbox stage. | | xx-sandbox |
+| [security](outputs.tf#L217) | Data for the networking stage. | | 02-security |
+| [teams](outputs.tf#L227) | Data for the teams stage. | | |
+| [tfvars](outputs.tf#L240) | Terraform variable files for the following stages. | ✓ | |
diff --git a/fast/stages/01-resman/cicd-data-platform.tf b/fast/stages/01-resman/cicd-data-platform.tf
index e62a02208..4a5c6d3f5 100644
--- a/fast/stages/01-resman/cicd-data-platform.tf
+++ b/fast/stages/01-resman/cicd-data-platform.tf
@@ -37,7 +37,7 @@ module "branch-dp-dev-cicd-repo" {
included_files = [
"**/*json", "**/*tf", "**/*yaml", ".cloudbuild/workflow.yaml"
]
- service_account = module.branch-dp-dev-sa.iam_email
+ service_account = module.branch-dp-dev-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -47,6 +47,7 @@ module "branch-dp-dev-cicd-repo" {
}
}
}
+ depends_on = [module.branch-dp-dev-sa-cicd]
}
module "branch-dp-prod-cicd-repo" {
@@ -68,7 +69,7 @@ module "branch-dp-prod-cicd-repo" {
included_files = [
"**/*json", "**/*tf", "**/*yaml", ".cloudbuild/workflow.yaml"
]
- service_account = module.branch-dp-prod-sa.iam_email
+ service_account = module.branch-dp-prod-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -78,6 +79,7 @@ module "branch-dp-prod-cicd-repo" {
}
}
}
+ depends_on = [module.branch-dp-prod-sa-cicd]
}
# SAs used by CI/CD workflows to impersonate automation SAs
@@ -96,7 +98,9 @@ module "branch-dp-dev-sa-cicd" {
iam = (
each.value.type == "sourcerepo"
# used directly from the cloud build trigger for source repos
- ? {}
+ ? {
+ "roles/iam.serviceAccountUser" = local.automation_resman_sa
+ }
# impersonated via workload identity federation for external repos
: {
"roles/iam.workloadIdentityUser" = [
@@ -135,7 +139,9 @@ module "branch-dp-prod-sa-cicd" {
iam = (
each.value.type == "sourcerepo"
# used directly from the cloud build trigger for source repos
- ? {}
+ ? {
+ "roles/iam.serviceAccountUser" = local.automation_resman_sa
+ }
# impersonated via workload identity federation for external repos
: {
"roles/iam.workloadIdentityUser" = [
diff --git a/fast/stages/01-resman/cicd-networking.tf b/fast/stages/01-resman/cicd-networking.tf
index 541d8bda0..951770475 100644
--- a/fast/stages/01-resman/cicd-networking.tf
+++ b/fast/stages/01-resman/cicd-networking.tf
@@ -35,7 +35,7 @@ module "branch-network-cicd-repo" {
fast-02-networking = {
filename = ".cloudbuild/workflow.yaml"
included_files = ["**/*tf", ".cloudbuild/workflow.yaml"]
- service_account = module.branch-network-sa.id
+ service_account = module.branch-network-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -45,6 +45,7 @@ module "branch-network-cicd-repo" {
}
}
}
+ depends_on = [module.branch-network-sa-cicd]
}
# SA used by CI/CD workflows to impersonate automation SAs
@@ -63,7 +64,9 @@ module "branch-network-sa-cicd" {
iam = (
each.value.type == "sourcerepo"
# used directly from the cloud build trigger for source repos
- ? {}
+ ? {
+ "roles/iam.serviceAccountUser" = local.automation_resman_sa
+ }
# impersonated via workload identity federation for external repos
: {
"roles/iam.workloadIdentityUser" = [
diff --git a/fast/stages/01-resman/cicd-security.tf b/fast/stages/01-resman/cicd-security.tf
index d6b0b8691..86fd84fdb 100644
--- a/fast/stages/01-resman/cicd-security.tf
+++ b/fast/stages/01-resman/cicd-security.tf
@@ -35,7 +35,7 @@ module "branch-security-cicd-repo" {
fast-02-security = {
filename = ".cloudbuild/workflow.yaml"
included_files = ["**/*tf", ".cloudbuild/workflow.yaml"]
- service_account = module.branch-security-sa.id
+ service_account = module.branch-security-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -45,6 +45,7 @@ module "branch-security-cicd-repo" {
}
}
}
+ depends_on = [module.branch-security-sa-cicd]
}
# SA used by CI/CD workflows to impersonate automation SAs
@@ -63,7 +64,9 @@ module "branch-security-sa-cicd" {
iam = (
each.value.type == "sourcerepo"
# used directly from the cloud build trigger for source repos
- ? {}
+ ? {
+ "roles/iam.serviceAccountUser" = local.automation_resman_sa
+ }
# impersonated via workload identity federation for external repos
: {
"roles/iam.workloadIdentityUser" = [
diff --git a/fast/stages/01-resman/cicd-teams.tf b/fast/stages/01-resman/cicd-teams.tf
index 2766e301e..f5e81fd3f 100644
--- a/fast/stages/01-resman/cicd-teams.tf
+++ b/fast/stages/01-resman/cicd-teams.tf
@@ -37,7 +37,7 @@ module "branch-teams-dev-pf-cicd-repo" {
included_files = [
"**/*json", "**/*tf", "**/*yaml", ".cloudbuild/workflow.yaml"
]
- service_account = module.branch-teams-dev-pf-sa.iam_email
+ service_account = module.branch-teams-dev-pf-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -47,6 +47,7 @@ module "branch-teams-dev-pf-cicd-repo" {
}
}
}
+ depends_on = [module.branch-teams-dev-pf-sa-cicd]
}
module "branch-teams-prod-pf-cicd-repo" {
@@ -68,7 +69,7 @@ module "branch-teams-prod-pf-cicd-repo" {
included_files = [
"**/*json", "**/*tf", "**/*yaml", ".cloudbuild/workflow.yaml"
]
- service_account = module.branch-teams-prod-pf-sa.iam_email
+ service_account = module.branch-teams-prod-pf-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -78,6 +79,7 @@ module "branch-teams-prod-pf-cicd-repo" {
}
}
}
+ depends_on = [module.branch-teams-prod-pf-sa-cicd]
}
# SAs used by CI/CD workflows to impersonate automation SAs
@@ -96,7 +98,9 @@ module "branch-teams-dev-pf-sa-cicd" {
iam = (
each.value.type == "sourcerepo"
# used directly from the cloud build trigger for source repos
- ? {}
+ ? {
+ "roles/iam.serviceAccountUser" = local.automation_resman_sa
+ }
# impersonated via workload identity federation for external repos
: {
"roles/iam.workloadIdentityUser" = [
@@ -135,7 +139,9 @@ module "branch-teams-prod-pf-sa-cicd" {
iam = (
each.value.type == "sourcerepo"
# used directly from the cloud build trigger for source repos
- ? {}
+ ? {
+ "roles/iam.serviceAccountUser" = local.automation_resman_sa
+ }
# impersonated via workload identity federation for external repos
: {
"roles/iam.workloadIdentityUser" = [
diff --git a/fast/stages/01-resman/main.tf b/fast/stages/01-resman/main.tf
index 6cefbd25d..c40957964 100644
--- a/fast/stages/01-resman/main.tf
+++ b/fast/stages/01-resman/main.tf
@@ -16,6 +16,13 @@
locals {
# convenience flags that express where billing account resides
+ automation_resman_sa = try(
+ [format(
+ "serviceAccount:%s",
+ data.google_client_openid_userinfo.provider_identity.0.email
+ )],
+ []
+ )
billing_ext = var.billing_account.organization_id == null
billing_org = var.billing_account.organization_id == var.organization.id
billing_org_ext = !local.billing_ext && !local.billing_org
@@ -64,3 +71,7 @@ locals {
try(var.automation.federated_identity_providers, null), {}
)
}
+
+data "google_client_openid_userinfo" "provider_identity" {
+ count = length(local.cicd_repositories) > 0 ? 1 : 0
+}
diff --git a/fast/stages/01-resman/outputs.tf b/fast/stages/01-resman/outputs.tf
index f91a843d8..73ed2eedd 100644
--- a/fast/stages/01-resman/outputs.tf
+++ b/fast/stages/01-resman/outputs.tf
@@ -52,9 +52,11 @@ locals {
for k, v in local.cicd_repositories : k => templatefile(
"${path.module}/templates/workflow-${v.type}.yaml",
merge(local.cicd_workflow_attrs[k], {
- identity_provider = local.identity_providers[v.identity_provider].name
- outputs_bucket = var.automation.outputs_bucket
- stage_name = k
+ identity_provider = try(
+ local.identity_providers[v.identity_provider].name, null
+ )
+ outputs_bucket = var.automation.outputs_bucket
+ stage_name = k
})
)
}
@@ -144,9 +146,11 @@ output "cicd_repositories" {
description = "WIF configuration for CI/CD repositories."
value = {
for k, v in local.cicd_repositories : k => {
- branch = v.branch
- name = v.name
- provider = local.identity_providers[v.identity_provider].name
+ branch = v.branch
+ name = v.name
+ provider = try(
+ local.identity_providers[v.identity_provider].name, null
+ )
service_account = local.cicd_workflow_attrs[k].service_account
} if v != null
}
diff --git a/fast/stages/01-resman/variables.tf b/fast/stages/01-resman/variables.tf
index c31e67790..c1d534bca 100644
--- a/fast/stages/01-resman/variables.tf
+++ b/fast/stages/01-resman/variables.tf
@@ -23,6 +23,7 @@ variable "automation" {
type = object({
outputs_bucket = string
project_id = string
+ project_number = string
federated_identity_pool = string
federated_identity_providers = map(object({
issuer = string
diff --git a/fast/stages/CLEANUP.md b/fast/stages/CLEANUP.md
new file mode 100644
index 000000000..a0a1688fe
--- /dev/null
+++ b/fast/stages/CLEANUP.md
@@ -0,0 +1,110 @@
+# FAST deployment clean up
+In case you require destroying a previous FAST deployment in your organization, follow these steps.
+
+Destruction must be done in reverse order, from stage 3 to stage 0:
+
+## Stage 3 (Project Factory)
+
+```bash
+cd $FAST_PWD/03-project-factory/prod/
+terraform destroy
+```
+
+## Stage 3 (GKE)
+Terraform refuses to delete non-empty GCS buckets and/or BigQuery datasets, so they need to be removed manually from tf state
+
+```bash
+cd $FAST_PWD/03-project-factory/prod/
+
+# remove BQ dataset manually
+for x in $(terraform state list | grep google_bigquery_dataset); do
+ terraform state rm "$x";
+done
+
+terraform destroy
+```
+
+
+## Stage 2 (Security)
+```bash
+cd $FAST_PWD/02-security/
+terraform destroy
+```
+
+## Stage 2 (Networking)
+```bash
+cd $FAST_PWD/02-networking-XXX/
+terraform destroy
+```
+
+There's a minor glitch that can surface running terraform destroy, where the service project attachments to the Shared VPC will not get destroyed even with the relevant API call succeeding. We are investigating the issue, in the meantime just manually remove the attachment in the Cloud console or via the ```gcloud beta compute shared-vpc associated-projects remove``` [command](https://cloud.google.com/sdk/gcloud/reference/beta/compute/shared-vpc/associated-projects/remove) when terraform destroy fails, and then relaunch the command.
+
+## Stage 1 (Resource Management)
+Stage 1 is a little more complicated because of the GCS Buckets. By default terraform refuses to delete non-empty buckets, which is a good thing for your terraform state. However, it makes destruction a bit harder
+
+```bash
+cd $FAST_PWD/01-resman/
+
+# remove buckets from state since terraform refuses to delete them
+for x in $(terraform state list | grep google_storage_bucket.bucket); do
+ terraform state rm "$x"
+done
+
+terraform destroy
+```
+
+## Stage 0 (Bootstrap)
+**You should follow these steps carefully because we can end up destroying our own permissions. As we will be removing gcp-admins group roles, where your user belongs to, you will be required to grant organization admin role again**
+
+We also have to remove several resources (GCS buckets and BQ datasets) manually.
+
+```bash
+cd $FAST_PWD/00-bootstrap/
+
+# remove provider config to execute without SA impersonation
+rm 00-bootstrap-providers.tf
+
+# migrate to local state
+terraform init -migrate-state
+
+# remove GCS buckets and BQ dataset manually
+for x in $(terraform state list | grep google_storage_bucket.bucket); do
+ terraform state rm "$x";
+done
+
+for x in $(terraform state list | grep google_bigquery_dataset); do
+ terraform state rm "$x";
+done
+
+terraform destroy
+
+# when this fails continue with the steps below
+# make your user (the one you are using to execute this step) org admin again, as we will remove organization-admins group roles
+
+# Add the Organization Admin role to $BU_USER in the GCP Console
+
+# grant yourself this permission so you can finish the destruction
+export FAST_DESTROY_ROLES="roles/billing.admin roles/logging.admin \
+ roles/iam.organizationRoleAdmin roles/resourcemanager.projectDeleter \
+ roles/resourcemanager.folderAdmin roles/owner"
+
+export FAST_BU=$(gcloud config list --format 'value(core.account)')
+
+# find your org id
+gcloud organizations list --filter display_name:[part of your domain]
+
+# set your org id
+export FAST_ORG_ID=XXXX
+
+for role in $FAST_DESTROY_ROLES; do
+ gcloud organizations add-iam-policy-binding $FAST_ORG_ID \
+ --member user:$FAST_BU --role $role
+done
+
+terraform destroy
+rm -i terraform.tfstate*
+```
+
+In case you are willing to deploy FAST stages again, the following changes shall be done before:
+* Modify the [prefix](00-bootstrap/variables.tf) variable to allow the deployment of resources that need unique names (eg, projects).
+* Modify the [custom_roles](00-bootstrap/variables.tf) variable to allow recently deleted custom roles to be created again.
\ No newline at end of file
diff --git a/fast/stages/README.md b/fast/stages/README.md
index 8b0814280..d7951ba79 100644
--- a/fast/stages/README.md
+++ b/fast/stages/README.md
@@ -17,6 +17,8 @@ To achieve this, we rely on specific GCP functionality like [delegated role gran
Refer to each stage's documentation for a detailed description of its purpose, the architectural choices made in its design, and how it can be configured and wired together to terraform a whole GCP organization. The following is a brief overview of each stage.
+To destroy a previous FAST deployment follow the instructions detailed in [cleanup](CLEANUP.md).
+
## Organizational level (00-01)
- [Bootstrap](00-bootstrap/README.md)
diff --git a/modules/cloud-function/README.md b/modules/cloud-function/README.md
index 6eac68bf1..73a1d3f2a 100644
--- a/modules/cloud-function/README.md
+++ b/modules/cloud-function/README.md
@@ -173,11 +173,12 @@ module "cf-http" {
| [labels](variables.tf#L82) | Resource labels. | map(string) | | {} |
| [prefix](variables.tf#L93) | Optional prefix used for resource names. | string | | null |
| [region](variables.tf#L104) | Region used for all resources. | string | | "europe-west1" |
-| [service_account](variables.tf#L110) | Service account email. Unused if service account is auto-created. | string | | null |
-| [service_account_create](variables.tf#L116) | Auto-create service account. | bool | | false |
-| [trigger_config](variables.tf#L122) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null |
-| [vpc_connector](variables.tf#L132) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null |
-| [vpc_connector_config](variables.tf#L142) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null |
+| [secrets](variables.tf#L110) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | map(object({…})) | | {} |
+| [service_account](variables.tf#L122) | Service account email. Unused if service account is auto-created. | string | | null |
+| [service_account_create](variables.tf#L128) | Auto-create service account. | bool | | false |
+| [trigger_config](variables.tf#L134) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null |
+| [vpc_connector](variables.tf#L144) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null |
+| [vpc_connector_config](variables.tf#L154) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null |
## Outputs
diff --git a/modules/cloud-function/main.tf b/modules/cloud-function/main.tf
index 949cb69b1..0a26c1205 100644
--- a/modules/cloud-function/main.tf
+++ b/modules/cloud-function/main.tf
@@ -91,6 +91,35 @@ resource "google_cloudfunctions_function" "function" {
}
}
+ dynamic "secret_environment_variables" {
+ for_each = { for k, v in var.secrets : k => v if !v.is_volume }
+ iterator = secret
+ content {
+ key = secret.key
+ project_id = secret.value.project_id
+ secret = secret.value.secret
+ version = try(secret.value.versions.0, "latest")
+ }
+ }
+
+ dynamic "secret_volumes" {
+ for_each = { for k, v in var.secrets : k => v if v.is_volume }
+ iterator = secret
+ content {
+ mount_path = secret.key
+ project_id = secret.value.project_id
+ secret = secret.value.secret
+ dynamic "versions" {
+ for_each = secret.value.versions
+ iterator = version
+ content {
+ path = split(":", version)[1]
+ version = split(":", version)[0]
+ }
+ }
+ }
+ }
+
}
resource "google_cloudfunctions_function_iam_binding" "default" {
diff --git a/modules/cloud-function/variables.tf b/modules/cloud-function/variables.tf
index a613b2f68..ce8633c8f 100644
--- a/modules/cloud-function/variables.tf
+++ b/modules/cloud-function/variables.tf
@@ -107,6 +107,18 @@ variable "region" {
default = "europe-west1"
}
+variable "secrets" {
+ description = "Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format."
+ type = map(object({
+ is_volume = bool
+ project_id = number
+ secret = string
+ versions = list(string)
+ }))
+ nullable = false
+ default = {}
+}
+
variable "service_account" {
description = "Service account email. Unused if service account is auto-created."
type = string
diff --git a/modules/iam-service-account/README.md b/modules/iam-service-account/README.md
index ab6b1882c..ad39c389e 100644
--- a/modules/iam-service-account/README.md
+++ b/modules/iam-service-account/README.md
@@ -2,6 +2,8 @@
This module allows simplified creation and management of one a service account and its IAM bindings. A key can optionally be generated and will be stored in Terraform state. To use it create a sensitive output in your root modules referencing the `key` output, then extract the private key from the JSON formatted outputs. Alternatively, the `key` can be generated with `openssl` library and only public part uploaded to the Service Account, for more refer to the [Onprem SA Key Management](../../examples/cloud-operations/onprem-sa-key-management/) example.
+Note that this module does not fully comply with our design principles, as outputs have no dependencies on IAM bindings to prevent resource cycles.
+
## Example
```hcl
@@ -64,9 +66,9 @@ module "myproject-default-service-accounts" {
| [email](outputs.tf#L17) | Service account email. | |
| [iam_email](outputs.tf#L25) | IAM-format service account email. | |
| [id](outputs.tf#L33) | Service account id. | |
-| [key](outputs.tf#L38) | Service account key. | ✓ |
-| [name](outputs.tf#L44) | Service account name. | |
-| [service_account](outputs.tf#L49) | Service account resource. | |
-| [service_account_credentials](outputs.tf#L54) | Service account json credential templates for uploaded public keys data. | |
+| [key](outputs.tf#L41) | Service account key. | ✓ |
+| [name](outputs.tf#L47) | Service account name. | |
+| [service_account](outputs.tf#L52) | Service account resource. | |
+| [service_account_credentials](outputs.tf#L57) | Service account json credential templates for uploaded public keys data. | |
diff --git a/modules/iam-service-account/outputs.tf b/modules/iam-service-account/outputs.tf
index 4f0e0aa52..42196534c 100644
--- a/modules/iam-service-account/outputs.tf
+++ b/modules/iam-service-account/outputs.tf
@@ -33,6 +33,9 @@ output "iam_email" {
output "id" {
description = "Service account id."
value = local.service_account.id
+ depends_on = [
+ local.service_account
+ ]
}
output "key" {
diff --git a/tests/fast/stages/s01_resman/fixture/main.tf b/tests/fast/stages/s01_resman/fixture/main.tf
index ddb9aafef..57d35b163 100644
--- a/tests/fast/stages/s01_resman/fixture/main.tf
+++ b/tests/fast/stages/s01_resman/fixture/main.tf
@@ -20,6 +20,7 @@ module "stage" {
federated_identity_pool = null
federated_identity_providers = null
project_id = "fast-prod-automation"
+ project_number = 123456
outputs_bucket = "test"
}
billing_account = {
diff --git a/tools/check_names.py b/tools/check_names.py
index 7e45fd877..e3fcf88f1 100755
--- a/tools/check_names.py
+++ b/tools/check_names.py
@@ -84,13 +84,21 @@ def main(dirs, prefix_length=None):
source_just = max(len(k) for k in MOD_LIMITS)
name_just = max(len(n.name) for n in names)
value_just = max(len(n.value) for n in names)
+ errors = []
for name in names:
name_length = name.length + prefix_length
- flag = '✗' if name_length >= MOD_LIMITS[name.source] else '✓'
- print(f'[{flag}] {name.source.ljust(source_just)} '
- f'{name.name.ljust(name_just)} '
- f'{name.value.ljust(value_just)} '
- f'({name_length})')
+ if name_length >= MOD_LIMITS[name.source]:
+ flag = "✗"
+ errors += [f"{name.source}:{name.name}:{name_length}"]
+ else:
+ flag = "✓"
+
+ print(f"[{flag}] {name.source.ljust(source_just)} "
+ f"{name.name.ljust(name_just)} "
+ f"{name.value.ljust(value_just)} "
+ f"({name_length})")
+ if errors:
+ raise ValueError(errors)
if __name__ == '__main__':