From 1b08c16490ffcfd306e849ff90e34e693ae7b2ea Mon Sep 17 00:00:00 2001 From: Amanda Karina Lopes de Oliveira Date: Mon, 23 Dec 2024 12:02:52 -0300 Subject: [PATCH] chore: add local deployment instructions (#1327) Co-authored-by: Caetano Colin <164910343+caetano-colin@users.noreply.github.com> Co-authored-by: caetano-colin --- 0-bootstrap/README.md | 182 +++++++++++++++++- 0-bootstrap/cb.tf | 2 - 0-bootstrap/main.tf | 4 +- 0-bootstrap/outputs.tf | 25 +-- 1-org/README.md | 51 +++-- 2-environments/README.md | 62 ++++-- 3-networks-dual-svpc/README.md | 88 ++++++--- 3-networks-hub-and-spoke/README.md | 88 ++++++--- 4-projects/README.md | 92 ++++++--- .../business_unit_1/development/main.tf | 1 + .../business_unit_1/nonproduction/main.tf | 1 + 4-projects/business_unit_1/production/main.tf | 1 + test/integration/testutils/retry.go | 3 + 13 files changed, 442 insertions(+), 158 deletions(-) diff --git a/0-bootstrap/README.md b/0-bootstrap/README.md index a9941e367..21c7dabf0 100644 --- a/0-bootstrap/README.md +++ b/0-bootstrap/README.md @@ -64,13 +64,15 @@ This repository is intended as an example to be forked, tweaked, and maintained Though this blueprint can help accelerate your foundation design and build, we assume that you have the engineering skills and teams to deploy and customize your own foundation based on your own requirements. We will support: - - Code is semantically valid, pinned to known good versions, and passes terraform validate and lint checks - - All PR to this repo must pass integration tests to deploy all resources into a test environment before being merged - - Feature requests about ease of use of the code, or feature requests that generally apply to all users, are welcome + +- Code is semantically valid, pinned to known good versions, and passes terraform validate and lint checks +- All PR to this repo must pass integration tests to deploy all resources into a test environment before being merged +- Feature requests about ease of use of the code, or feature requests that generally apply to all users, are welcome We will not support: - - In-place upgrades from a foundation deployed with an earlier version to a more recent version, even for minor version changes, might not be feasible. Repository maintainers do not have visibility to what resources a user deploys on top of their foundation or how the foundation was customized in deployment, so we make no guarantee about avoiding breaking changes. - - Feature requests that are specific to a single user's requirement and not representative of general best practices + +- In-place upgrades from a foundation deployed with an earlier version to a more recent version, even for minor version changes, might not be feasible. Repository maintainers do not have visibility to what resources a user deploys on top of their foundation or how the foundation was customized in deployment, so we make no guarantee about avoiding breaking changes. +- Feature requests that are specific to a single user's requirement and not representative of general best practices ## Prerequisites @@ -86,21 +88,25 @@ To run the commands described in this document, install the following: Version 1.5.7 is the last version before the license model change. To use a later version of Terraform, ensure that the Terraform version used in the Operational System to manually execute part of the steps in `3-networks` and `4-projects` is the same version configured in the following code - 0-bootstrap/modules/jenkins-agent/variables.tf + ``` default = "1.5.7" ``` - 0-bootstrap/cb.tf + ``` terraform_version = "1.5.7" ``` - scripts/validate-requirements.sh + ``` TF_VERSION="1.5.7" ``` - build/github-tf-apply.yaml + ``` terraform_version: '1.5.7' ``` @@ -112,6 +118,7 @@ Version 1.5.7 is the last version before the license model change. To use a late ``` - 0-bootstrap/Dockerfile + ``` ARG TERRAFORM_VERSION=1.5.7 ``` @@ -136,7 +143,9 @@ Set the variables in **terraform.tfvars** (`groups` block) to use the specific g # example: gcloud organizations add-iam-policy-binding ${ORG_ID} --member=user:$SUPER_ADMIN_EMAIL --role=roles/securitycenter.admin --quiet > /dev/null 1>&1 ``` + 1. Enable the following additional services on your current bootstrap project: + ```bash gcloud services enable cloudresourcemanager.googleapis.com gcloud services enable cloudbilling.googleapis.com @@ -342,11 +351,164 @@ The following steps introduce the steps to deploy with Cloud Build Alternatively ## Running Terraform locally -If you deploy using Cloud Build, the bucket information is replaced in the state -backends as part of the build process when the build is executed by Cloud Build. -If you want to execute Terraform locally, you need to add your Cloud -Storage bucket to the `backend.tf` files. -Each step has instructions for this change. +The following steps will guide you through deploying without using Cloud Build. + +1. Clone [terraform-example-foundation](https://github.com/terraform-google-modules/terraform-example-foundation) into your local environment and create to the `gcp-bootstrap` folder at the same level. Copy the `0-bootstrap` content and `.gitignore` to `gcp-bootstrap`. + + ```bash + git clone https://github.com/terraform-google-modules/terraform-example-foundation.git + + mkdir gcp-bootstrap + + cp -R terraform-example-foundation/0-bootstrap/* gcp-bootstrap/ + + cp terraform-example-foundation/.gitignore gcp-bootstrap + ``` + +1. Navigate to `gcp-bootstrap` and initialize a local Git repository to manage versions locally. Then, Create the environment branches. + + ```bash + cd gcp-bootstrap + + git init + git commit -m "initialize empty directory" --allow-empty + git checkout -b plan + + git checkout -b shared + ``` + +1. Rename `terraform.example.tfvars` to `terraform.tfvars` and update the file with values from your environment: + + ```bash + mv terraform.example.tfvars terraform.tfvars + ``` + +1. Rename `cb.tf` to `cb.tf.example`: + + ```bash + mv cb.tf cb.tf.example + ``` + +1. Comment Cloud Build related outputs at `outputs.tf`. + +1. In `sa.tf` file, comment out lines related to Cloud Build. Specifically, search for `cicd_project_iam_member` and comment out the corresponding module, as well as the "depends_on" meta-argument in any modules that depend on the commented module. + +1. In `sa.tf` file, search for `local.cicd_project_id` and comment out the corresponding code. + +1. Use the helper script [validate-requirements.sh](../scripts/validate-requirements.sh) to validate your environment: + + ```bash + ../terraform-example-foundation/scripts/validate-requirements.sh -o -b -u + ``` + + **Note:** The script is not able to validate if the user is in a Cloud Identity or Google Workspace group with the required roles. + +1. Run `terraform init` and `terraform plan` and review the output. + + ```bash + git checkout plan + terraform init + terraform plan -input=false -out bootstrap.tfplan + ``` + +1. Create a new folder called gcp-policies at the same directory level as the `terraform-example-foundation` folder. Initialize a Git repository, create a branch called `main`, and copy the contents of the `policy-library` directory from the `terraform-example-foundation` folder into the gcp-policies folder. + + ```bash + cd ../ + + mkdir gcp-policies + + cd gcp-policies + git init + git checkout -b main + cp -RT ../terraform-example-foundation/policy-library/ . + ``` + +1. Commit changes to the main branch of the policy repo. This way you can manage versions locally. + + ```bash + git add . + git commit -m 'Initialize policy library repo' + ``` + +1. Navigate back to `gcp-bootstrap` repo. + + ```bash + cd ../gcp-bootstrap + ``` + +1. To validate your policies, run `gcloud beta terraform vet`. For installation instructions, see [Install Google Cloud CLI](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install). + +1. Run the following commands and check for violations: + + ```bash + export VET_PROJECT_ID=A-VALID-PROJECT-ID + terraform show -json bootstrap.tfplan > bootstrap.json + gcloud beta terraform vet bootstrap.json --policy-library="$(pwd)/../gcp-policies" --project ${VET_PROJECT_ID} + ``` + + *`A-VALID-PROJECT-ID`* must be an existing project you have access to. This is necessary because `gcloud beta terraform vet` needs to link resources to a valid Google Cloud Platform project. + +1. Commit validated code in plan branch. + + ```bash + git add . + git commit -m "Initial version os gcp-bootstrap." + ``` + +1. Checkout `shared` branch and merge the `plan` branch into it. Then, Run `terraform apply`. + + ```bash + git checkout shared + git merge plan + + terraform apply bootstrap.tfplan + ``` + +1. Run `terraform output` to get the email address of the terraform service accounts that will be used to run steps manually and the state bucket that will be used by step `4-projects`. + + ```bash + export network_step_sa=$(terraform output -raw networks_step_terraform_service_account_email) + export projects_step_sa=$(terraform output -raw projects_step_terraform_service_account_email) + export projects_gcs_bucket_tfstate=$(terraform output -raw projects_gcs_bucket_tfstate) + + echo "network step service account = ${network_step_sa}" + echo "projects step service account = ${projects_step_sa}" + echo "projects gcs bucket tfstate = ${projects_gcs_bucket_tfstate}" + ``` + +1. Copy the backend and update `backend.tf` with the name of your Google Cloud Storage bucket for Terraform's state. Also update the `backend.tf` of all steps. + + ```bash + export backend_bucket=$(terraform output -raw gcs_bucket_tfstate) + echo "backend_bucket = ${backend_bucket}" + + export backend_bucket_projects=$(terraform output -raw projects_gcs_bucket_tfstate) + echo "backend_bucket_projects = ${backend_bucket_projects}" + + cp backend.tf.example backend.tf + + cd ../ + + for i in `find . -name 'backend.tf'`; do sed -i'' -e "s/UPDATE_ME/${backend_bucket}/" $i; done + for i in `find . -name 'backend.tf'`; do sed -i'' -e "s/UPDATE_PROJECTS_BACKEND/${backend_bucket_projects}/" $i; done + + cd gcp-bootstrap + ``` + +1. Re-run `terraform init`. When you're prompted, agree to copy Terraform state to Cloud Storage. + + ```bash + terraform init + ``` + +1. Commit the new code version, so you can manage versions locally. + + ```sh + git add backend.tf + git commit -m "Init gcs backend." + cd ../ + ``` ## Inputs diff --git a/0-bootstrap/cb.tf b/0-bootstrap/cb.tf index ef7e922b4..27ca53163 100644 --- a/0-bootstrap/cb.tf +++ b/0-bootstrap/cb.tf @@ -22,8 +22,6 @@ locals { cicd_project_id = module.tf_source.cloudbuild_project_id - state_bucket_kms_key = "projects/${module.seed_bootstrap.seed_project_id}/locations/${var.default_region}/keyRings/${var.project_prefix}-keyring/cryptoKeys/${var.project_prefix}-key" - bucket_self_link_prefix = "https://www.googleapis.com/storage/v1/b/" default_state_bucket_self_link = "${local.bucket_self_link_prefix}${module.seed_bootstrap.gcs_bucket_tfstate}" gcp_projects_state_bucket_self_link = module.gcp_projects_state_bucket.bucket.self_link diff --git a/0-bootstrap/main.tf b/0-bootstrap/main.tf index 1063e58fe..17bc985e5 100644 --- a/0-bootstrap/main.tf +++ b/0-bootstrap/main.tf @@ -32,6 +32,9 @@ locals { org_admins_org_iam_permissions = var.org_policy_admin_role == true ? [ "roles/orgpolicy.policyAdmin", "roles/resourcemanager.organizationAdmin", "roles/billing.user" ] : ["roles/resourcemanager.organizationAdmin", "roles/billing.user"] + + state_bucket_kms_key = "projects/${module.seed_bootstrap.seed_project_id}/locations/${var.default_region}/keyRings/${var.project_prefix}-keyring/cryptoKeys/${var.project_prefix}-key" + } resource "google_folder" "bootstrap" { @@ -103,4 +106,3 @@ module "seed_bootstrap" { depends_on = [module.required_group] } - diff --git a/0-bootstrap/outputs.tf b/0-bootstrap/outputs.tf index 81b1f77ab..01e6fe09b 100644 --- a/0-bootstrap/outputs.tf +++ b/0-bootstrap/outputs.tf @@ -49,6 +49,11 @@ output "gcs_bucket_tfstate" { value = module.seed_bootstrap.gcs_bucket_tfstate } +output "projects_gcs_bucket_tfstate" { + description = "Bucket used for storing terraform state for stage 4-projects foundations pipelines in seed project." + value = module.gcp_projects_state_bucket.bucket.name +} + output "common_config" { description = "Common configuration data to be used in other steps." value = { @@ -96,11 +101,6 @@ output "gcs_bucket_cloudbuild_logs" { value = { for key, value in module.tf_workspace : key => replace(value.logs_bucket, local.bucket_self_link_prefix, "") } } -output "projects_gcs_bucket_tfstate" { - description = "Bucket used for storing terraform state for stage 4-projects foundations pipelines in seed project." - value = module.gcp_projects_state_bucket.bucket.name -} - output "cloud_builder_artifact_repo" { description = "Artifact Registry (AR) Repository created to store TF Cloud Builder images." value = "projects/${module.tf_source.cloudbuild_project_id}/locations/${var.default_region}/repositories/${module.tf_cloud_builder.artifact_repo}" @@ -146,11 +146,6 @@ output "cloud_build_peered_network_id" { # value = module.gh_cicd.project_id # } -# output "projects_gcs_bucket_tfstate" { -# description = "Bucket used for storing terraform state for stage 4-projects foundations pipelines in seed project." -# value = module.seed_bootstrap.gcs_bucket_tfstate -# } - /* ---------------------------------------- Specific to jenkins_bootstrap module ---------------------------------------- */ @@ -170,11 +165,6 @@ output "cloud_build_peered_network_id" { # value = module.jenkins_bootstrap.jenkins_agent_vpc_id # } -# output "projects_gcs_bucket_tfstate" { -# description = "Bucket used for storing terraform state for stage 4-projects foundations pipelines in seed project." -# value = module.seed_bootstrap.gcs_bucket_tfstate -# } - # output "jenkins_agent_sa_email" { # description = "Email for privileged custom service account for Jenkins Agent GCE instance." # value = module.jenkins_bootstrap.jenkins_agent_sa_email @@ -199,11 +189,6 @@ output "cloud_build_peered_network_id" { # value = module.gitlab_cicd.project_id # } -# output "projects_gcs_bucket_tfstate" { -# description = "Bucket used for storing terraform state for stage 4-projects foundations pipelines in seed project." -# value = module.seed_bootstrap.gcs_bucket_tfstate -# } - /* ---------------------------------------- Specific to tfc_bootstrap ---------------------------------------- */ diff --git a/1-org/README.md b/1-org/README.md index 2c0b16e00..cf5eac821 100644 --- a/1-org/README.md +++ b/1-org/README.md @@ -175,14 +175,14 @@ If required, run `terraform output cloudbuild_project_id` in the `0-bootstrap` f 1. Push your plan branch to trigger a plan for all environments. Because the _plan_ branch is not a [named environment branch](../docs/FAQ.md#what-is-a-named-branch), pushing your _plan_ - branch triggers _terraform plan_ but not _terraform apply_. Review the plan output in your Cloud Build project. https://console.cloud.google.com/cloud-build/builds;region=DEFAULT_REGION?project=YOUR_CLOUD_BUILD_PROJECT_ID + branch triggers _terraform plan_ but not _terraform apply_. Review the plan output in your Cloud Build project. ```bash git push --set-upstream origin plan ``` 1. Merge changes to the production branch. Because the _production_ branch is a [named environment branch](../docs/FAQ.md#what-is-a-named-branch), - pushing to this branch triggers both _terraform plan_ and _terraform apply_. Review the apply output in your Cloud Build project. https://console.cloud.google.com/cloud-build/builds;region=DEFAULT_REGION?project=YOUR_CLOUD_BUILD_PROJECT_ID + pushing to this branch triggers both _terraform plan_ and _terraform apply_. Review the apply output in your Cloud Build project. ```bash git checkout -b production @@ -209,14 +209,26 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s ### Running Terraform locally 1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. -Change into the `1-org` folder, copy the Terraform wrapper script, and ensure it can be executed. +Create `gcp-org` folder, copy `1-org` content and Terraform wrapper script; ensure it can be executed. ```bash - cd terraform-example-foundation/1-org - cp ../build/tf-wrapper.sh . + mkdir gcp-org + cp -R terraform-example-foundation/1-org/* gcp-org/ + cp terraform-example-foundation/build/tf-wrapper.sh gcp-org/ + cp terraform-example-foundation/.gitignore gcp-org/ + cd gcp-org chmod 755 ./tf-wrapper.sh ``` +1. Initialize a local Git repository to manage versions locally. Then, create the environment branches. + + ```bash + git init + git commit -m "initialize empty directory" --allow-empty + git checkout -b plan + git checkout -b production + ``` + 1. Rename `./envs/shared/terraform.example.tfvars` to `./envs/shared/terraform.tfvars`. ```bash @@ -226,7 +238,7 @@ Change into the `1-org` folder, copy the Terraform wrapper script, and ensure it 1. Check if a Security Command Center notification with the default name, **scc-notify**, already exists. If it exists, choose a different value for the `scc_notification_name` variable in the `./envs/shared/terraform.tfvars` file. ```bash - export ORGANIZATION_ID=$(terraform -chdir="../0-bootstrap/" output -json common_config | jq '.org_id' --raw-output) + export ORGANIZATION_ID=$(terraform -chdir="../gcp-bootstrap/" output -json common_config | jq '.org_id' --raw-output) gcloud scc notifications describe "scc-notify" --organization=${ORGANIZATION_ID} ``` @@ -237,10 +249,10 @@ Change into the `1-org` folder, copy the Terraform wrapper script, and ensure it echo "access_context_manager_policy_id = ${ACCESS_CONTEXT_MANAGER_ID}" ``` -1. Update the `envs/shared/terraform.tfvars` file with values from your environment and 0-bootstrap step. If the previous step showed a numeric value, un-comment the variable `create_access_context_manager_access_policy = false`. See the shared folder [README.md](./envs/shared/README.md) for additional information on the values in the `terraform.tfvars` file. +1. Update the `envs/shared/terraform.tfvars` file with values from your environment and `gcp-bootstrap` step. If the previous step showed a numeric value, un-comment the variable `create_access_context_manager_access_policy = false`. See the shared folder [README.md](./envs/shared/README.md) for additional information on the values in the `terraform.tfvars` file. ```bash - export backend_bucket=$(terraform -chdir="../0-bootstrap/" output -raw gcs_bucket_tfstate) + export backend_bucket=$(terraform -chdir="../gcp-bootstrap/" output -raw gcs_bucket_tfstate) echo "remote_state_bucket = ${backend_bucket}" sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./envs/shared/terraform.tfvars @@ -249,23 +261,23 @@ Change into the `1-org` folder, copy the Terraform wrapper script, and ensure it ``` You can now deploy your environment (production) using this script. -When using Cloud Build or Jenkins as your CI/CD tool, each environment corresponding to a branch is the repository for 1-org step and only the corresponding environment is applied. To use the `validate` option of the `tf-wrapper.sh` script, follow the [instructions](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install) to install the terraform-tools component. -1. Use `terraform output` to get the Cloud Build project ID and the organization step Terraform service account from 0-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. +1. Use `terraform output` to get the Seed project ID and the organization step Terraform service account from gcp-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. ```bash - export CLOUD_BUILD_PROJECT_ID=$(terraform -chdir="../0-bootstrap/" output -raw cloudbuild_project_id) - echo ${CLOUD_BUILD_PROJECT_ID} + export SEED_PROJECT_ID=$(terraform -chdir="../gcp-bootstrap/" output -raw seed_project_id) + echo ${SEED_PROJECT_ID} - export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../0-bootstrap/" output -raw organization_step_terraform_service_account_email) + export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../gcp-bootstrap/" output -raw organization_step_terraform_service_account_email) echo ${GOOGLE_IMPERSONATE_SERVICE_ACCOUNT} ``` 1. Run `init` and `plan` and review the output. ```bash + git checkout plan ./tf-wrapper.sh init production ./tf-wrapper.sh plan production ``` @@ -273,12 +285,21 @@ To use the `validate` option of the `tf-wrapper.sh` script, follow the [instruct 1. Run `validate` and resolve any violations. ```bash - ./tf-wrapper.sh validate production $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate production $(pwd)/../gcp-policies ${SEED_PROJECT_ID} + ``` + +1. Commit validated code in plan branch. + + ```bash + git add . + git commit -m "Initial version of gcp-org." ``` -1. Run `apply production`. +1. Checkout `production` branch and merge plan into it. Run `apply production`. ```bash + git checkout production + git merge plan ./tf-wrapper.sh apply production ``` diff --git a/2-environments/README.md b/2-environments/README.md index d0624593a..814b89896 100644 --- a/2-environments/README.md +++ b/2-environments/README.md @@ -81,7 +81,6 @@ Use the [GCP console](https://console.cloud.google.com/compliance/assuredworkloa ## Usage - **Note:** If you are using MacOS, replace `cp -RT` with `cp -R` in the relevant commands. The `-T` flag is needed for Linux, but causes problems for MacOS. @@ -180,12 +179,25 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s ### Run Terraform locally -1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Change into `2-environments` folder, copy the Terraform wrapper script and ensure it can be executed. +1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Create the `gcp-environments` folder, copy the Terraform wrapper script and ensure it can be executed. ```bash - cd terraform-example-foundation/2-environments - cp ../build/tf-wrapper.sh . - chmod 755 ./tf-wrapper.sh + mkdir gcp-environments + cp -R terraform-example-foundation/2-environments/* gcp-environments/ + cp terraform-example-foundation/build/tf-wrapper.sh gcp-environments/ + cp terraform-example-foundation/.gitignore gcp-environments/ + chmod 755 ./gcp-environments/tf-wrapper.sh + ``` + +1. Navigate to `gcp-environments` and initialize a local Git repository to manage versions locally. Then, create the environment branches. + + ```bash + cd gcp-environments + git init + git commit -m "initialize empty directory" --allow-empty + git checkout -b production + git checkout -b nonproduction + git checkout -b development ``` 1. Rename `terraform.example.tfvars` to `terraform.tfvars`. @@ -198,30 +210,30 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s 1. Use `terraform output` to get the backend bucket value from 0-bootstrap output. ```bash - export backend_bucket=$(terraform -chdir="../0-bootstrap/" output -raw gcs_bucket_tfstate) + export backend_bucket=$(terraform -chdir="../gcp-bootstrap/" output -raw gcs_bucket_tfstate) echo "remote_state_bucket = ${backend_bucket}" sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./terraform.tfvars ``` We will now deploy each of our environments(development/production/nonproduction) using this script. -When using Cloud Build or Jenkins as your CI/CD tool each environment corresponds to a branch is the repository for 2-environments step and only the corresponding environment is applied. To use the `validate` option of the `tf-wrapper.sh` script, please follow the [instructions](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install) to install the terraform-tools component. -1. Use `terraform output` to get the Cloud Build project ID and the environment step Terraform Service Account from 0-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. +1. Use `terraform output` to get the Seed project ID and the organization step Terraform service account from gcp-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. ```bash - export CLOUD_BUILD_PROJECT_ID=$(terraform -chdir="../0-bootstrap/" output -raw cloudbuild_project_id) - echo ${CLOUD_BUILD_PROJECT_ID} + export SEED_PROJECT_ID=$(terraform -chdir="../gcp-bootstrap/" output -raw seed_project_id) + echo ${SEED_PROJECT_ID} - export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../0-bootstrap/" output -raw environment_step_terraform_service_account_email) + export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../gcp-bootstrap/" output -raw environment_step_terraform_service_account_email) echo ${GOOGLE_IMPERSONATE_SERVICE_ACCOUNT} ``` -1. Run `init` and `plan` and review output for environment development. +1. Checkout `development` branch. Run `init` and `plan` and review output for environment development. ```bash + git checkout development ./tf-wrapper.sh init development ./tf-wrapper.sh plan development ``` @@ -229,18 +241,22 @@ To use the `validate` option of the `tf-wrapper.sh` script, please follow the [i 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate development $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate development $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` development. +1. Run `apply` development and commit the initial version of `development` branch. ```bash ./tf-wrapper.sh apply development + git add . + git commit -m "Development initial commit." ``` -1. Run `init` and `plan` and review output for environment nonproduction. +1. Checkout `nonproduction` branch and merge `development` branch into it. Run `init` and `plan` and review output for environment nonproduction. ```bash + git checkout nonproduction + git merge development ./tf-wrapper.sh init nonproduction ./tf-wrapper.sh plan nonproduction ``` @@ -248,18 +264,22 @@ To use the `validate` option of the `tf-wrapper.sh` script, please follow the [i 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate nonproduction $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate nonproduction $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` nonproduction. +1. Run `apply` production and commit initial version of nonproduction. ```bash ./tf-wrapper.sh apply nonproduction + git add . + git commit -m "Nonproduction initial commit." ``` -1. Run `init` and `plan` and review output for environment production. +1. Checkout `production` branch and merge `nonproduction` branch into it. Run `init` and `plan` and review output for environment production. ```bash + git checkout production + git merge nonproduction ./tf-wrapper.sh init production ./tf-wrapper.sh plan production ``` @@ -267,13 +287,15 @@ To use the `validate` option of the `tf-wrapper.sh` script, please follow the [i 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate production $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate production $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` production. +1. Run `apply` production and commit initial version of production. ```bash ./tf-wrapper.sh apply production + git add . + git commit -m "Production initial commit." ``` If you received any errors or made any changes to the Terraform config or `terraform.tfvars` you must re-run `./tf-wrapper.sh plan ` before running `./tf-wrapper.sh apply `. diff --git a/3-networks-dual-svpc/README.md b/3-networks-dual-svpc/README.md index 1a5255e3d..61ade0323 100644 --- a/3-networks-dual-svpc/README.md +++ b/3-networks-dual-svpc/README.md @@ -55,7 +55,6 @@ For an overview of the architecture and the parts, see the ## Purpose - The purpose of this step is to: - Set up the global [DNS Hub](https://cloud.google.com/blog/products/networking/cloud-forwarding-peering-and-zones). @@ -189,6 +188,7 @@ Run `terraform output cloudbuild_project_id` in the `0-bootstrap` folder to get sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./common.auto.tfvars ``` + **Note:** Make sure that you update the `perimeter_additional_members` variable with your user identity in order to be able to view/access resources in the project protected by the VPC Service Controls. 1. Commit changes @@ -281,12 +281,26 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s ### Run Terraform locally -1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Change into `3-networks-dual-svpc` folder, copy the Terraform wrapper script and ensure it can be executed. +1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Create and change into `gcp-network` folder, copy `3-networks-dual-svpc` content, the Terraform wrapper script and ensure it can be executed. Also, initialize git so you can manage versions locally. ```bash - cd terraform-example-foundation/3-networks-dual-svpc - cp ../build/tf-wrapper.sh . - chmod 755 ./tf-wrapper.sh + mkdir gcp-network + cp -R terraform-example-foundation/3-networks-dual-svpc/* gcp-network + cp terraform-example-foundation/build/tf-wrapper.sh gcp-network/ + cp terraform-example-foundation/.gitignore gcp-network/ + chmod 755 ./gcp-network/tf-wrapper.sh + ``` + +1. Navigate to `gcp-network` and initialize a local Git repository to manage versions locally. Then, create the environment branches. + + ```bash + cd gcp-network + git init + git commit -m "initialize empty directory" --allow-empty + git checkout -b shared + git checkout -b development + git checkout -b nonproduction + git checkout -b production ``` 1. Rename `common.auto.example.tfvars` to `common.auto.tfvars`, rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars`. @@ -300,40 +314,39 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s 1. Update `common.auto.tfvars` file with values from your environment and bootstrap. See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `common.auto.tfvars` file. 1. Update `shared.auto.tfvars` file with the `target_name_server_addresses`. 1. Update `access_context.auto.tfvars` file with the `access_context_manager_policy_id`. -1. Use `terraform output` to get the backend bucket value from 0-bootstrap output. +1. Use `terraform output` to get the backend bucket value from gcp-bootstrap output. ```bash - export ORGANIZATION_ID=$(terraform -chdir="../0-bootstrap/" output -json common_config | jq '.org_id' --raw-output) + export ORGANIZATION_ID=$(terraform -chdir="../gcp-bootstrap/" output -json common_config | jq '.org_id' --raw-output) export ACCESS_CONTEXT_MANAGER_ID=$(gcloud access-context-manager policies list --organization ${ORGANIZATION_ID} --format="value(name)") echo "access_context_manager_policy_id = ${ACCESS_CONTEXT_MANAGER_ID}" sed -i'' -e "s/ACCESS_CONTEXT_MANAGER_ID/${ACCESS_CONTEXT_MANAGER_ID}/" ./access_context.auto.tfvars - export backend_bucket=$(terraform -chdir="../0-bootstrap/" output -raw gcs_bucket_tfstate) + export backend_bucket=$(terraform -chdir="../gcp-bootstrap/" output -raw gcs_bucket_tfstate) echo "remote_state_bucket = ${backend_bucket}" sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./common.auto.tfvars ```` We will now deploy each of our environments(development/production/nonproduction) using this script. -When using Cloud Build or Jenkins as your CI/CD tool each environment corresponds to a branch in the repository for 3-networks-dual-svpc step -and only the corresponding environment is applied. To use the `validate` option of the `tf-wrapper.sh` script, please follow the [instructions](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install) to install the terraform-tools component. -1. Use `terraform output` to get the Cloud Build project ID and the environment step Terraform Service Account from 0-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. +1. Use `terraform output` to get the Seed project ID and the organization step Terraform service account from 0-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. ```bash - export CLOUD_BUILD_PROJECT_ID=$(terraform -chdir="../0-bootstrap/" output -raw cloudbuild_project_id) - echo ${CLOUD_BUILD_PROJECT_ID} + export SEED_PROJECT_ID=$(terraform -chdir="../gcp-bootstrap/" output -raw seed_project_id) + echo ${SEED_PROJECT_ID} - export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../0-bootstrap/" output -raw networks_step_terraform_service_account_email) + export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../gcp-bootstrap/" output -raw networks_step_terraform_service_account_email) echo ${GOOGLE_IMPERSONATE_SERVICE_ACCOUNT} ``` -1. Run `init` and `plan` and review output for environment shared. +1. Checkout `shared` branch. Run `init` and `plan` and review output for environment shared. ```bash + git checkout shared ./tf-wrapper.sh init shared ./tf-wrapper.sh plan shared ``` @@ -341,37 +354,45 @@ To use the `validate` option of the `tf-wrapper.sh` script, please follow the [i 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate shared $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate shared $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` 1. Run `apply` shared. ```bash ./tf-wrapper.sh apply shared + git add . + git commit -m "Initial shared commit." ``` -1. Run `init` and `plan` and review output for environment production. +1. Checkout `development` branch and merge `shared` into it. Run `init` and `plan` and review output for environment production. ```bash - ./tf-wrapper.sh init production - ./tf-wrapper.sh plan production + git checkout development + git merge shared + ./tf-wrapper.sh init development + ./tf-wrapper.sh plan development ``` 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate production $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate development $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` production. +1. Run `apply` development. ```bash - ./tf-wrapper.sh apply production + ./tf-wrapper.sh apply development + git add . + git commit -m "Initial development commit." ``` -1. Run `init` and `plan` and review output for environment nonproduction. +1. Checkout `nonproduction` and merge `development` into it. Run `init` and `plan` and review output for environment nonproduction. ```bash + git checkout nonproduction + git merge development ./tf-wrapper.sh init nonproduction ./tf-wrapper.sh plan nonproduction ``` @@ -379,32 +400,39 @@ To use the `validate` option of the `tf-wrapper.sh` script, please follow the [i 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate nonproduction $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate nonproduction $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` 1. Run `apply` nonproduction. ```bash ./tf-wrapper.sh apply nonproduction + git add . + git commit -m "Initial nonproduction commit." ``` -1. Run `init` and `plan` and review output for environment development. +1. Checkout shared `production`. Run `init` and `plan` and review output for environment development. ```bash - ./tf-wrapper.sh init development - ./tf-wrapper.sh plan development + git checkout production + git merge nonproduction + ./tf-wrapper.sh init production + ./tf-wrapper.sh plan production ``` 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate development $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate production $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` development. +1. Run `apply` production. ```bash - ./tf-wrapper.sh apply development + ./tf-wrapper.sh apply production + git add . + git commit -m "Initial production commit." + cd ../ ``` If you received any errors or made any changes to the Terraform config or any `.tfvars`, you must re-run `./tf-wrapper.sh plan ` before run `./tf-wrapper.sh apply `. diff --git a/3-networks-hub-and-spoke/README.md b/3-networks-hub-and-spoke/README.md index 22bb16932..2607a7e7c 100644 --- a/3-networks-hub-and-spoke/README.md +++ b/3-networks-hub-and-spoke/README.md @@ -192,6 +192,7 @@ Run `terraform output cloudbuild_project_id` in the `0-bootstrap` folder to get sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./common.auto.tfvars ``` + **Note:** Make sure that you update the `perimeter_additional_members` variable with your user identity in order to be able to view/access resources in the project protected by the VPC Service Controls. 1. Commit changes @@ -284,12 +285,25 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s ### Run Terraform locally -1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Change into `3-networks-hub-and-spoke` folder, copy the Terraform wrapper script and ensure it can be executed. +1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Create and change into `gcp-network` folder, copy `3-networks-hub-and-spoke` content, the Terraform wrapper script and ensure it can be executed. Also, initialize git so you can manage versions locally. ```bash - cd terraform-example-foundation/3-networks-hub-and-spoke - cp ../build/tf-wrapper.sh . - chmod 755 ./tf-wrapper.sh + mkdir gcp-network + cp -R terraform-example-foundation/3-networks-hub-and-spoke/* gcp-network/ + cp terraform-example-foundation/build/tf-wrapper.sh gcp-network/ + cp terraform-example-foundation/.gitignore gcp-network/ + chmod 755 ./gcp-environments/tf-wrapper.sh + ``` + +1. Navigate to `gcp-network` and initialize a local Git repository to manage versions locally. Then, create the environment branches. + + ```bash + cd gcp-network + git init + git checkout -b shared + git checkout -b development + git checkout -b nonproduction + git checkout -b production ``` 1. Rename `common.auto.example.tfvars` to `common.auto.tfvars`, rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars`. @@ -303,40 +317,39 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s 1. Update `common.auto.tfvars` file with values from your environment and bootstrap. See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `common.auto.tfvars` file. 1. Update `shared.auto.tfvars` file with the `target_name_server_addresses`. 1. Update `access_context.auto.tfvars` file with the `access_context_manager_policy_id`. -1. Use `terraform output` to get the backend bucket value from 0-bootstrap output. +1. Use `terraform output` to get the backend bucket value from gcp-bootstrap output. ```bash - export ORGANIZATION_ID=$(terraform -chdir="../0-bootstrap/" output -json common_config | jq '.org_id' --raw-output) + export ORGANIZATION_ID=$(terraform -chdir="../gcp-bootstrap/" output -json common_config | jq '.org_id' --raw-output) export ACCESS_CONTEXT_MANAGER_ID=$(gcloud access-context-manager policies list --organization ${ORGANIZATION_ID} --format="value(name)") echo "access_context_manager_policy_id = ${ACCESS_CONTEXT_MANAGER_ID}" sed -i'' -e "s/ACCESS_CONTEXT_MANAGER_ID/${ACCESS_CONTEXT_MANAGER_ID}/" ./access_context.auto.tfvars - export backend_bucket=$(terraform -chdir="../0-bootstrap/" output -raw gcs_bucket_tfstate) + export backend_bucket=$(terraform -chdir="../gcp-bootstrap/" output -raw gcs_bucket_tfstate) echo "remote_state_bucket = ${backend_bucket}" sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./common.auto.tfvars - ``` + ```` We will now deploy each of our environments(development/production/nonproduction) using this script. -When using Cloud Build or Jenkins as your CI/CD tool each environment corresponds to a branch in the repository for 3-networks-hub-and-spoke step -and only the corresponding environment is applied. To use the `validate` option of the `tf-wrapper.sh` script, please follow the [instructions](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install) to install the terraform-tools component. -1. Use `terraform output` to get the Cloud Build project ID and the networks step Terraform Service Account from 0-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. +1. Use `terraform output` to get the Seed project ID and the organization step Terraform service account from 0-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. ```bash - export CLOUD_BUILD_PROJECT_ID=$(terraform -chdir="../0-bootstrap/" output -raw cloudbuild_project_id) - echo ${CLOUD_BUILD_PROJECT_ID} + export SEED_PROJECT_ID=$(terraform -chdir="../gcp-bootstrap/" output -raw seed_project_id) + echo ${SEED_PROJECT_ID} - export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../0-bootstrap/" output -raw networks_step_terraform_service_account_email) + export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../gcp-bootstrap/" output -raw networks_step_terraform_service_account_email) echo ${GOOGLE_IMPERSONATE_SERVICE_ACCOUNT} ``` -1. Run `init` and `plan` and review output for environment shared. +1. Checkout `shared` branch. Run `init` and `plan` and review output for environment shared. ```bash + git checkout shared ./tf-wrapper.sh init shared ./tf-wrapper.sh plan shared ``` @@ -344,37 +357,45 @@ To use the `validate` option of the `tf-wrapper.sh` script, please follow the [i 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate shared $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate shared $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` 1. Run `apply` shared. ```bash ./tf-wrapper.sh apply shared + git add . + git commit -m "Initial shared commit." ``` -1. Run `init` and `plan` and review output for environment production. +1. Checkout `development` branch and merge `shared` into it. Run `init` and `plan` and review output for environment production. ```bash - ./tf-wrapper.sh init production - ./tf-wrapper.sh plan production + git checkout development + git merge shared + ./tf-wrapper.sh init development + ./tf-wrapper.sh plan development ``` 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate production $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate development $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` production. +1. Run `apply` development. ```bash - ./tf-wrapper.sh apply production + ./tf-wrapper.sh apply development + git add . + git commit -m "Initial development commit." ``` -1. Run `init` and `plan` and review output for environment nonproduction. +1. Checkout `nonproduction` and merge `development` into it. Run `init` and `plan` and review output for environment nonproduction. ```bash + git checkout nonproduction + git merge development ./tf-wrapper.sh init nonproduction ./tf-wrapper.sh plan nonproduction ``` @@ -382,32 +403,39 @@ To use the `validate` option of the `tf-wrapper.sh` script, please follow the [i 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate nonproduction $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate nonproduction $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` 1. Run `apply` nonproduction. ```bash ./tf-wrapper.sh apply nonproduction + git add . + git commit -m "Initial nonproduction commit." ``` -1. Run `init` and `plan` and review output for environment development. +1. Checkout shared `production`. Run `init` and `plan` and review output for environment development. ```bash - ./tf-wrapper.sh init development - ./tf-wrapper.sh plan development + git checkout production + git merge nonproduction + ./tf-wrapper.sh init production + ./tf-wrapper.sh plan production ``` 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate development $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate production $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` development. +1. Run `apply` production. ```bash - ./tf-wrapper.sh apply development + ./tf-wrapper.sh apply production + git add . + git commit -m "Initial production commit." + cd ../ ``` If you received any errors or made any changes to the Terraform config or any `.tfvars`, you must re-run `./tf-wrapper.sh plan ` before run `./tf-wrapper.sh apply `. diff --git a/4-projects/README.md b/4-projects/README.md index 914863ddf..d092afb3c 100644 --- a/4-projects/README.md +++ b/4-projects/README.md @@ -144,9 +144,10 @@ For example, to create a new business unit similar to business_unit_1, run the f # search all files under the folder `business_unit_2` and replace strings for business_unit_1 with strings for business_unit_2 grep -rl bu1 business_unit_2/ | xargs sed -i 's/bu1/bu2/g' grep -rl business_unit_1 business_unit_2/ | xargs sed -i 's/business_unit_1/business_unit_2/g' + # search subnet_ip_range 10.3.64.0 and replace for the new range 10.4.64.0 + grep -rl 10.3.64.0 business_unit_2/ | xargs sed -i 's/10.3.64.0/10.4.64.0/g' ``` - 1. Commit changes. ```bash @@ -237,12 +238,26 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s ### Run Terraform locally -1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Change into `4-projects` folder, copy the Terraform wrapper script and ensure it can be executed. +1. The next instructions assume that you are at the same level of the `terraform-example-foundation` folder. Create and change into `gcp-projects` folder, copy the code, Terraform wrapper script and ensure it can be executed. ```bash - cd terraform-example-foundation/4-projects - cp ../build/tf-wrapper.sh . - chmod 755 ./tf-wrapper.sh + mkdir gcp-projects + cp -R terraform-example-foundation/4-projects/* gcp-projects/ + cp terraform-example-foundation/build/tf-wrapper.sh gcp-projects/ + cp terraform-example-foundation/.gitignore gcp-projects/ + chmod 755 ./gcp-projects/tf-wrapper.sh + ``` + +1. Navigate to `gcp-projects` and initialize a local Git repository to manage versions locally. Then, create the environment branches. + + ```bash + cd gcp-projects + git init + git commit -m "initialize empty directory" --allow-empty + git checkout -b shared + git checkout -b development + git checkout -b nonproduction + git checkout -b production ``` 1. Rename `auto.example.tfvars` files to `auto.tfvars`. @@ -257,30 +272,30 @@ See `0-bootstrap` [README-GitHub.md](../0-bootstrap/README-GitHub.md#deploying-s 1. See any of the envs folder [README.md](./business_unit_1/production/README.md) files for additional information on the values in the `common.auto.tfvars`, `development.auto.tfvars`, `nonproduction.auto.tfvars`, and `production.auto.tfvars` files. See any of the shared folder [README.md](./business_unit_1/shared/README.md) files for additional information on the values in the `shared.auto.tfvars` file. - Use `terraform output` to get the remote state bucket (the backend bucket used by previous steps) value from `0-bootstrap` output. + Use `terraform output` to get the remote state bucket (the backend bucket used by previous steps) value from `gcp-bootstrap` output. ```bash - export remote_state_bucket=$(terraform -chdir="../0-bootstrap/" output -raw gcs_bucket_tfstate) + export remote_state_bucket=$(terraform -chdir="../gcp-bootstrap/" output -raw gcs_bucket_tfstate) echo "remote_state_bucket = ${remote_state_bucket}" sed -i'' -e "s/REMOTE_STATE_BUCKET/${remote_state_bucket}/" ./common.auto.tfvars ``` We will now deploy each of our environments(development/production/nonproduction) using the `tf-wrapper.sh` script. -When using Cloud Build or Jenkins as your CI/CD tool each environment corresponds to a branch is the repository for 4-projects step and only the corresponding environment is applied. Environment shared must be applied first because development, nonproduction, and production depend on it. To use the `validate` option of the `tf-wrapper.sh` script, please follow the [instructions](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install) to install the terraform-tools component. -1. Use `terraform output` to get the Cloud Build Project ID and the environment step Terraform Service Account from 0-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. +1. Use `terraform output` to get the Seed project ID and the organization step Terraform service account from gcp-bootstrap output. An environment variable `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` will be set using the Terraform Service Account to enable impersonation. ```bash - export CLOUD_BUILD_PROJECT_ID=$(terraform -chdir="../0-bootstrap/" output -raw cloudbuild_project_id) - echo ${CLOUD_BUILD_PROJECT_ID} + export SEED_PROJECT_ID=$(terraform -chdir="../gcp-bootstrap/" output -raw seed_project_id) + echo ${SEED_PROJECT_ID} - export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../0-bootstrap/" output -raw projects_step_terraform_service_account_email) + export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=$(terraform -chdir="../gcp-bootstrap/" output -raw projects_step_terraform_service_account_email) echo ${GOOGLE_IMPERSONATE_SERVICE_ACCOUNT} ``` + 1. (Optional) If you want additional subfolders for separate business units or entities, make additional copies of the folder `business_unit_1` and modify any values that vary across business unit like `business_code`, `business_unit`, or `subnet_ip_range`. For example, to create a new business unit similar to business_unit_1, run the following: @@ -292,12 +307,14 @@ For example, to create a new business unit similar to business_unit_1, run the f # search all files under the folder `business_unit_2` and replace strings for business_unit_1 with strings for business_unit_2 grep -rl bu1 business_unit_2/ | xargs sed -i 's/bu1/bu2/g' grep -rl business_unit_1 business_unit_2/ | xargs sed -i 's/business_unit_1/business_unit_2/g' + # search subnet_ip_range 10.3.64.0 and replace for the new range 10.4.64.0 + grep -rl 10.3.64.0 business_unit_2/ | xargs sed -i 's/10.3.64.0/10.4.64.0/g' ``` - -1. Run `init` and `plan` and review output for environment shared. +1. Checkout `shared` branch. Run `init` and `plan` and review output for environment shared. ```bash + git checkout shared ./tf-wrapper.sh init shared ./tf-wrapper.sh plan shared ``` @@ -305,37 +322,45 @@ For example, to create a new business unit similar to business_unit_1, run the f 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate shared $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate shared $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` 1. Run `apply` shared. ```bash ./tf-wrapper.sh apply shared + git add . + git commit -m "Initial shared commit." ``` -1. Run `init` and `plan` and review output for environment production. +1. Checkout `development` branch and merge `shared` into it. Run `init` and `plan` and review output for environment production. ```bash - ./tf-wrapper.sh init production - ./tf-wrapper.sh plan production + git checkout development + git merge shared + ./tf-wrapper.sh init development + ./tf-wrapper.sh plan development ``` 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate production $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate development $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` production. +1. Run `apply` development. ```bash - ./tf-wrapper.sh apply production + ./tf-wrapper.sh apply development + git add . + git commit -m "Initial development commit." ``` -1. Run `init` and `plan` and review output for environment nonproduction. +1. Checkout `nonproduction` and merge `development` into it. Run `init` and `plan` and review output for environment nonproduction. ```bash + git checkout nonproduction + git merge development ./tf-wrapper.sh init nonproduction ./tf-wrapper.sh plan nonproduction ``` @@ -343,35 +368,42 @@ For example, to create a new business unit similar to business_unit_1, run the f 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate nonproduction $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate nonproduction $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` 1. Run `apply` nonproduction. ```bash ./tf-wrapper.sh apply nonproduction + git add . + git commit -m "Initial nonproduction commit." ``` -1. Run `init` and `plan` and review output for environment development. +1. Checkout shared `production`. Run `init` and `plan` and review output for environment development. ```bash - ./tf-wrapper.sh init development - ./tf-wrapper.sh plan development + git checkout production + git merge nonproduction + ./tf-wrapper.sh init production + ./tf-wrapper.sh plan production ``` 1. Run `validate` and check for violations. ```bash - ./tf-wrapper.sh validate development $(pwd)/../policy-library ${CLOUD_BUILD_PROJECT_ID} + ./tf-wrapper.sh validate production $(pwd)/../gcp-policies ${SEED_PROJECT_ID} ``` -1. Run `apply` development. +1. Run `apply` production. ```bash - ./tf-wrapper.sh apply development + ./tf-wrapper.sh apply production + git add . + git commit -m "Initial production commit." + cd ../ ``` -If you received any errors or made any changes to the Terraform config or any `.tfvars`, you must re-run `./tf-wrapper.sh plan ` before running `./tf-wrapper.sh apply `. +If you received any errors or made any changes to the Terraform config or any `.tfvars`, you must re-run `./tf-wrapper.sh plan ` before run `./tf-wrapper.sh apply `. Before executing the next stages, unset the `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` environment variable. diff --git a/4-projects/business_unit_1/development/main.tf b/4-projects/business_unit_1/development/main.tf index 1ad8a4131..e06845839 100644 --- a/4-projects/business_unit_1/development/main.tf +++ b/4-projects/business_unit_1/development/main.tf @@ -23,6 +23,7 @@ module "env" { remote_state_bucket = var.remote_state_bucket location_kms = coalesce(var.location_kms, local.default_region_kms) location_gcs = coalesce(var.location_gcs, local.default_region_gcs) + keyring_name = "bu1-sample-keyring" gcs_custom_placement_config = { data_locations = [ upper(local.default_region), diff --git a/4-projects/business_unit_1/nonproduction/main.tf b/4-projects/business_unit_1/nonproduction/main.tf index b8a4514b7..2086a4494 100644 --- a/4-projects/business_unit_1/nonproduction/main.tf +++ b/4-projects/business_unit_1/nonproduction/main.tf @@ -22,6 +22,7 @@ module "env" { business_unit = "business_unit_1" remote_state_bucket = var.remote_state_bucket location_kms = coalesce(var.location_kms, local.default_region_kms) + keyring_name = "bu1-sample-keyring" location_gcs = coalesce(var.location_gcs, local.default_region_gcs) gcs_custom_placement_config = { data_locations = [ diff --git a/4-projects/business_unit_1/production/main.tf b/4-projects/business_unit_1/production/main.tf index 4bf4b9f74..68d2a73ad 100644 --- a/4-projects/business_unit_1/production/main.tf +++ b/4-projects/business_unit_1/production/main.tf @@ -22,6 +22,7 @@ module "env" { business_unit = "business_unit_1" remote_state_bucket = var.remote_state_bucket location_kms = coalesce(var.location_kms, local.default_region_kms) + keyring_name = "bu1-sample-keyring" location_gcs = coalesce(var.location_gcs, local.default_region_gcs) gcs_custom_placement_config = { data_locations = [ diff --git a/test/integration/testutils/retry.go b/test/integration/testutils/retry.go index 8b86d38f2..e50bc2a45 100644 --- a/test/integration/testutils/retry.go +++ b/test/integration/testutils/retry.go @@ -39,5 +39,8 @@ var ( // Error 403: Compute Engine API has not been used in project {} before or it is disabled. ".*Error 403.*Compute Engine API has not been used in project.*": "Compute Engine API not enabled", + + // Error 400: Service account {} does not exist. + ".*Error 400.*Service account.*does not exist*": "Error setting IAM policy", } )