Skip to content

Commit 015fe3d

Browse files
authored
feat!: Configure bring your own service account in bootstrap (#777)
* configure byosa * update list of allowed APIs * fix integration tests * fix permissions and log bucket * fix linting * add log bucket for infra pipeline * set the version of the terraform image * google terraform module exclusion * remove service account impersonation * nyosa in step 4-projects pipeline infra * bump tf version to 0.15.5 * build terraform image * set terraform service account as default member in the perimeter * byosa in step 4-projects * bump terrraform version to 1.0.0 * remove members variable * add missing cloud build sa id * use impersonate service account to run gcloud build submit * add terraform tools to step 4 infra pipeline * set base terraform version in trigger to v1 * restore step 5 providers * make app infra pipeline compatible with with cloudbuild.yaml files * add time sleep before creating terraform image * setting a project is required for gcloud beta terraform vet * increase wait time in integration build * remove terraform_service_account from terraform.tfvars in step 2 * export service account for impersonation * PR fixes * fix lint * create local value for docker_tag_version_terraform * bump bootstrap version to 6.2
1 parent 0d3b515 commit 015fe3d

File tree

109 files changed

+464
-784
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+464
-784
lines changed

0-bootstrap/Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
FROM gcr.io/cloud-builders/gcloud-slim
16+
17+
# Use ARG so that values can be overriden by user/cloudbuild
18+
ARG TERRAFORM_VERSION=1.0.0
19+
20+
ENV ENV_TERRAFORM_VERSION=$TERRAFORM_VERSION
21+
22+
RUN apt-get update && \
23+
/builder/google-cloud-sdk/bin/gcloud -q components install alpha beta terraform-tools && \
24+
apt-get -y install curl jq unzip git ca-certificates gnupg && \
25+
curl https://releases.hashicorp.com/terraform/${ENV_TERRAFORM_VERSION}/terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip --output terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip && \
26+
curl https://releases.hashicorp.com/terraform/${ENV_TERRAFORM_VERSION}/terraform_${ENV_TERRAFORM_VERSION}_SHA256SUMS.sig --output terraform_SHA256SUMS.sig && \
27+
curl https://releases.hashicorp.com/terraform/${ENV_TERRAFORM_VERSION}/terraform_${ENV_TERRAFORM_VERSION}_SHA256SUMS --output terraform_SHA256SUMS && \
28+
curl https://keybase.io/hashicorp/pgp_keys.asc --output pgp_keys.asc && \
29+
gpg --import pgp_keys.asc && \
30+
gpg --verify terraform_SHA256SUMS.sig terraform_SHA256SUMS && \
31+
grep terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip terraform_SHA256SUMS | shasum --algorithm 256 --check && \
32+
unzip terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip -d /builder/terraform && \
33+
rm -f terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip terraform_SHA256SUMS && \
34+
apt-get --purge -y autoremove && \
35+
apt-get clean && \
36+
rm -rf /var/lib/apt/lists/*
37+
38+
ENV PATH=/builder/terraform/:$PATH
39+
ENTRYPOINT ["terraform"]

0-bootstrap/README.md

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,9 @@ To run the commands described in this document, you need to have the following
6565
installed:
6666

6767
- The [Google Cloud SDK](https://cloud.google.com/sdk/install) version 391.0.0 or later
68-
- [Terraform](https://www.terraform.io/downloads.html) version 0.13.7.
69-
- An existing project which the user has access to be used by terraform-validator.
68+
- [Terraform](https://www.terraform.io/downloads.html) version 1.0.0 or later
7069

71-
**Note:** Make sure that you use the same version of Terraform throughout this series. Otherwise, you might experience Terraform state snapshot lock errors.
70+
**Note:** Make sure that you use version 1.0.0 or later of Terraform throughout this series. Otherwise, you might experience Terraform state snapshot lock errors.
7271

7372
Also make sure that you've done the following:
7473

@@ -131,12 +130,16 @@ your current Jenkins manager (controller) environment.
131130
```
132131
1. Run `terraform init`.
133132
1. Run `terraform plan` and review the output.
134-
1. To run terraform-validator steps please follow the [instructions](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install) to install the terraform-tools component.
133+
1. To run `gcloud beta terraform vet` steps please follow the [instructions](https://cloud.google.com/docs/terraform/policy-validation/validate-policies#install) to install the terraform-tools component.
135134
1. Run `terraform plan -input=false -out bootstrap.tfplan`
136135
1. Run `terraform show -json bootstrap.tfplan > bootstrap.json`
137136
1. Run `gcloud beta terraform vet bootstrap.json --policy-library="../policy-library" --project <A-VALID-PROJECT-ID>` and check for violations (`<A-VALID-PROJECT-ID>` must be an existing project you have access to, this is necessary because Terraform-validator needs to link resources to a valid Google Cloud Platform project).
138137
1. Run `terraform apply`.
139-
1. Run `terraform output terraform_service_account` to get the email address of the admin. You need this address in a later procedure.
138+
1. Run `terraform output organization_step_terraform_service_account_email` to get the email address of the admin of step `1-org`. You need this address in a later procedure.
139+
1. Run `terraform output environment_step_terraform_service_account_email` to get the email address of the admin of step `2-environments`. You need this address in a later procedure.
140+
1. Run `terraform output networks_step_terraform_service_account_email` to get the email address of the admin of steps `3-networks-dual-svpc` and `3-networks-hub-and-spoke`. You need this address in a later procedure.
141+
1. Run `terraform output projects_step_terraform_service_account_email` to get the email address of the admin of step `4-projects`. You need this address in a later procedure.
142+
1. Run `terraform output cloudbuild_project_id` to get the ID of your Cloud Build project.
140143
1. Run `terraform output gcs_bucket_tfstate` to get your Google Cloud bucket name from Terraform's state.
141144
1. Copy the backend:
142145
```
@@ -148,21 +151,7 @@ your current Jenkins manager (controller) environment.
148151
1. (Optional) Run `terraform apply` to verify that state is configured
149152
correctly. You should see no changes from the previous state.
150153
151-
**Note 1:** The output of terraform-validator will contain lines like
152-
153-
```
154-
ERROR: logging before flag.Parse: I0413 13:49:49.852283 6380 convert.go:189] unsupported resource: google_billing_account_iam_member
155-
```
156-
157-
or
158-
159-
```
160-
ERROR: logging before flag.Parse: I0413 13:49:49.852290 6380 convert.go:183] unknown resource: random_id
161-
```
162-
163-
These are warnings for resources that are not yet supported or not known by terraform-validator, these are not actual errors.
164-
165-
**Note 2:** After the deploy, even if you did not receive the project quota error described in the [Troubleshooting guide](../docs/TROUBLESHOOTING.md#project-quota-exceeded), we recommend that you request 50 additional projects for the service account, `terraform_service_account`, created in this step.
154+
**Note:** After the deploy, even if you did not receive the project quota error described in the [Troubleshooting guide](../docs/TROUBLESHOOTING.md#project-quota-exceeded), we recommend that you request 50 additional projects for the four service accounts created in this step.
166155
167156
## Running Terraform locally
168157
@@ -186,8 +175,8 @@ the following steps:
186175
| Name | Description | Type | Default | Required |
187176
|------|-------------|------|---------|:--------:|
188177
| billing\_account | The ID of the billing account to associate projects with. | `string` | n/a | yes |
178+
| bucket\_force\_destroy | When deleting a bucket, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. | `bool` | `false` | no |
189179
| bucket\_prefix | Name prefix to use for state bucket created. | `string` | `"bkt"` | no |
190-
| cloud\_source\_repos | List of Cloud Source Repositories created during bootstrap project build stage for use with Cloud Build. | `list(string)` | <pre>[<br> "gcp-org",<br> "gcp-environments",<br> "gcp-networks",<br> "gcp-projects"<br>]</pre> | no |
191180
| default\_region | Default region to create resources where applicable. | `string` | `"us-central1"` | no |
192181
| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
193182
| group\_billing\_admins | Google Group for GCP Billing Administrators | `string` | n/a | yes |
@@ -216,7 +205,5 @@ the following steps:
216205
| required\_groups | List of Google Groups created that are required by the Example Foundation steps. |
217206
| seed\_project\_id | Project where service accounts and core APIs will be enabled. |
218207
| terraform\_sa\_name | Fully qualified name for privileged service account for Terraform. |
219-
| terraform\_service\_account | Email for privileged service account for Terraform. |
220-
| terraform\_validator\_policies\_repo | Cloud Source Repository created for terraform-validator policies. |
221208
222209
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

0-bootstrap/cb.tf

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
2+
/**
3+
* Copyright 2022 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
locals {
19+
// terraform version image configuration
20+
terraform_version = "1.0.0"
21+
// The version of the terraform docker image to be used in the workspace builds
22+
docker_tag_version_terraform = "v1"
23+
24+
cb_source = {
25+
"org" = "gcp-org",
26+
"env" = "gcp-environments",
27+
"net" = "gcp-networks",
28+
"proj" = "gcp-projects",
29+
}
30+
cloud_source_repos = values(local.cb_source)
31+
cloudbuilder_repo = "tf-cloudbuilder"
32+
base_cloud_source_repos = [
33+
"gcp-policies",
34+
"gcp-bootstrap",
35+
local.cloudbuilder_repo,
36+
]
37+
gar_repository = split("/", module.tf_cloud_builder.artifact_repo)[length(split("/", module.tf_cloud_builder.artifact_repo)) - 1]
38+
}
39+
40+
resource "random_string" "suffix" {
41+
length = 8
42+
special = false
43+
upper = false
44+
}
45+
46+
module "tf_source" {
47+
source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_source"
48+
version = "~> 6.2"
49+
50+
org_id = var.org_id
51+
folder_id = google_folder.bootstrap.id
52+
project_id = "${var.project_prefix}-b-cicd-${random_string.suffix.result}"
53+
billing_account = var.billing_account
54+
group_org_admins = local.group_org_admins
55+
buckets_force_destroy = var.bucket_force_destroy
56+
57+
activate_apis = [
58+
"serviceusage.googleapis.com",
59+
"servicenetworking.googleapis.com",
60+
"compute.googleapis.com",
61+
"logging.googleapis.com",
62+
"iam.googleapis.com",
63+
"admin.googleapis.com",
64+
"sourcerepo.googleapis.com",
65+
"workflows.googleapis.com",
66+
"artifactregistry.googleapis.com",
67+
"cloudbuild.googleapis.com",
68+
"cloudscheduler.googleapis.com",
69+
"bigquery.googleapis.com",
70+
"cloudresourcemanager.googleapis.com",
71+
"cloudbilling.googleapis.com",
72+
"appengine.googleapis.com",
73+
"storage-api.googleapis.com",
74+
"billingbudgets.googleapis.com",
75+
]
76+
77+
cloud_source_repos = distinct(concat(local.base_cloud_source_repos, local.cloud_source_repos))
78+
79+
project_labels = {
80+
environment = "bootstrap"
81+
application_name = "cloudbuild-bootstrap"
82+
billing_code = "1234"
83+
primary_contact = "example1"
84+
secondary_contact = "example2"
85+
business_code = "abcd"
86+
env_code = "b"
87+
}
88+
89+
# Remove after github.com/terraform-google-modules/terraform-google-bootstrap/issues/160
90+
depends_on = [module.seed_bootstrap]
91+
}
92+
93+
module "tf_cloud_builder" {
94+
source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_builder"
95+
version = "~> 6.2"
96+
97+
project_id = module.tf_source.cloudbuild_project_id
98+
dockerfile_repo_uri = module.tf_source.csr_repos[local.cloudbuilder_repo].url
99+
gar_repo_location = var.default_region
100+
workflow_region = var.default_region
101+
terraform_version = local.terraform_version
102+
cb_logs_bucket_force_destroy = var.bucket_force_destroy
103+
}
104+
105+
module "bootstrap_csr_repo" {
106+
source = "terraform-google-modules/gcloud/google"
107+
version = "~> 3.1.0"
108+
upgrade = false
109+
110+
create_cmd_entrypoint = "${path.module}/scripts/push-to-repo.sh"
111+
create_cmd_body = "${module.tf_source.cloudbuild_project_id} ${split("/", module.tf_source.csr_repos[local.cloudbuilder_repo].id)[3]} ${path.module}/Dockerfile"
112+
}
113+
114+
resource "time_sleep" "cloud_builder" {
115+
create_duration = "30s"
116+
117+
depends_on = [
118+
module.tf_cloud_builder,
119+
module.bootstrap_csr_repo,
120+
]
121+
}
122+
123+
module "build_terraform_image" {
124+
source = "terraform-google-modules/gcloud/google"
125+
version = "~> 3.1.0"
126+
upgrade = false
127+
128+
create_cmd_triggers = {
129+
"terraform_version" = local.terraform_version
130+
}
131+
132+
create_cmd_body = "beta builds triggers run ${split("/", module.tf_cloud_builder.cloudbuild_trigger_id)[3]} --branch main --project ${module.tf_source.cloudbuild_project_id}"
133+
134+
module_depends_on = [
135+
time_sleep.cloud_builder,
136+
]
137+
}
138+
139+
module "tf_workspace" {
140+
source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_workspace"
141+
version = "~> 6.2"
142+
for_each = local.granular_sa
143+
144+
project_id = module.tf_source.cloudbuild_project_id
145+
location = var.default_region
146+
state_bucket_self_link = "${local.bucket_self_link_prefix}${module.seed_bootstrap.gcs_bucket_tfstate}"
147+
cloudbuild_plan_filename = "cloudbuild-tf-plan.yaml"
148+
cloudbuild_apply_filename = "cloudbuild-tf-apply.yaml"
149+
tf_repo_uri = module.tf_source.csr_repos[local.cb_source[each.key]].url
150+
cloudbuild_sa = google_service_account.terraform-env-sa[each.key].id
151+
create_cloudbuild_sa = false
152+
diff_sa_project = true
153+
create_state_bucket = false
154+
buckets_force_destroy = var.bucket_force_destroy
155+
156+
substitutions = {
157+
"_ORG_ID" = var.org_id
158+
"_BILLING_ID" = var.billing_account
159+
"_DEFAULT_REGION" = var.default_region
160+
"_GAR_REPOSITORY" = local.gar_repository
161+
"_DOCKER_TAG_VERSION_TERRAFORM" = local.docker_tag_version_terraform
162+
}
163+
164+
tf_apply_branches = ["development", "non\\-production", "production"]
165+
166+
depends_on = [
167+
module.tf_source,
168+
module.tf_cloud_builder,
169+
]
170+
171+
}

0 commit comments

Comments
 (0)