Configure User-Specified Service Accounts for GCP Cloud Build
Step-by-step: Configure secure GCP Cloud Build using Terraform, GitHub CI/CD, and custom service accounts.
In a move towards enhanced security and granular control, Google Cloud Platform (GCP) has recently shifted its Cloud Build service away from the default service account.
This change encourages users to specify custom service accounts when triggering builds, empowering you to enforce least-privilege principles and tighten your CI/CD pipeline's security posture.
In this blog post, I will guide you through configuring custom service accounts for Cloud Build using Terraform and YAML files within the robust GitHub Actions CI/CD framework.
Prerequisites
A Google Cloud Platform account with billing enabled.
Terraform installed on your machine.
A service account with the necessary permissions to trigger a cloudbuild job.
A Github account.
Setup
Step 1: Enable the Cloud Build API
Navigate to the Cloud Build API and enable it.
Step2: Create a Terraform file
Create a main.tf file in the root of your repository with the following content.
data "google_project" "project" {}
resource "google_cloudbuild_trigger" "service-account-trigger" {
trigger_template {
branch_name = "main"
repo_name = "my-repo"
}
service_account = google_service_account.cloudbuild_service_account.id
filename = "cloudbuild.yaml"
depends_on = [
google_project_iam_member.act_as,
google_project_iam_member.logs_writer
]
}
resource "google_service_account" "cloudbuild_service_account" {
account_id = "cloud-sa"
}
resource "google_project_iam_member" "act_as" {
project = data.google_project.project.project_id
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${google_service_account.cloudbuild_service_account.email}"
}
resource "google_project_iam_member" "logs_writer" {
project = data.google_project.project.project_id
role = "roles/logging.logWriter"
member = "serviceAccount:${google_service_account.cloudbuild_service_account.email}"
}
Step 3: Create a key for the service account
gcloud iam service-accounts keys create [KEY_FILE] \
--iam-account=[SA-EMAIL]
Step 4: Store the key in Github secrets
Navigate to your Github repository and go to Settings
> Secrets
and add the key as a secret.
Step 5: Create a cloudbuild.yaml file
Create a cloudbuild.yaml
file in the root of your repository with the following content.
steps:
# Docker Build
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t',
'us-central1-docker.pkg.dev/${PROJECT_ID}/my-docker-repo/myimage',
'.']
# Docker Push
- name: 'gcr.io/cloud-builders/docker'
args: ['push',
'us-central1-docker.pkg.dev/${PROJECT_ID}/my-docker-repo/myimage']
# Entrypoint, timeout and environment variables
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: 'gcloud'
timeout: 240s
args: ['compute', 'instances',
'create-with-container', 'my-vm-name',
'--container-image',
'us-central1-docker.pkg.dev/${PROJECT_ID}/my-docker-repo/myimage']
env:
- 'CLOUDSDK_COMPUTE_REGION=us-central1'
- 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
Step 6: Create a Github workflow
Create a .github/workflows/main.yml
file in the root of your repository with the following content.
name: Trigger cloudbuild job
on:
push:
branches:
- main
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up gcloud
uses: google-github-actions/setup-gcloud@v0.2.0
with:
service_account_key: ${{ secrets.SERVICE_ACCOUNT_KEY }}
project_id: ${{ secrets.PROJECT_ID }}
export_default_credentials: true
- name: Trigger cloudbuild job
run: |
gcloud builds submit --config=cloudbuild.yaml .
Step 7: Run Terraform
Run the following commands to apply the Terraform configuration.
terraform init
terraform apply
Usage
Commit the changes to your repository and push them to the main branch. This will trigger the Github workflow and start the cloudbuild job.
Conclusion
Congratulations! You have successfully used a user-specified service account to trigger a GCP cloudbuild job with Terraform and YAML using Github CI workflow.