deploy_generated/cicd/main.tf (176 lines of code) (raw):

# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This folder contains Terraform resources to setup CI/CD, which includes: # - Necessary APIs to enable in the devops project for CI/CD purposes, # - Necessary IAM permissions to set to enable Cloud Build Service Account perform CI/CD jobs. # - Cloud Build Triggers to monitor GitHub repos to start CI/CD jobs. # # The Cloud Build configs can be found under the configs/ sub-folder. # ***NOTE***: First follow # https://cloud.google.com/cloud-build/docs/automating-builds/create-github-app-triggers#installing_the_cloud_build_app # to install the Cloud Build app and connect your GitHub repository to your Cloud project. terraform { required_version = "~> 0.12.0" required_providers { google = "~> 3.0" google-beta = "~> 3.0" } backend "gcs" { bucket = "sof-test-terraform-state" prefix = "cicd" } } data "google_project" "devops" { project_id = var.project_id } locals { services = [ "admin.googleapis.com", "bigquery.googleapis.com", "cloudbilling.googleapis.com", "cloudbuild.googleapis.com", "cloudresourcemanager.googleapis.com", "compute.googleapis.com", "iam.googleapis.com", "servicenetworking.googleapis.com", "serviceusage.googleapis.com", "sqladmin.googleapis.com", ] cloudbuild_sa_viewer_roles = [ "roles/browser", "roles/iam.securityReviewer", "roles/secretmanager.secretViewer", "roles/secretmanager.secretAccessor", ] cloudbuild_sa_editor_roles = [ "roles/compute.xpnAdmin", "roles/logging.configWriter", "roles/resourcemanager.projectCreator", "roles/resourcemanager.folderAdmin", ] cloudbuild_devops_roles = [ # Allow CICD to view all resources within the devops project so it can run terraform plans against them. # It won't be able to actually apply any changes unless granted the permission in this list. "roles/viewer", # Enable Cloud Build SA to list and enable APIs in the devops project. "roles/serviceusage.serviceUsageAdmin", ] } locals { # Covert "" and "/" to "." in case users use them to indicate root of the git repo. terraform_root = trim((var.terraform_root == "" || var.terraform_root == "/") ? "." : var.terraform_root, "/") # ./ to indicate root is not recognized by Cloud Build Trigger. terraform_root_prefix = local.terraform_root == "." ? "" : "${local.terraform_root}/" cloudbuild_sa = "serviceAccount:${data.google_project.devops.number}@cloudbuild.gserviceaccount.com" } # Cloud Build - API resource "google_project_service" "services" { for_each = toset(local.services) project = var.project_id service = each.value disable_on_destroy = false } # IAM permissions to allow approvers and contributors to view the cloud build jobs. resource "google_project_iam_member" "cloudbuild_builds_viewers" { for_each = toset(var.build_viewers) project = var.project_id role = "roles/cloudbuild.builds.viewer" member = each.value depends_on = [ google_project_service.services, ] } # IAM permissions to allow approvers and contributors to view the cloud build logs. # https://cloud.google.com/cloud-build/docs/securing-builds/store-view-build-logs resource "google_project_iam_member" "cloudbuild_logs_viewers" { for_each = toset(var.build_viewers) project = var.project_id role = "roles/viewer" member = each.value depends_on = [ google_project_service.services, ] } # IAM permissions to allow Cloud Build Service Account use the billing account. resource "google_billing_account_iam_member" "binding" { billing_account_id = var.billing_account role = "roles/billing.user" member = local.cloudbuild_sa depends_on = [ google_project_service.services, ] } # Cloud Build - Cloud Build Service Account IAM permissions # IAM permissions to allow Cloud Build SA to access state. resource "google_storage_bucket_iam_member" "cloudbuild_state_iam" { bucket = var.state_bucket role = "roles/storage.admin" member = local.cloudbuild_sa depends_on = [ google_project_service.services, ] } # Grant Cloud Build Service Account access to the folder. resource "google_folder_iam_member" "cloudbuild_sa_folder_iam" { for_each = toset(local.cloudbuild_sa_editor_roles) folder = 000000000000 role = each.value member = local.cloudbuild_sa depends_on = [ google_project_service.services, ] } # Grant Cloud Build Service Account access to the devops project. resource "google_project_iam_member" "cloudbuild_sa_project_iam" { for_each = toset(local.cloudbuild_devops_roles) project = var.project_id role = each.key member = local.cloudbuild_sa depends_on = [ google_project_service.services, ] } resource "google_cloudbuild_trigger" "validate" { provider = google-beta project = var.project_id name = "tf-validate" description = "Terraform validate job triggered on push event." included_files = [ "${local.terraform_root_prefix}**", ] github { owner = "GoogleCloudPlatform" name = "example" pull_request { branch = "^main$" } } filename = "${local.terraform_root_prefix}cicd/configs/tf-validate.yaml" substitutions = { _TERRAFORM_ROOT = local.terraform_root } depends_on = [ google_project_service.services, ] } resource "google_cloudbuild_trigger" "plan" { provider = google-beta project = var.project_id name = "tf-plan" description = "Terraform plan job triggered on push event." included_files = [ "${local.terraform_root_prefix}**", ] github { owner = "GoogleCloudPlatform" name = "example" pull_request { branch = "^main$" } } filename = "${local.terraform_root_prefix}cicd/configs/tf-plan.yaml" substitutions = { _TERRAFORM_ROOT = local.terraform_root } depends_on = [ google_project_service.services, ] } resource "google_cloudbuild_trigger" "apply" { provider = google-beta project = var.project_id name = "tf-apply" description = "Terraform apply job triggered on push event and/or schedule." included_files = [ "${local.terraform_root_prefix}**", ] github { owner = "GoogleCloudPlatform" name = "example" push { branch = "^main$" } } filename = "${local.terraform_root_prefix}cicd/configs/tf-apply.yaml" substitutions = { _TERRAFORM_ROOT = local.terraform_root } depends_on = [ google_project_service.services, ] }