Use a user-specified service account to trigger a GCP cloudbuild job.
Sat Feb 24 2024
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.
Step 2: Create a service account
Create a service account with the necessary permissions to trigger a cloudbuild job.
gcloud iam service-accounts create [SA-NAME] \
--description="Service account to trigger cloudbuild jobs" \
--display-name="[SA-DISPLAY-NAME]"
Step 3: Grant the necessary permissions to the service account
gcloud projects add-iam-policy-binding [PROJECT_ID] \
--member="serviceAccount:[SA-EMAIL]" \
--role="roles/cloudbuild.builds.builder"
Step 4: Create a key for the service account
gcloud iam service-accounts keys create [KEY_FILE] \
--iam-account=[SA-EMAIL]
Step 5: Store the key in Github secrets
Navigate to your Github repository and go to Settings
> Secrets
and add the key as a secret.
Step 6: 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 7: 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 8: 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 9: 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.