diff --git a/0-bootstrap/README-Jenkins.md b/0-bootstrap/README-Jenkins.md index 393d81126..4bef9f831 100644 --- a/0-bootstrap/README-Jenkins.md +++ b/0-bootstrap/README-Jenkins.md @@ -6,12 +6,12 @@ Another CICD option is to use Cloud Build & Cloud Source Repos. If you don't hav ## Overview -The objective of the instructions below is to configure the infrastructure that allows you to run CICD deployments for the next stages (`1-org, 2-environments, 3-networks, 4-projects`) using Jenkins. The infrastructure consists in two Google Cloud Platform projects (`cft-seed` and `prj-cicd`) and VPN configuration to connect to your on-prem environment. +The objective of the instructions below is to configure the infrastructure that allows you to run CICD deployments for the next stages (`1-org, 2-environments, 3-networks, 4-projects`) using Jenkins. The infrastructure consists in two Google Cloud Platform projects (`prj-seed` and `prj-cicd`) and VPN configuration to connect to your on-prem environment. -It is a best practice to have two separate projects here (`cft-seed` and `prj-cicd`) for separation of concerns. On one hand, `cft-seed` stores terraform state and has the Service Account able to create / modify infrastructure. On the other hand, the deployment of that infrastructure is coordinated by Jenkins, which is implemented in `prj-cicd` and connected to your Master on-prem. +It is a best practice to have two separate projects here (`prj-seed` and `prj-cicd`) for separation of concerns. On one hand, `prj-seed` stores terraform state and has the Service Account able to create / modify infrastructure. On the other hand, the deployment of that infrastructure is coordinated by Jenkins, which is implemented in `prj-cicd` and connected to your Master on-prem. **After following the instructions below, you will have:** -- The `cft-seed` project, which contains: +- The `prj-seed` project, which contains: - Terraform state bucket - Custom Service Account used by Terraform to create new resources in GCP - The `prj-cicd` project, which contains: @@ -20,7 +20,7 @@ It is a best practice to have two separate projects here (`cft-seed` and `prj-ci - FW rules to allow communication over port 22 - VPN connection with on-prem (or where ever your Jenkins Master is located) - Custom service account `sa-jenkins-agent-gce@prj-cicd-xxxx.iam.gserviceaccount.com` for the GCE instance. - - This service account is granted the access to generate tokens on the Terraform custom service account in the `cft-seed` project + - This service account is granted the access to generate tokens on the Terraform custom service account in the `prj-seed` project - **Note: these instructions do not indicate how to create a Jenkins Master.** To deploy a Jenkins Master, you should follow [Jenkins Architecture](https://www.jenkins.io/doc/book/architecting-for-scale/) recommendations. @@ -135,7 +135,7 @@ You arrived to these instructions because you are using the `jenkins_bootstrap` 1. Open the link in your browser and accept. 1. Run terraform commands. - - After the credentials are configured, we will create the `cft-seed` project (which contains the GCS state bucket and Terraform custom service account) and the `prj-cicd` project (which contains the Jenkins Agent, its custom service account and where we will add VPN configuration) + - After the credentials are configured, we will create the `prj-seed` project (which contains the GCS state bucket and Terraform custom service account) and the `prj-cicd` project (which contains the Jenkins Agent, its custom service account and where we will add VPN configuration) - **WARNING: Make sure you have commented-out the `cloudbuild_bootstrap` module and enabled the `jenkins_bootstrap` module in the `./main.tf` file** - **Use Terraform 0.13.6** to run the terraform script with the commands below ``` diff --git a/0-bootstrap/README.md b/0-bootstrap/README.md index 5c1e9914a..435261b68 100644 --- a/0-bootstrap/README.md +++ b/0-bootstrap/README.md @@ -8,24 +8,25 @@ The purpose of this step is to bootstrap a GCP organization, creating all the re 1. A GCP [Billing Account](https://cloud.google.com/billing/docs/how-to/manage-billing-account) 1. Cloud Identity / Google Workspace (former G Suite) groups for organization and billing admins 1. User account should be used for running this step, service accounts are not supported. -1. Membership in the `group_org_admins` group for user running terraform. -1. Grant the roles mentioned in bootstrap [README.md](https://github.com/terraform-google-modules/terraform-google-bootstrap#permissions), as well as `roles/resourcemanager.folderCreator` for the user running the step. +1. Membership in the `group_org_admins` group for the user running terraform. +1. Grant the roles mentioned in bootstrap module [README.md](https://github.com/terraform-google-modules/terraform-google-bootstrap#permissions), as well as `roles/resourcemanager.folderCreator` for the user running the step. -Further details of permissions required and resources created, can be found in the bootstrap module [documentation.](https://github.com/terraform-google-modules/terraform-google-bootstrap) +Further details of groups, permissions required and resources created, can be found in the bootstrap module [documentation.](https://github.com/terraform-google-modules/terraform-google-bootstrap) **Note:** when running the examples in this repository, you may receive various errors when applying terraform: -- `Error code 8, message: The project cannot be created because you have exceeded your allotted project quota.`. That means you have reached your [Project creation quota](https://support.google.com/cloud/answer/6330231). In this case you can use this [Request Project Quota Increase](https://support.google.com/code/contact/project_quota_increase) form to request a quota increase. The `terraform_sa_email` created in `0-bootstrap` should also be listed in "Email addresses that will be used to create projects" in that support form. If you face others quota errors, check the [Quota documentation](https://cloud.google.com/docs/quota) for guidence. + +- `Error code 8, message: The project cannot be created because you have exceeded your allotted project quota.`. That means you have reached your [Project creation quota](https://support.google.com/cloud/answer/6330231). In this case you can use this [Request Project Quota Increase](https://support.google.com/code/contact/project_quota_increase) form to request a quota increase. The `terraform_service_account` created in `0-bootstrap` should also be listed in "Email addresses that will be used to create projects" in that support form. If you face others quota errors, check the [Quota documentation](https://cloud.google.com/docs/quota) for guidance. - `Error: Error when reading or editing Organization Not Found : : googleapi: Error 403: The caller does not have permission, forbidden`. - - Check that your user have [Organization Admin](https://cloud.google.com/iam/docs/understanding-roles#resource-manager-roles) predefined role at the Organization level. - - If this is the case, try the following: - ``` - gcloud auth application-default login - gcloud auth list # <- confirm that correct account has a star next to it - ``` - - Re-run `terraform` after. + - Check that your user have [Organization Admin](https://cloud.google.com/iam/docs/understanding-roles#resource-manager-roles) predefined role at the Organization level. + - If this is the case, try the following: + ``` + gcloud auth application-default login + gcloud auth list # <- confirm that correct account has a star next to it + ``` + - Re-run `terraform` after. - `Error: Error setting billing account "XXXXXX-XXXXXX-XXXXXX" for project "projects/some-project": googleapi: Error 400: Precondition check failed., failedPrecondition`. Most likely this is related to billing quota issue. - - To confirm this, try `gcloud alpha billing projects link projects/some-project --billing-account XXXXXX-XXXXXX-XXXXXX`. - - If output states `Cloud billing quota exceeded`, please request increase via [https://support.google.com/code/contact/billing_quota_increase](https://support.google.com/code/contact/billing_quota_increase). + - To confirm this, try `gcloud alpha billing projects link projects/some-project --billing-account XXXXXX-XXXXXX-XXXXXX`. + - If output states `Cloud billing quota exceeded`, please request increase via [https://support.google.com/code/contact/billing_quota_increase](https://support.google.com/code/contact/billing_quota_increase). ## 0-bootstrap usage to deploy Jenkins @@ -77,13 +78,13 @@ Currently, the bucket information is replaced in the state backends as a part of |------|-------------| | cloudbuild\_project\_id | Project where CloudBuild configuration and terraform container image will reside. | | csr\_repos | List of Cloud Source Repos created by the module, linked to Cloud Build triggers. | -| gcs\_bucket\_cloudbuild\_artifacts | Bucket used to store Cloud/Build artefacts in CloudBuild project. | +| gcs\_bucket\_cloudbuild\_artifacts | Bucket used to store Cloud/Build artifacts in CloudBuild project. | | gcs\_bucket\_tfstate | Bucket used for storing terraform state for foundations pipelines in seed project. | | kms\_crypto\_key | KMS key created by the module. | | kms\_keyring | KMS Keyring created by the module. | | seed\_project\_id | Project where service accounts and core APIs will be enabled. | -| terraform\_sa\_email | Email for privileged service account for Terraform. | | terraform\_sa\_name | Fully qualified name for privileged service account for Terraform. | +| terraform\_service\_account | Email for privileged service account for Terraform. | @@ -93,4 +94,4 @@ Currently, the bucket information is replaced in the state backends as a part of - [gcloud sdk](https://cloud.google.com/sdk/install) >= 206.0.0 - [Terraform](https://www.terraform.io/downloads.html) >= 0.13.6 - - You should use the same version in the manual steps during 0-bootstrap to avoid possible [Terraform State Snapshot Lock](https://github.com/hashicorp/terraform/issues/23290) errors caused by differences in terraform versions. This can usually be resolved with a version upgrade. + - You should use the same version in the manual steps during 0-bootstrap to avoid possible [Terraform State Snapshot Lock](https://github.com/hashicorp/terraform/issues/23290) errors caused by differences in terraform versions. This can usually be resolved with a version upgrade. diff --git a/0-bootstrap/main.tf b/0-bootstrap/main.tf index c9a79ce18..6a0064f90 100644 --- a/0-bootstrap/main.tf +++ b/0-bootstrap/main.tf @@ -214,7 +214,7 @@ resource "google_folder_iam_member" "folder_tf_compute_security_resource_admin" # billing_account = var.billing_account # group_org_admins = var.group_org_admins # default_region = var.default_region -# terraform_sa_email = module.seed_bootstrap.terraform_sa_email +# terraform_service_account = module.seed_bootstrap.terraform_sa_email # terraform_sa_name = module.seed_bootstrap.terraform_sa_name # terraform_state_bucket = module.seed_bootstrap.gcs_bucket_tfstate # sa_enable_impersonation = true diff --git a/0-bootstrap/modules/jenkins-agent/README.md b/0-bootstrap/modules/jenkins-agent/README.md index 04fa3e5e9..f8321b28b 100644 --- a/0-bootstrap/modules/jenkins-agent/README.md +++ b/0-bootstrap/modules/jenkins-agent/README.md @@ -23,7 +23,7 @@ module "jenkins_bootstrap" { billing_account = "" group_org_admins = "gcp-organization-admins@example.com" default_region = "us-central1" - terraform_sa_email = "" # normally module.seed_bootstrap.terraform_sa_email + terraform_service_account = "" # normally module.seed_bootstrap.terraform_sa_email terraform_sa_name = "" # normally module.seed_bootstrap.terraform_sa_name terraform_state_bucket = "" # normally module.seed_bootstrap.gcs_bucket_tfstate sa_enable_impersonation = true @@ -76,8 +76,8 @@ module "jenkins_bootstrap" { | service\_account\_prefix | Name prefix to use for service accounts. | `string` | `"sa"` | no | | storage\_bucket\_labels | Labels to apply to the storage bucket. | `map(string)` | `{}` | no | | storage\_bucket\_prefix | Name prefix to use for storage buckets. | `string` | `"bkt"` | no | -| terraform\_sa\_email | Email for terraform service account. It must be supplied by the seed project | `string` | n/a | yes | | terraform\_sa\_name | Fully-qualified name of the terraform service account. It must be supplied by the seed project | `string` | n/a | yes | +| terraform\_service\_account | Email for terraform service account. It must be supplied by the seed project | `string` | n/a | yes | | terraform\_state\_bucket | Default state bucket, used in Cloud Build substitutions. It must be supplied by the seed project | `string` | n/a | yes | | terraform\_version | Default terraform version. | `string` | `"0.13.6"` | no | | terraform\_version\_sha256sum | sha256sum for default terraform version. | `string` | `"55f2db00b05675026be9c898bdd3e8230ff0c5c78dd12d743ca38032092abfc9"` | no | @@ -135,7 +135,7 @@ Error: google: could not find default credentials. See https://developers.google ``` ``` -Error: Error setting billing account "aaaaaa-bbbbbb-cccccc" for project "projects/cft-jenkins-dc3a": googleapi: Error 400: Precondition check failed., failedPrecondition +Error: Error setting billing account "aaaaaa-bbbbbb-cccccc" for project "projects/prj-jenkins-dc3a": googleapi: Error 400: Precondition check failed., failedPrecondition on .terraform/modules/jenkins/terraform-google-project-factory-7.1.0/modules/core_project_factory/main.tf line 96, in resource "google_project" "main": 96: resource "google_project" "main" { ``` diff --git a/0-bootstrap/modules/jenkins-agent/variables.tf b/0-bootstrap/modules/jenkins-agent/variables.tf index fb69d473e..80cc2a5eb 100644 --- a/0-bootstrap/modules/jenkins-agent/variables.tf +++ b/0-bootstrap/modules/jenkins-agent/variables.tf @@ -141,7 +141,7 @@ variable "tunnel1_bgp_session_range" { /* ---------------------------------------- Specific to Seed Project ---------------------------------------- */ -variable "terraform_sa_email" { +variable "terraform_service_account" { description = "Email for terraform service account. It must be supplied by the seed project" type = string } diff --git a/0-bootstrap/outputs.tf b/0-bootstrap/outputs.tf index 8b42ba4d3..3cfbcdd55 100644 --- a/0-bootstrap/outputs.tf +++ b/0-bootstrap/outputs.tf @@ -19,7 +19,7 @@ output "seed_project_id" { value = module.seed_bootstrap.seed_project_id } -output "terraform_sa_email" { +output "terraform_service_account" { description = "Email for privileged service account for Terraform." value = module.seed_bootstrap.terraform_sa_email } @@ -44,7 +44,7 @@ output "cloudbuild_project_id" { } output "gcs_bucket_cloudbuild_artifacts" { - description = "Bucket used to store Cloud/Build artefacts in CloudBuild project." + description = "Bucket used to store Cloud/Build artifacts in CloudBuild project." value = module.cloudbuild_bootstrap.gcs_bucket_cloudbuild_artifacts } diff --git a/1-org/README.md b/1-org/README.md index 7d0af6613..afe332663 100644 --- a/1-org/README.md +++ b/1-org/README.md @@ -15,11 +15,11 @@ Enabling Data Access logs might result in your project being charged for the add For details on costs you might incur, go to [Pricing](https://cloud.google.com/stackdriver/pricing). You can choose not to enable the Data Access logs by setting variable `data_access_logs_enabled` to false. -**Note:** This module creates sink to export all logs to Google Storage. It's also create sinks to export a subset of security related logs +**Note:** This module creates a sink to export all logs to Google Storage. It also creates sinks to export a subset of security related logs to Bigquery and Pub/Sub. This will result in additional charges for those copies of logs. You can change the filters & sinks by modifying the configuration in `envs/shared/log_sinks.tf`. -**Note:** Currently, this module does not enable bucket policy retention for organization logs, please, enable it if needed. +**Note:** Currently, this module does not enable [bucket policy retention](https://cloud.google.com/storage/docs/bucket-lock) for organization logs, please, enable it if needed. **Note:** It is possible to enable an organization policy for [OS Login](https://cloud.google.com/compute/docs/oslogin/manage-oslogin-in-an-org) with this module. OS Login has some [limitations](https://cloud.google.com/compute/docs/instances/managing-instance-access#limitations). @@ -27,20 +27,20 @@ If those limitations do not apply to your workload/environment you can choose to ### Setup to run via Cloud Build -1. Clone repo `gcloud source repos clone gcp-policies --project=YOUR_CLOUD_BUILD_PROJECT_ID`. +1. Clone repo `gcloud source repos clone gcp-policies --project=YOUR_CLOUD_BUILD_PROJECT_ID` (this is from the terraform output from the previous section, run `terraform output cloudbuild_project_id` in the `0-bootstrap` folder). 1. Navigate into the repo `cd gcp-policies`. 1. Copy contents of policy-library to new repo `cp -RT ../terraform-example-foundation/policy-library/ .` (modify accordingly based on your current directory). 1. Commit changes with `git add .` and `git commit -m 'Your message'`. 1. Push your master branch to the new repo `git push --set-upstream origin master`. 1. Navigate out of the repo `cd ..`. -1. Clone repo `gcloud source repos clone gcp-org --project=YOUR_CLOUD_BUILD_PROJECT_ID` (this is from terraform output from the previous section, 0-bootstrap). +1. Clone repo `gcloud source repos clone gcp-org --project=YOUR_CLOUD_BUILD_PROJECT_ID`. 1. Navigate into the repo `cd gcp-org` and change to a non production branch `git checkout -b plan`. 1. Copy contents of foundation to new repo `cp -RT ../terraform-example-foundation/1-org/ .` (modify accordingly based on your current directory). 1. Copy cloud build configuration files for terraform `cp ../terraform-example-foundation/build/cloudbuild-tf-* . ` (modify accordingly based on your current directory). 1. Copy terraform wrapper script `cp ../terraform-example-foundation/build/tf-wrapper.sh . ` to the root of your new repository (modify accordingly based on your current directory). 1. Ensure wrapper script can be executed `chmod 755 ./tf-wrapper.sh`. -1. Check if your organization already has a Access Context Manager Policy `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. -1. Rename `./envs/shared/terraform.example.tfvars` to `./envs/shared/terraform.tfvars` and update the file with values from your environment and bootstrap (you can re-run `terraform output` in the 0-bootstrap directory to find these values). Make sure that `default_region` is set to a valid [BigQuery dataset region](https://cloud.google.com/bigquery/docs/locations). Also if the previous step showed a numeric value, make sure to un-comment the variable `create_access_context_manager_access_policy = false`. +1. Check if your organization already has a Access Context Manager Policy `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. +1. Rename `./envs/shared/terraform.example.tfvars` to `./envs/shared/terraform.tfvars` and update the file with values from your environment and bootstrap step (you can re-run `terraform output` in the 0-bootstrap directory to find these values). Make sure that `default_region` is set to a valid [BigQuery dataset region](https://cloud.google.com/bigquery/docs/locations). Also if the previous step showed a numeric value, make sure to 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. Commit changes with `git add .` and `git commit -m 'Your message'`. 1. Push your plan branch to trigger a plan `git push --set-upstream origin plan` (the branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan). 1. Review the plan output in your cloud build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID @@ -62,8 +62,8 @@ If those limitations do not apply to your workload/environment you can choose to ``` 1. Copy terraform wrapper script `cp ../terraform-example-foundation/build/tf-wrapper.sh . ` to the root of your new repository (modify accordingly based on your current directory). 1. Ensure wrapper script can be executed `chmod 755 ./tf-wrapper.sh`. -1. Check if your organization already has a Access Context Manager Policy `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. -1. Rename `./envs/shared/terraform.example.tfvars` to `./envs/shared/terraform.tfvars` and update the file with values from your environment and bootstrap (you can re-run `terraform output` in the 0-bootstrap directory to find these values). Make sure that `default_region` is set to a valid [BigQuery dataset region](https://cloud.google.com/bigquery/docs/locations). Also if the previous step showed a numeric value, make sure to un-comment the variable `create_access_context_manager_access_policy = false`. +1. Check if your organization already has a Access Context Manager Policy `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. +1. Rename `./envs/shared/terraform.example.tfvars` to `./envs/shared/terraform.tfvars` and update the file with values from your environment and bootstrap (you can re-run `terraform output` in the 0-bootstrap directory to find these values). Make sure that `default_region` is set to a valid [BigQuery dataset region](https://cloud.google.com/bigquery/docs/locations). Also if the previous step showed a numeric value, make sure to 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. Commit changes with `git add .` and `git commit -m 'Your message'` 1. Push your plan branch `git push --set-upstream origin plan`. The branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan. - Assuming you configured an automatic trigger in your Jenkins Master (see [Jenkins sub-module README](../0-bootstrap/modules/jenkins-agent)), this will trigger a plan. You can also trigger a Jenkins job manually. Given the many options to do this in Jenkins, it is out of the scope of this document see [Jenkins website](http://www.jenkins.io) for more details. diff --git a/1-org/envs/shared/README.md b/1-org/envs/shared/README.md index 5520c24d6..20995e4e0 100644 --- a/1-org/envs/shared/README.md +++ b/1-org/envs/shared/README.md @@ -17,9 +17,9 @@ | dns\_hub\_project\_alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` for the DNS hub project. | `string` | `null` | no | | dns\_hub\_project\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded for the DNS hub project. | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | dns\_hub\_project\_budget\_amount | The amount to use as the budget for the DNS hub project. | `number` | `1000` | no | -| domains\_to\_allow | The list of domains to allow users from in IAM. | `list(string)` | n/a | yes | +| domains\_to\_allow | The list of domains to allow users from in IAM. Used by Domain Restricted Sharing Organization Policy. | `list(string)` | n/a | yes | | enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | -| enable\_os\_login\_policy | Enable OS Login policy. | `bool` | `false` | no | +| enable\_os\_login\_policy | Enable OS Login Organization Policy. | `bool` | `false` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | interconnect\_project\_alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` for the Dedicated Interconnect project. | `string` | `null` | no | | interconnect\_project\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded for the Dedicated Interconnect project. | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | @@ -43,8 +43,8 @@ | restricted\_net\_hub\_project\_alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` for the restricted net hub project. | `string` | `null` | no | | restricted\_net\_hub\_project\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded for the restricted net hub project. | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | restricted\_net\_hub\_project\_budget\_amount | The amount to use as the budget for the restricted net hub project. | `number` | `1000` | no | -| scc\_notification\_filter | Filter used to SCC Notification, you can see more details how to create filters in https://cloud.google.com/security-command-center/docs/how-to-api-filter-notifications#create-filter | `string` | `"state=\\\"ACTIVE\\\""` | no | -| scc\_notification\_name | Name of SCC Notification | `string` | n/a | yes | +| scc\_notification\_filter | Filter used to create the Security Command Center Notification, you can see more details on how to create filters in https://cloud.google.com/security-command-center/docs/how-to-api-filter-notifications#create-filter | `string` | `"state=\\\"ACTIVE\\\""` | no | +| scc\_notification\_name | Name of the Security Command Center Notification. It must be unique in the organization. Run `gcloud scc notifications describe --organization=org_id` to check if it already exists. | `string` | n/a | yes | | scc\_notifications\_project\_alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` for the SCC notifications project. | `string` | `null` | no | | scc\_notifications\_project\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded for the SCC notifications project. | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | scc\_notifications\_project\_budget\_amount | The amount to use as the budget for the SCC notifications project. | `number` | `1000` | no | diff --git a/1-org/envs/shared/variables.tf b/1-org/envs/shared/variables.tf index f52a28054..b17197927 100644 --- a/1-org/envs/shared/variables.tf +++ b/1-org/envs/shared/variables.tf @@ -51,12 +51,12 @@ variable "audit_data_users" { } variable "domains_to_allow" { - description = "The list of domains to allow users from in IAM." + description = "The list of domains to allow users from in IAM. Used by Domain Restricted Sharing Organization Policy." type = list(string) } variable "enable_os_login_policy" { - description = "Enable OS Login policy." + description = "Enable OS Login Organization Policy." type = bool default = false } @@ -68,7 +68,7 @@ variable "audit_logs_table_expiration_days" { } variable "scc_notification_name" { - description = "Name of SCC Notification" + description = "Name of the Security Command Center Notification. It must be unique in the organization. Run `gcloud scc notifications describe --organization=org_id` to check if it already exists." type = string } @@ -79,7 +79,7 @@ variable "skip_gcloud_download" { } variable "scc_notification_filter" { - description = "Filter used to SCC Notification, you can see more details how to create filters in https://cloud.google.com/security-command-center/docs/how-to-api-filter-notifications#create-filter" + description = "Filter used to create the Security Command Center Notification, you can see more details on how to create filters in https://cloud.google.com/security-command-center/docs/how-to-api-filter-notifications#create-filter" type = string default = "state=\\\"ACTIVE\\\"" } diff --git a/2-environments/README.md b/2-environments/README.md index 82e32e057..32ee8a153 100644 --- a/2-environments/README.md +++ b/2-environments/README.md @@ -12,13 +12,14 @@ The purpose of this step is to set up development, non-production and production ## Usage ### Setup to run via Cloud Build + 1. Clone repo `gcloud source repos clone gcp-environments --project=YOUR_CLOUD_BUILD_PROJECT_ID`. -1. Change freshly cloned repo and change to non master branch `git checkout -b plan`. +1. Navigate into the repo `cd gcp-environments` and change to non master branch `git checkout -b plan`. 1. Copy contents of foundation to new repo `cp -RT ../terraform-example-foundation/2-environments/ .` (modify accordingly based on your current directory). 1. Copy cloud build configuration files for terraform `cp ../terraform-example-foundation/build/cloudbuild-tf-* . ` (modify accordingly based on your current directory). 1. Copy terraform wrapper script `cp ../terraform-example-foundation/build/tf-wrapper.sh . ` to the root of your new repository (modify accordingly based on your current directory). 1. Ensure wrapper script can be executed `chmod 755 ./tf-wrapper.sh`. -1. Rename `terraform.example.tfvars` to `terraform.tfvars` and update the file with values from your environment and bootstrap (you can re-run `terraform output` in the 0-bootstrap directory to find these values). +1. Rename `terraform.example.tfvars` to `terraform.tfvars` and update the file with values from your environment and bootstrap (you can re-run `terraform output` in the 0-bootstrap directory to find these values). See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `terraform.tfvars` file. 1. Commit changes with `git add .` and `git commit -m 'Your message'`. 1. Push your plan branch to trigger a plan for all environments `git push --set-upstream origin plan` (the branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan). 1. Review the plan output in your cloud build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID @@ -30,6 +31,7 @@ The purpose of this step is to set up development, non-production and production 1. Review the apply output in your cloud build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID ### Setup to run via Jenkins + 1. Clone the repo you created manually in bootstrap: `git clone `. 1. Navigate into the repo `cd YOUR_NEW_REPO_CLONE-2-environments` and change to a non production branch `git checkout -b plan` (the branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan). 1. Copy contents of foundation to new repo `cp -RT ../terraform-example-foundation/2-environments/ .` (modify accordingly based on your current directory). @@ -42,7 +44,7 @@ The purpose of this step is to set up development, non-production and production ``` 1. Copy terraform wrapper script `cp ../terraform-example-foundation/build/tf-wrapper.sh . ` to the root of your new repository (modify accordingly based on your current directory). 1. Ensure wrapper script can be executed `chmod 755 ./tf-wrapper.sh`. -1. Rename `terraform.example.tfvars` to `terraform.tfvars` and update the file with values from your environment and bootstrap (you can re-run `terraform output` in the 0-bootstrap directory to find these values). +1. Rename `terraform.example.tfvars` to `terraform.tfvars` and update the file with values from your environment and bootstrap (you can re-run `terraform output` in the 0-bootstrap directory to find these values). See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `terraform.tfvars` file. 1. Commit changes with `git add .` and `git commit -m 'Your message'`. 1. Push your plan branch `git push --set-upstream origin plan`. The branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan. - Assuming you configured an automatic trigger in your Jenkins Master (see [Jenkins sub-module README](../0-bootstrap/modules/jenkins-agent)), this will trigger a plan. You can also trigger a Jenkins job manually. Given the many options to do this in Jenkins, it is out of the scope of this document see [Jenkins website](http://www.jenkins.io) for more details. @@ -57,10 +59,11 @@ The purpose of this step is to set up development, non-production and production 1. You can now move to the instructions in the step [3-networks](../3-networks/README.md). ### Run terraform locally + 1. Change into 2-environments folder. 1. Run `cp ../build/tf-wrapper.sh .` 1. Run `chmod 755 ./tf-wrapper.sh`. -1. Rename terraform.example.tfvars to terraform.tfvars and update the file with values from your environment and bootstrap. +1. Rename terraform.example.tfvars to terraform.tfvars and update the 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 `terraform.tfvars` file. 1. Update backend.tf with your bucket from bootstrap. You can run ```for i in `find -name 'backend.tf'`; do sed -i 's/UPDATE_ME//' $i; done```. You can run `terraform output gcs_bucket_tfstate` in the 0-bootstap folder to obtain the bucket name. diff --git a/2-environments/envs/development/README.md b/2-environments/envs/development/README.md index 5814db70f..3c199b35b 100644 --- a/2-environments/envs/development/README.md +++ b/2-environments/envs/development/README.md @@ -15,10 +15,10 @@ | Name | Description | |------|-------------| -| base\_shared\_vpc\_project\_id | Project for monitoring infra. | +| base\_shared\_vpc\_project\_id | Project for base shared VPC. | | env\_folder | Environment folder created under parent. | -| env\_secrets\_project\_id | Project for monitoring infra. | +| env\_secrets\_project\_id | Project for environment related secrets. | | monitoring\_project\_id | Project for monitoring infra. | -| restricted\_shared\_vpc\_project\_id | Project for monitoring infra. | +| restricted\_shared\_vpc\_project\_id | Project for restricted shared VPC. | diff --git a/2-environments/envs/development/outputs.tf b/2-environments/envs/development/outputs.tf index 741e8e03e..7b759fbc9 100644 --- a/2-environments/envs/development/outputs.tf +++ b/2-environments/envs/development/outputs.tf @@ -25,16 +25,16 @@ output "monitoring_project_id" { } output "base_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for base shared VPC." value = module.env.base_shared_vpc_project_id } output "restricted_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for restricted shared VPC." value = module.env.restricted_shared_vpc_project_id } output "env_secrets_project_id" { - description = "Project for monitoring infra." + description = "Project for environment related secrets." value = module.env.env_secrets_project_id } diff --git a/2-environments/envs/non-production/README.md b/2-environments/envs/non-production/README.md index 5814db70f..3c199b35b 100644 --- a/2-environments/envs/non-production/README.md +++ b/2-environments/envs/non-production/README.md @@ -15,10 +15,10 @@ | Name | Description | |------|-------------| -| base\_shared\_vpc\_project\_id | Project for monitoring infra. | +| base\_shared\_vpc\_project\_id | Project for base shared VPC. | | env\_folder | Environment folder created under parent. | -| env\_secrets\_project\_id | Project for monitoring infra. | +| env\_secrets\_project\_id | Project for environment related secrets. | | monitoring\_project\_id | Project for monitoring infra. | -| restricted\_shared\_vpc\_project\_id | Project for monitoring infra. | +| restricted\_shared\_vpc\_project\_id | Project for restricted shared VPC. | diff --git a/2-environments/envs/non-production/outputs.tf b/2-environments/envs/non-production/outputs.tf index 741e8e03e..7b759fbc9 100644 --- a/2-environments/envs/non-production/outputs.tf +++ b/2-environments/envs/non-production/outputs.tf @@ -25,16 +25,16 @@ output "monitoring_project_id" { } output "base_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for base shared VPC." value = module.env.base_shared_vpc_project_id } output "restricted_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for restricted shared VPC." value = module.env.restricted_shared_vpc_project_id } output "env_secrets_project_id" { - description = "Project for monitoring infra." + description = "Project for environment related secrets." value = module.env.env_secrets_project_id } diff --git a/2-environments/envs/production/README.md b/2-environments/envs/production/README.md index 747bf085b..8e2aee060 100644 --- a/2-environments/envs/production/README.md +++ b/2-environments/envs/production/README.md @@ -15,11 +15,11 @@ | Name | Description | |------|-------------| -| base\_shared\_vpc\_project\_id | Project for monitoring infra. | +| base\_shared\_vpc\_project\_id | Project for base shared VPC. | | env\_folder | Environment folder created under parent. | -| env\_secrets\_project\_id | Project for monitoring infra. | +| env\_secrets\_project\_id | Project for environment related secrets. | | monitoring\_project\_id | Project for monitoring infra. | -| restricted\_shared\_vpc\_project\_id | Project for monitoring infra. | +| restricted\_shared\_vpc\_project\_id | Project for restricted shared VPC. | diff --git a/2-environments/envs/production/outputs.tf b/2-environments/envs/production/outputs.tf index 741e8e03e..7b759fbc9 100644 --- a/2-environments/envs/production/outputs.tf +++ b/2-environments/envs/production/outputs.tf @@ -25,16 +25,16 @@ output "monitoring_project_id" { } output "base_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for base shared VPC." value = module.env.base_shared_vpc_project_id } output "restricted_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for restricted shared VPC." value = module.env.restricted_shared_vpc_project_id } output "env_secrets_project_id" { - description = "Project for monitoring infra." + description = "Project for environment related secrets." value = module.env.env_secrets_project_id } diff --git a/3-networks/README.md b/3-networks/README.md index e15d09b13..7f67f86ca 100644 --- a/3-networks/README.md +++ b/3-networks/README.md @@ -10,7 +10,7 @@ The purpose of this step is to: 1. 0-bootstrap executed successfully. 1. 1-org executed successfully. 1. 2-environments executed successfully. -1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. +1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. ## Usage @@ -48,7 +48,7 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a 1. Copy cloud build configuration files for terraform `cp ../terraform-example-foundation/build/cloudbuild-tf-* . ` (modify accordingly based on your current directory). 1. Copy terraform wrapper script `cp ../terraform-example-foundation/build/tf-wrapper.sh . ` to the root of your new repository (modify accordingly based on your current directory). 1. Ensure wrapper script can be executed `chmod 755 ./tf-wrapper.sh`. -1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the file with values from your environment and bootstrap. +1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the 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. Rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and update the file with the target_name_server_addresses (the list of target name servers for the DNS forwarding zone in the DNS Hub). 1. Rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars` and update the file with the `access_context_manager_policy_id`. 1. Commit changes with `git add .` and `git commit -m 'Your message'`. @@ -70,6 +70,7 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a 1. Review the apply output in your cloud build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID ### Setup to run via Jenkins + 1. Clone the repo you created manually in bootstrap: `git clone `. 1. Navigate into the repo `cd YOUR_NEW_REPO_CLONE-3-networks` and change to a non production branch `git checkout -b plan` (the branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan). 1. Copy contents of foundation to new repo `cp -RT ../terraform-example-foundation/3-networks/ .` (modify accordingly based on your current directory). @@ -82,7 +83,7 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a ``` 1. Copy terraform wrapper script `cp ../terraform-example-foundation/build/tf-wrapper.sh . ` to the root of your new repository (modify accordingly based on your current directory). 1. Ensure wrapper script can be executed `chmod 755 ./tf-wrapper.sh`. -1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the file with values from your environment and bootstrap. +1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the 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. Rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and update the file with the `target_name_server_addresses`. 1. Rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars` and update the file with the `access_context_manager_policy_id`. 1. Commit changes with `git add .` and `git commit -m 'Your message'`. @@ -111,10 +112,10 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a 1. Change into 3-networks folder. 1. Run `cp ../build/tf-wrapper.sh .` 1. Run `chmod 755 ./tf-wrapper.sh`. -1. Rename common.auto.example.tfvars to common.auto.tfvars and update the file with values from your environment and bootstrap. -1. Rename shared.auto.example.tfvars to shared.auto.tfvars and update the file with the target_name_server_addresses. -1. Rename access_context.auto.example.tfvars to access_context.auto.tfvars and update the file with the access_context_manager_policy_id. -1. Update backend.tf with your bucket from bootstrap. You can run +1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the 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. Rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and update the file with the `target_name_server_addresses`. +1. Rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars` and update the file with the `access_context_manager_policy_id`. +1. Update `backend.tf` with your bucket from bootstrap. You can run ```for i in `find -name 'backend.tf'`; do sed -i 's/UPDATE_ME//' $i; done```. You can run `terraform output gcs_bucket_tfstate` in the 0-bootstrap folder to obtain the bucket name. diff --git a/3-networks/envs/development/README.md b/3-networks/envs/development/README.md index 82bcbe16e..37de30cce 100644 --- a/3-networks/envs/development/README.md +++ b/3-networks/envs/development/README.md @@ -8,14 +8,14 @@ The purpose of this step is to set up base and restricted shared VPCs with defau 1. 1-org executed successfully. 1. 2-environments/envs/development executed successfully. 1. 3-networks/envs/shared executed successfully. -1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. +1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | +| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | | default\_region1 | First subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes | | default\_region2 | Second subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes | | dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for VPC DNS. | `bool` | `true` | no | diff --git a/3-networks/envs/development/variables.tf b/3-networks/envs/development/variables.tf index 4b5fd46ce..473b60b0d 100644 --- a/3-networks/envs/development/variables.tf +++ b/3-networks/envs/development/variables.tf @@ -21,7 +21,7 @@ variable "org_id" { variable "access_context_manager_policy_id" { type = number - description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "terraform_service_account" { diff --git a/3-networks/envs/non-production/README.md b/3-networks/envs/non-production/README.md index 327404069..4e4e6b77d 100644 --- a/3-networks/envs/non-production/README.md +++ b/3-networks/envs/non-production/README.md @@ -8,14 +8,14 @@ The purpose of this step is to set up base and restricted shared VPCs with defau 1. 1-org executed successfully. 1. 2-environments/envs/non-production executed successfully. 1. 3-networks/envs/shared executed successfully. -1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. +1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | +| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | | default\_region1 | First subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes | | default\_region2 | Second subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes | | dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for VPC DNS. | `bool` | `true` | no | diff --git a/3-networks/envs/non-production/variables.tf b/3-networks/envs/non-production/variables.tf index b371b8b68..e36ee34ec 100644 --- a/3-networks/envs/non-production/variables.tf +++ b/3-networks/envs/non-production/variables.tf @@ -21,7 +21,7 @@ variable "org_id" { variable "access_context_manager_policy_id" { type = number - description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "terraform_service_account" { diff --git a/3-networks/envs/production/README.md b/3-networks/envs/production/README.md index de74709f4..1de44d2e4 100644 --- a/3-networks/envs/production/README.md +++ b/3-networks/envs/production/README.md @@ -8,14 +8,14 @@ The purpose of this step is to set up base and restricted shared VPCs with defau 1. 1-org executed successfully. 1. 2-environments/envs/production executed successfully. 1. 3-networks/envs/shared executed successfully. -1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. +1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | +| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | | default\_region1 | First subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes | | default\_region2 | Second subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes | | dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for VPC DNS. | `bool` | `true` | no | diff --git a/3-networks/envs/production/variables.tf b/3-networks/envs/production/variables.tf index 4b5fd46ce..473b60b0d 100644 --- a/3-networks/envs/production/variables.tf +++ b/3-networks/envs/production/variables.tf @@ -21,7 +21,7 @@ variable "org_id" { variable "access_context_manager_policy_id" { type = number - description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "terraform_service_account" { diff --git a/3-networks/envs/shared/README.md b/3-networks/envs/shared/README.md index 032500d62..b8fa5d04c 100644 --- a/3-networks/envs/shared/README.md +++ b/3-networks/envs/shared/README.md @@ -12,7 +12,7 @@ The purpose of this step is to set up the global [DNS Hub](https://cloud.google. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | +| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | | base\_hub\_dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for Base Hub VPC DNS. | `bool` | `true` | no | | base\_hub\_dns\_enable\_logging | Toggle DNS logging for Base Hub VPC DNS. | `bool` | `true` | no | | base\_hub\_firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls in Base Hub VPC. | `bool` | `true` | no | diff --git a/3-networks/envs/shared/variables.tf b/3-networks/envs/shared/variables.tf index d0cd6f2e8..4c05bfebf 100644 --- a/3-networks/envs/shared/variables.tf +++ b/3-networks/envs/shared/variables.tf @@ -38,7 +38,7 @@ variable "enable_hub_and_spoke_transitivity" { variable "access_context_manager_policy_id" { type = number - description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "default_region1" { diff --git a/3-networks/modules/restricted_shared_vpc/README.md b/3-networks/modules/restricted_shared_vpc/README.md index 320943b37..43b51b864 100644 --- a/3-networks/modules/restricted_shared_vpc/README.md +++ b/3-networks/modules/restricted_shared_vpc/README.md @@ -3,7 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | +| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | | allow\_all\_egress\_ranges | List of network ranges to which all egress traffic will be allowed | `any` | `null` | no | | allow\_all\_ingress\_ranges | List of network ranges from which all ingress traffic will be allowed | `any` | `null` | no | | bgp\_asn\_subnet | BGP ASN for Subnets cloud routers. | `number` | n/a | yes | diff --git a/3-networks/modules/restricted_shared_vpc/variables.tf b/3-networks/modules/restricted_shared_vpc/variables.tf index 2344d5bd0..41bf468da 100644 --- a/3-networks/modules/restricted_shared_vpc/variables.tf +++ b/3-networks/modules/restricted_shared_vpc/variables.tf @@ -21,7 +21,7 @@ variable "org_id" { variable "access_context_manager_policy_id" { type = number - description = "The id of the default Access Context Manager policy. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "project_id" { diff --git a/4-projects/README.md b/4-projects/README.md index dcfdb0344..b9ee28827 100644 --- a/4-projects/README.md +++ b/4-projects/README.md @@ -8,14 +8,39 @@ The purpose of this step is to set up folder structure, projects and infrastruct 1. 1-org executed successfully. 1. 2-environments executed successfully. 1. 3-networks executed successfully. -1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. +1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. 1. Obtain the values for the `perimeter_name` for each environment variable by running `gcloud access-context-manager perimeters list --policy ACCESS_CONTEXT_MANAGER_POLICY_ID --format="value(name)"`. **Troubleshooting:** If your user does not have access to run the commands above and you are in the organization admins group, you can append `--impersonate-service-account=org-terraform@.iam.gserviceaccount.com` to run the command as the terraform service account. +**Note:** If you have more then one service perimeter for each environment you can also get the values from the `restricted_service_perimeter_name` output from each of the`3-networks` environments. + +If you are using Cloud Build you can also search for the values in the outputs in the build logs: + +```console +gcloud builds list \ + --project=YOUR_CLOUD_BUILD_PROJECT_ID \ + --filter="status=SUCCESS \ + AND source.repoSource.repoName=gcp-networks \ + AND substitutions.BRANCH_NAME=development" \ + --format="value(id)" +``` + +Use the result of this command as the `BUILD_ID` value in the next command: + +```console +gcloud builds log BUILD_ID \ + --project=YOUR_CLOUD_BUILD_PROJECT_ID | \ + grep "restricted_service_perimeter_name = " +``` + +Change the `BRANCH_NAME` from `development` to `non-production` or `production` for the other two service perimeters. + ## Usage + ### Setup to run via Cloud Build + 1. Clone repo `gcloud source repos clone gcp-projects --project=YOUR_CLOUD_BUILD_PROJECT_ID`. 1. Change freshly cloned repo and change to non master branch `git checkout -b plan` (the branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan). 1. Copy contents of foundation to new repo `cp -RT ../terraform-example-foundation/4-projects/ .` (modify accordingly based on your current directory). @@ -36,8 +61,8 @@ If your user does not have access to run the commands above and you are in the o 1. Run `terraform output cloudbuild_sa` to get the cloudbuild service account from the apply step. 1. If you would like the bucket to be replaced by cloud build at run time, change the bucket name back to `UPDATE_ME` 1. Once you have done the instructions for the `business_unit_1`, you need to repeat same steps for `business_unit_2` folder. -1. Rename `business_unit_1.auto.example.tfvars` to `business_unit_1.auto.tfvars` and update the file with the `app_infra_pipeline_cloudbuild_sa` wich is the output of `cloudbuild_sa` from `business_unit_1` shared steps. -1. Rename `business_unit_2.auto.example.tfvars` to `business_unit_2.auto.tfvars` and update the file with the `app_infra_pipeline_cloudbuild_sa` wich is the output of `cloudbuild_sa` from `business_unit_2` shared steps. +1. Rename `business_unit_1.auto.example.tfvars` to `business_unit_1.auto.tfvars` and update the file with the `app_infra_pipeline_cloudbuild_sa` which is the output of `cloudbuild_sa` from `business_unit_1` shared steps. +1. Rename `business_unit_2.auto.example.tfvars` to `business_unit_2.auto.tfvars` and update the file with the `app_infra_pipeline_cloudbuild_sa` which is the output of `cloudbuild_sa` from `business_unit_2` shared steps. 1. Commit changes with `git add .` and `git commit -m 'Your message'`. 1. Push your plan branch to trigger a plan `git push --set-upstream origin plan` (the branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan). 1. Review the plan output in your cloud build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID @@ -48,8 +73,8 @@ If your user does not have access to run the commands above and you are in the o 1. Merge changes to non-production with `git checkout -b non-production` and `git push origin non-production`. 1. Review the apply output in your cloud build project. https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID - ### Setup to run via Jenkins + 1. Clone the repo you created manually in bootstrap: `git clone `. 1. Navigate into the repo `cd YOUR_NEW_REPO_CLONE-4-projects` and change to a non production branch `git checkout -b plan` (the branch `plan` is not a special one. Any branch which name is different from `development`, `non-production` or `production` will trigger a terraform plan). 1. Copy contents of foundation to new repo `cp -RT ../terraform-example-foundation/4-projects/ .` (modify accordingly based on your current directory). @@ -81,6 +106,7 @@ If your user does not have access to run the commands above and you are in the o 1. You can now move to the instructions in the step [4-projects](../4-projects/README.md). ### Run terraform locally + 1. Change into 4-projects folder. 1. Run `cp ../build/tf-wrapper.sh .` 1. Run `chmod 755 ./tf-wrapper.sh`. @@ -90,7 +116,7 @@ If your user does not have access to run the commands above and you are in the o 1. Rename `production.auto.example.tfvars` to `production.auto.tfvars` and update the file with the `perimeter_name` that starts with `sp_p_shared_restricted`. 1. Update backend.tf with your bucket from bootstrap. You can run ```for i in `find -name 'backend.tf'`; do sed -i 's/UPDATE_ME//' $i; done```. -You can run `terraform output gcs_bucket_tfstate` in the 0-bootstap folder to obtain the bucket name. +You can run `terraform output gcs_bucket_tfstate` in the 0-bootstrap folder to obtain the bucket name. We will now deploy each of our environments(development/production/non-production) using this 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. diff --git a/4-projects/business_unit_1.auto.example.tfvars b/4-projects/business_unit_1.auto.example.tfvars index 6048873c9..2f150efee 100644 --- a/4-projects/business_unit_1.auto.example.tfvars +++ b/4-projects/business_unit_1.auto.example.tfvars @@ -14,4 +14,4 @@ * limitations under the License. */ -app_infra_pipeline_cloudbuild_sa = "project-service-account@prj-bu1-s-sample-infra-.iam.gserviceaccount.com" +app_infra_pipeline_cloudbuild_sa = "@cloudbuild.gserviceaccount.com" diff --git a/4-projects/business_unit_1/development/README.md b/4-projects/business_unit_1/development/README.md index 67360d157..0896a65b6 100644 --- a/4-projects/business_unit_1/development/README.md +++ b/4-projects/business_unit_1/development/README.md @@ -3,7 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | +| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | | alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` | `string` | `null` | no | | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | app\_infra\_pipeline\_cloudbuild\_sa | Cloud Build SA used for deploying infrastructure | `string` | n/a | yes | diff --git a/4-projects/business_unit_1/development/variables.tf b/4-projects/business_unit_1/development/variables.tf index c231f0003..fddcdc0f6 100644 --- a/4-projects/business_unit_1/development/variables.tf +++ b/4-projects/business_unit_1/development/variables.tf @@ -31,7 +31,7 @@ variable "billing_account" { variable "access_context_manager_policy_id" { type = string - description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "parent_folder" { diff --git a/4-projects/business_unit_1/non-production/README.md b/4-projects/business_unit_1/non-production/README.md index 67360d157..0896a65b6 100644 --- a/4-projects/business_unit_1/non-production/README.md +++ b/4-projects/business_unit_1/non-production/README.md @@ -3,7 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | +| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | | alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` | `string` | `null` | no | | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | app\_infra\_pipeline\_cloudbuild\_sa | Cloud Build SA used for deploying infrastructure | `string` | n/a | yes | diff --git a/4-projects/business_unit_1/non-production/variables.tf b/4-projects/business_unit_1/non-production/variables.tf index c231f0003..fddcdc0f6 100644 --- a/4-projects/business_unit_1/non-production/variables.tf +++ b/4-projects/business_unit_1/non-production/variables.tf @@ -31,7 +31,7 @@ variable "billing_account" { variable "access_context_manager_policy_id" { type = string - description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "parent_folder" { diff --git a/4-projects/business_unit_1/production/README.md b/4-projects/business_unit_1/production/README.md index 7286ebb83..dcd99d222 100644 --- a/4-projects/business_unit_1/production/README.md +++ b/4-projects/business_unit_1/production/README.md @@ -3,7 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | +| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | | alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` | `string` | `null` | no | | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | app\_infra\_pipeline\_cloudbuild\_sa | Cloud Build SA used for deploying infrastructure | `string` | n/a | yes | diff --git a/4-projects/business_unit_1/production/variables.tf b/4-projects/business_unit_1/production/variables.tf index a7cdb793c..6e544165d 100644 --- a/4-projects/business_unit_1/production/variables.tf +++ b/4-projects/business_unit_1/production/variables.tf @@ -37,7 +37,7 @@ variable "env_code" { variable "access_context_manager_policy_id" { type = string - description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "parent_folder" { diff --git a/4-projects/business_unit_2.auto.example.tfvars b/4-projects/business_unit_2.auto.example.tfvars index 109b09395..03f2a179b 100644 --- a/4-projects/business_unit_2.auto.example.tfvars +++ b/4-projects/business_unit_2.auto.example.tfvars @@ -14,4 +14,4 @@ * limitations under the License. */ -app_infra_pipeline_cloudbuild_sa = "project-service-account@prj-bu2-s-sample-infra-.iam.gserviceaccount.com" +app_infra_pipeline_cloudbuild_sa = "@cloudbuild.gserviceaccount.com" diff --git a/4-projects/business_unit_2/development/README.md b/4-projects/business_unit_2/development/README.md index 67360d157..0896a65b6 100644 --- a/4-projects/business_unit_2/development/README.md +++ b/4-projects/business_unit_2/development/README.md @@ -3,7 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | +| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | | alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` | `string` | `null` | no | | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | app\_infra\_pipeline\_cloudbuild\_sa | Cloud Build SA used for deploying infrastructure | `string` | n/a | yes | diff --git a/4-projects/business_unit_2/development/variables.tf b/4-projects/business_unit_2/development/variables.tf index c231f0003..fddcdc0f6 100644 --- a/4-projects/business_unit_2/development/variables.tf +++ b/4-projects/business_unit_2/development/variables.tf @@ -31,7 +31,7 @@ variable "billing_account" { variable "access_context_manager_policy_id" { type = string - description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "parent_folder" { diff --git a/4-projects/business_unit_2/non-production/README.md b/4-projects/business_unit_2/non-production/README.md index 67360d157..0896a65b6 100644 --- a/4-projects/business_unit_2/non-production/README.md +++ b/4-projects/business_unit_2/non-production/README.md @@ -3,7 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | +| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | | alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` | `string` | `null` | no | | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | app\_infra\_pipeline\_cloudbuild\_sa | Cloud Build SA used for deploying infrastructure | `string` | n/a | yes | diff --git a/4-projects/business_unit_2/non-production/variables.tf b/4-projects/business_unit_2/non-production/variables.tf index c231f0003..fddcdc0f6 100644 --- a/4-projects/business_unit_2/non-production/variables.tf +++ b/4-projects/business_unit_2/non-production/variables.tf @@ -31,7 +31,7 @@ variable "billing_account" { variable "access_context_manager_policy_id" { type = string - description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "parent_folder" { diff --git a/4-projects/business_unit_2/production/README.md b/4-projects/business_unit_2/production/README.md index 67360d157..0896a65b6 100644 --- a/4-projects/business_unit_2/production/README.md +++ b/4-projects/business_unit_2/production/README.md @@ -3,7 +3,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | +| access\_context\_manager\_policy\_id | The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `string` | n/a | yes | | alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` | `string` | `null` | no | | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
[
0.5,
0.75,
0.9,
0.95
]
| no | | app\_infra\_pipeline\_cloudbuild\_sa | Cloud Build SA used for deploying infrastructure | `string` | n/a | yes | diff --git a/4-projects/business_unit_2/production/variables.tf b/4-projects/business_unit_2/production/variables.tf index c231f0003..fddcdc0f6 100644 --- a/4-projects/business_unit_2/production/variables.tf +++ b/4-projects/business_unit_2/production/variables.tf @@ -31,7 +31,7 @@ variable "billing_account" { variable "access_context_manager_policy_id" { type = string - description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "parent_folder" { diff --git a/README.md b/README.md index 02e6d0b76..c15310baf 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ This stage executes the [CFT Bootstrap module](https://github.com/terraform-goog For CI/CD pipelines, you can use either Cloud Build (by default) or Jenkins. If you want to use Jenkins instead of Cloud Build, please see [README-Jenkins](./0-bootstrap/README-Jenkins.md) on how to use the included Jenkins sub-module. The bootstrap step includes: -- The `cft-seed` project, which contains: +- The `prj-seed` project, which contains: - Terraform state bucket - Custom Service Account used by Terraform to create new resources in GCP -- The `cft-cloudbuild` project (`prj-cicd` if using Jenkins), which contains: +- The `prj-cloudbuild` project (`prj-cicd` if using Jenkins), which contains: - A CI/CD pipeline implemented with either Cloud Build or Jenkins - If using Cloud Build: - Cloud Source Repository @@ -27,8 +27,8 @@ The bootstrap step includes: - VPN connection with on-prem (or where ever your Jenkins Master is located) It is a best practice to separate concerns by having two projects here: one for the CFT resources and one for the CI/CD tool. -The `cft-seed` project stores Terraform state and has the Service Account able to create / modify infrastructure. -On the other hand, the deployment of that infrastructure is coordinated by a CI/CD tool of your choice allocated in a second project (named `cft-cloudbuild` project if using Google Cloud Build and `prj-cicd` project if using Jenkins). +The `prj-seed` project stores Terraform state and has the Service Account able to create / modify infrastructure. +On the other hand, the deployment of that infrastructure is coordinated by a CI/CD tool of your choice allocated in a second project (named `prj-cloudbuild` project if using Google Cloud Build and `prj-cicd` project if using Jenkins). To further separate the concerns at the IAM level as well, the service account of the CI/CD tool is given different permissions than the Terraform account. The CI/CD tool account (`@cloudbuild.gserviceaccount.com` if using Cloud Build and `sa-jenkins-agent-gce@prj-cicd-xxxx.iam.gserviceaccount.com` if using Jenkins) is granted access to generate tokens over the Terraform custom service account. @@ -39,8 +39,8 @@ After executing this step, you will have the following structure: ``` example-organization/ └── fldr-bootstrap - ├── cft-cloudbuild (prj-cicd if using Jenkins) - └── cft-seed + ├── prj-cloudbuild (prj-cicd if using Jenkins) + └── prj-seed ``` When this step uses the Cloud Build submodule, it sets up Cloud Build and Cloud Source Repositories for each of the stages below. @@ -49,23 +49,25 @@ Usage instructions are available in the 0-bootstrap [README](./0-bootstrap/READM ### [1. org](./1-org/) -The purpose of this stage is to set up the common folder used to house projects which contain shared resources such as DNS Hub, Interconnect, SCC Notification, org level secrets and org level logging. +The purpose of this stage is to set up the common folder used to house projects which contain shared resources such as DNS Hub, Interconnect, SCC Notification, org level secrets, Network Hub and org level logging. This will create the following folder & project structure: ``` example-organization └── fldr-common ├── prj-c-logging + ├── prj-c-base-net-hub ├── prj-c-billing-logs ├── prj-c-dns-hub ├── prj-c-interconnect + ├── prj-c-restricted-net-hub ├── prj-c-scc └── prj-c-secrets ``` #### Logs -Among the six projects created under the common folder, two projects (`prj-c-logging`, `prj-c-billing-logs`) are used for logging. +Among the eight projects created under the common folder, two projects (`prj-c-logging`, `prj-c-billing-logs`) are used for logging. The first one for organization wide audit logs and the latter for billing logs. In both cases the logs are collected into BigQuery datasets which can then be used general querying, dashboarding & reporting. Logs are also exported to Pub/Sub and GCS bucket. @@ -77,21 +79,21 @@ In both cases the logs are collected into BigQuery datasets which can then be us #### DNS Hub -Under the common folder, one project is created. This project will host the DNS Hub for the organization. +Another project created under the common folder. This project will host the DNS Hub for the organization. #### Interconnect -Under the common folder, one project is created. This project will host the Dedicated Interconnect [Interconnect connection](https://cloud.google.com/network-connectivity/docs/interconnect/concepts/terminology#elements) for the organization. In case of the Partner Interconnect this project is unused and the [VLAN attachments](https://cloud.google.com/network-connectivity/docs/interconnect/concepts/terminology#for-partner-interconnect) will be placed directly into the corresponding Hub projcts. +Another project created under the common folder. This project will host the Dedicated Interconnect [Interconnect connection](https://cloud.google.com/network-connectivity/docs/interconnect/concepts/terminology#elements) for the organization. In case of the Partner Interconnect this project is unused and the [VLAN attachments](https://cloud.google.com/network-connectivity/docs/interconnect/concepts/terminology#for-partner-interconnect) will be placed directly into the corresponding Hub projcts. #### SCC Notification -Under the common folder, one project is created. This project will host the SCC Notification resources at the organization level. +Another project created under the common folder. This project will host the SCC Notification resources at the organization level. This project will contain a Pub/Sub topic and subscription, a [SCC Notification](https://cloud.google.com/security-command-center/docs/how-to-notifications) configured to send all new Findings to the topic created. You can adjust the filter when deploying this step. #### Secrets -Under the common folder, one project is created. This project is allocated for [GCP Secret Manager](https://cloud.google.com/secret-manager) for secrets shared by the organization. +Another project created under the common folder. This project is allocated for [GCP Secret Manager](https://cloud.google.com/secret-manager) for secrets shared by the organization. Usage instructions are available for the org step in the [README](./1-org/README.md). @@ -132,7 +134,7 @@ This stage only creates the projects and enables the correct APIs, the following #### Secrets -Under the environment folder, one project is created. This is allocated for [GCP Secret Manager](https://cloud.google.com/secret-manager) for secrets shared by the environment. +Under the environment folder, a project is created per environment (`development`, `non-production` & `production`), which is intended to be used by [GCP Secret Manager](https://cloud.google.com/secret-manager) for secrets shared by the environment. Usage instructions are available for the environments step in the [README](./2-environments/README.md). @@ -141,9 +143,10 @@ Usage instructions are available for the environments step in the [README](./2-e This step focuses on creating a Shared VPC per environment (`development`, `non-production` & `production`) in a standard configuration with a reasonable security baseline. Currently this includes: - Optional - Example subnets for `development`, `non-production` & `production` inclusive of secondary ranges for those that want to use GKE. -- Optional - Default firewall rules created to allow remote access to VMs through IAP, without needing public IPs. - - `allow-iap-ssh` and `allow-iap-rdp` network tags respectively. -- Optional - Default firewall rule created to allow for load balancing using `allow-lb` tag. +- Optional - Default firewall rules created to allow remote access to [VMs through IAP](https://cloud.google.com/iap/docs/using-tcp-forwarding), without needing public IPs. + - `allow-iap-ssh` and `allow-iap-rdp` network tags respectively. +- Optional - Default firewall rule created to allow for [load balancing health checks](https://cloud.google.com/load-balancing/docs/health-checks#firewall_rules) using `allow-lb` tag. +- Optional - Default firewall rule created to allow [Windows KMS activation](https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server) using `allow-win-activation` tag. - [Private service networking](https://cloud.google.com/vpc/docs/configure-private-services-access) configured to enable workload dependant resources like Cloud SQL. - Base Shared VPC with [private.googleapis.com](https://cloud.google.com/vpc/docs/configure-private-google-access#private-domains) configured for base access to googleapis.com and gcr.io. Route added for VIP so no internet access is required to access APIs. - Restricted Shared VPC with [restricted.googleapis.com](https://cloud.google.com/vpc-service-controls/docs/supported-products) configured for restricted access to googleapis.com and gcr.io. Route added for VIP so no internet access is required to access APIs. @@ -205,9 +208,11 @@ Once all steps above have been executed your GCP organization should represent t example-organization └── fldr-common ├── prj-c-logging + ├── prj-c-base-net-hub ├── prj-c-billing-logs ├── prj-c-dns-hub ├── prj-c-interconnect + ├── prj-c-restricted-net-hub ├── prj-c-scc ├── prj-c-secrets ├── prj-bu1-s-sample-infra @@ -252,8 +257,8 @@ example-organization ├── prj-p-shared-base └── prj-p-shared-restricted └── fldr-bootstrap - ├── cft-cloudbuild (prj-cicd if using Jenkins) - └── cft-seed + ├── prj-cloudbuild (prj-cicd if using Jenkins) + └── prj-seed ``` ### Branching strategy diff --git a/test/fixtures/bootstrap/outputs.tf b/test/fixtures/bootstrap/outputs.tf index cbf7969fa..42e3e5b7b 100644 --- a/test/fixtures/bootstrap/outputs.tf +++ b/test/fixtures/bootstrap/outputs.tf @@ -24,9 +24,9 @@ output "seed_project_id" { value = module.bootstrap.seed_project_id } -output "terraform_sa_email" { +output "terraform_service_account" { description = "Email for privileged service account for Terraform." - value = module.bootstrap.terraform_sa_email + value = module.bootstrap.terraform_service_account } output "gcs_bucket_tfstate" { diff --git a/test/fixtures/envs/main.tf b/test/fixtures/envs/main.tf index 4931dd08c..c71beccb2 100644 --- a/test/fixtures/envs/main.tf +++ b/test/fixtures/envs/main.tf @@ -20,7 +20,7 @@ module "development" { billing_account = var.billing_account monitoring_workspace_users = var.group_email parent_folder = var.parent_folder - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account project_prefix = var.project_prefix } @@ -30,7 +30,7 @@ module "non-production" { billing_account = var.billing_account monitoring_workspace_users = var.group_email parent_folder = var.parent_folder - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account project_prefix = var.project_prefix } @@ -40,6 +40,6 @@ module "production" { billing_account = var.billing_account monitoring_workspace_users = var.group_email parent_folder = var.parent_folder - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account project_prefix = var.project_prefix } diff --git a/test/fixtures/envs/variables.tf b/test/fixtures/envs/variables.tf index 97de2f992..f6c246053 100644 --- a/test/fixtures/envs/variables.tf +++ b/test/fixtures/envs/variables.tf @@ -30,7 +30,7 @@ variable "group_email" { description = "The group that will be assigned permissions for testing." } -variable "terraform_sa_email" { +variable "terraform_service_account" { description = "The SA that will be used for creating projects." } diff --git a/test/fixtures/networks/main.tf b/test/fixtures/networks/main.tf index e43da79d7..c1899a7d6 100644 --- a/test/fixtures/networks/main.tf +++ b/test/fixtures/networks/main.tf @@ -21,7 +21,7 @@ module "development" { default_region2 = "us-central1" default_region1 = "us-west1" domain = var.domain - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account parent_folder = var.parent_folder enable_hub_and_spoke = var.enable_hub_and_spoke } @@ -33,7 +33,7 @@ module "non-production" { default_region2 = "us-central1" default_region1 = "us-west1" domain = var.domain - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account parent_folder = var.parent_folder enable_hub_and_spoke = var.enable_hub_and_spoke depends_on = [module.development] @@ -46,7 +46,7 @@ module "production" { default_region2 = "us-central1" default_region1 = "us-west1" domain = var.domain - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account parent_folder = var.parent_folder enable_hub_and_spoke = var.enable_hub_and_spoke depends_on = [module.non-production] diff --git a/test/fixtures/networks/outputs.tf b/test/fixtures/networks/outputs.tf index ebee6262f..1958c7859 100644 --- a/test/fixtures/networks/outputs.tf +++ b/test/fixtures/networks/outputs.tf @@ -15,7 +15,7 @@ */ output "access_context_manager_policy_id" { - description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." value = var.policy_id } diff --git a/test/fixtures/networks/variables.tf b/test/fixtures/networks/variables.tf index c035a159c..e585623b6 100644 --- a/test/fixtures/networks/variables.tf +++ b/test/fixtures/networks/variables.tf @@ -18,18 +18,13 @@ variable "org_id" { description = "The numeric organization id" } -variable "terraform_sa_email" { - description = "The SA that will be used for creating projects." -} - -# used by provider configs copied by /test/network_test_prepare.sh variable "terraform_service_account" { description = "The SA that will be used for creating projects." } variable "policy_id" { type = number - description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "domain" { diff --git a/test/fixtures/org/main.tf b/test/fixtures/org/main.tf index c27ad11a2..f2ade8423 100644 --- a/test/fixtures/org/main.tf +++ b/test/fixtures/org/main.tf @@ -24,7 +24,7 @@ module "test" { parent_folder = var.parent_folder org_id = var.org_id billing_account = var.billing_account - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account default_region = "us-east4" billing_data_users = var.group_email audit_data_users = var.group_email diff --git a/test/fixtures/org/variables.tf b/test/fixtures/org/variables.tf index c6a3fbf79..1afb15e0c 100644 --- a/test/fixtures/org/variables.tf +++ b/test/fixtures/org/variables.tf @@ -30,7 +30,7 @@ variable "group_email" { description = "The group that will be assigned permissions for testing." } -variable "terraform_sa_email" { +variable "terraform_service_account" { description = "The SA that will be used for creating projects." } diff --git a/test/fixtures/projects/main.tf b/test/fixtures/projects/main.tf index 5daafb4cf..263deda2b 100644 --- a/test/fixtures/projects/main.tf +++ b/test/fixtures/projects/main.tf @@ -16,7 +16,7 @@ module "bu1_shared" { source = "../../../4-projects/business_unit_1/shared" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account parent_folder = var.parent_folder @@ -25,7 +25,7 @@ module "bu1_shared" { module "projects_bu1_dev" { source = "../../../4-projects/business_unit_1/development" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account access_context_manager_policy_id = var.policy_id @@ -38,7 +38,7 @@ module "projects_bu1_dev" { module "projects_bu1_nonprod" { source = "../../../4-projects/business_unit_1/non-production" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account access_context_manager_policy_id = var.policy_id @@ -52,7 +52,7 @@ module "projects_bu1_nonprod" { module "projects_bu1_prod" { source = "../../../4-projects/business_unit_1/production" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account access_context_manager_policy_id = var.policy_id @@ -65,7 +65,7 @@ module "projects_bu1_prod" { module "bu2_shared" { source = "../../../4-projects/business_unit_2/shared" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account parent_folder = var.parent_folder @@ -74,7 +74,7 @@ module "bu2_shared" { module "projects_bu2_dev" { source = "../../../4-projects/business_unit_2/development" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account access_context_manager_policy_id = var.policy_id @@ -88,7 +88,7 @@ module "projects_bu2_dev" { module "projects_bu2_nonprod" { source = "../../../4-projects/business_unit_2/non-production" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account access_context_manager_policy_id = var.policy_id @@ -103,7 +103,7 @@ module "projects_bu2_nonprod" { module "projects_bu2_prod" { source = "../../../4-projects/business_unit_2/production" - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account org_id = var.org_id billing_account = var.billing_account access_context_manager_policy_id = var.policy_id diff --git a/test/fixtures/projects/variables.tf b/test/fixtures/projects/variables.tf index a6a9605b8..766549a36 100644 --- a/test/fixtures/projects/variables.tf +++ b/test/fixtures/projects/variables.tf @@ -14,7 +14,7 @@ * limitations under the License. */ -variable "terraform_sa_email" { +variable "terraform_service_account" { description = "Service account email of the account to impersonate to run Terraform" type = string } @@ -31,7 +31,7 @@ variable "billing_account" { variable "policy_id" { type = string - description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "parent_folder" { diff --git a/test/fixtures/shared/main.tf b/test/fixtures/shared/main.tf index 72b20d81d..fae051ad7 100644 --- a/test/fixtures/shared/main.tf +++ b/test/fixtures/shared/main.tf @@ -21,7 +21,7 @@ module "shared" { domain = var.domain access_context_manager_policy_id = var.policy_id target_name_server_addresses = ["192.168.0.1", "192.168.0.2"] - terraform_service_account = var.terraform_sa_email + terraform_service_account = var.terraform_service_account parent_folder = var.parent_folder enable_hub_and_spoke = var.enable_hub_and_spoke org_id = var.org_id diff --git a/test/fixtures/shared/variables.tf b/test/fixtures/shared/variables.tf index 1f1b0d1b6..71bf489a3 100644 --- a/test/fixtures/shared/variables.tf +++ b/test/fixtures/shared/variables.tf @@ -14,7 +14,7 @@ * limitations under the License. */ -variable "terraform_sa_email" { +variable "terraform_service_account" { description = "The SA that will be used for creating projects." } @@ -36,7 +36,7 @@ variable "parent_folder" { variable "policy_id" { type = number - description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`." } variable "enable_hub_and_spoke" { diff --git a/test/integration/bootstrap/controls/gcp_bootstrap.rb b/test/integration/bootstrap/controls/gcp_bootstrap.rb index 034b07bd1..945184d5f 100644 --- a/test/integration/bootstrap/controls/gcp_bootstrap.rb +++ b/test/integration/bootstrap/controls/gcp_bootstrap.rb @@ -15,7 +15,7 @@ org_id = attribute('org_id') seed_project_id = attribute('seed_project_id') gcs_bucket_tfstate = attribute('gcs_bucket_tfstate') -terraform_sa_email = attribute('terraform_sa_email') +terraform_service_account = attribute('terraform_service_account') activate_apis = [ 'serviceusage.googleapis.com', @@ -62,14 +62,14 @@ it { should exist } end - describe google_service_account(project: seed_project_id, name: terraform_sa_email) do + describe google_service_account(project: seed_project_id, name: terraform_service_account) do it { should exist } end sa_org_iam_permissions.each do |role| describe google_organization_iam_binding(name: org_name, role: role) do it { should exist } - its('members') { should include "serviceAccount:#{terraform_sa_email}" } + its('members') { should include "serviceAccount:#{terraform_service_account}" } end end diff --git a/test/integration/bootstrap/inspec.yml b/test/integration/bootstrap/inspec.yml index 654a53acc..756ea1b92 100644 --- a/test/integration/bootstrap/inspec.yml +++ b/test/integration/bootstrap/inspec.yml @@ -10,7 +10,7 @@ attributes: - name: seed_project_id required: true type: string - - name: terraform_sa_email + - name: terraform_service_account required: true type: string - name: gcs_bucket_tfstate diff --git a/test/network_test_prepare.sh b/test/network_test_prepare.sh index 98a42620c..d17201633 100755 --- a/test/network_test_prepare.sh +++ b/test/network_test_prepare.sh @@ -40,10 +40,6 @@ function prepare(){ mv 3-networks/envs/non-production/providers.tf 3-networks/envs/non-production/providers.tf.disabled mv 3-networks/envs/production/providers.tf 3-networks/envs/production/providers.tf.disabled - # email fix, we need to add `terraform_service_account` as a var within test/fixtures/networks/variables.tf as network provider.tf uses this. - # Using the same value exported by setup - # shellcheck disable=SC2154 - export TF_VAR_terraform_service_account=$TF_VAR_terraform_sa_email } function restore(){ diff --git a/test/setup/outputs.tf b/test/setup/outputs.tf index 0423f71ef..d0219a5bb 100644 --- a/test/setup/outputs.tf +++ b/test/setup/outputs.tf @@ -29,10 +29,6 @@ output "sa_key" { sensitive = true } -output "terraform_sa_email" { - value = google_service_account.int_test.email -} - output "terraform_service_account" { value = google_service_account.int_test.email }