Skip to content

Commit bb25044

Browse files
Merge pull request #511 from overmindtech/gcp-demo
Gcp demo
2 parents a2412a3 + 7c9d5ce commit bb25044

11 files changed

Lines changed: 231 additions & 2 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
// Features to add to the dev container. More info: https://containers.dev/features.
88
"features": {
99
"ghcr.io/devcontainers/features/aws-cli:1": {},
10+
"ghcr.io/devcontainers/features/gcloud:1": {},
1011
"ghcr.io/devcontainers/features/terraform:1": {}
1112
},
1213
// Configure tool-specific properties.
1314
"customizations": {
1415
"vscode": {
1516
"extensions": [
1617
"github.vscode-github-actions",
17-
"hashicorp.terraform"
18+
"hashicorp.terraform",
19+
"googlecloudplatform.gcp-vscode"
1820
]
1921
}
2022
}
@@ -24,5 +26,6 @@
2426
// },
2527
// "mounts": [
2628
// "source=${localEnv:HOME}${localEnv:USERPROFILE}/.aws,target=/home/vscode/.aws,type=bind",
29+
// "source=${localEnv:HOME}${localEnv:USERPROFILE}/.config/gcloud,target=/home/vscode/.config/gcloud,type=bind"
2730
// ]
2831
}

.github/actions/terraform_init/action.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ inputs:
77
terraform_workspace:
88
description: "The Terraform workspace to use (optional)"
99
required: false
10+
gcp_workload_identity_provider:
11+
description: "GCP Workload Identity Provider resource name for OIDC auth"
12+
required: true
13+
gcp_service_account:
14+
description: "GCP service account email to impersonate via WIF"
15+
required: true
1016

1117
runs:
1218
using: "composite"
@@ -29,6 +35,12 @@ runs:
2935
aws-region: eu-west-2
3036
role-to-assume: ${{ inputs.terraform_deploy_role }}
3137

38+
- name: Configure GCP Credentials
39+
uses: google-github-actions/auth@v3
40+
with:
41+
workload_identity_provider: ${{ inputs.gcp_workload_identity_provider }}
42+
service_account: ${{ inputs.gcp_service_account }}
43+
3244
- name: Terraform Init
3345
id: init
3446
shell: bash

.github/workflows/automatic.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ jobs:
3232
with:
3333
terraform_deploy_role: ${{ vars.TERRAFORM_DEPLOY_ROLE }}
3434
terraform_workspace: terraform-example
35+
gcp_workload_identity_provider: ${{ vars.GCP_WORKLOAD_IDENTITY_PROVIDER }}
36+
gcp_service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
3537

3638
- name: Download terraform plan
3739
uses: actions/download-artifact@v8
@@ -70,6 +72,8 @@ jobs:
7072
with:
7173
terraform_deploy_role: ${{ vars.TERRAFORM_DEPLOY_ROLE }}
7274
terraform_workspace: terraform-example
75+
gcp_workload_identity_provider: ${{ vars.GCP_WORKLOAD_IDENTITY_PROVIDER }}
76+
gcp_service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
7377

7478
- name: Terraform Validate
7579
if: github.event.action != 'closed'
@@ -153,6 +157,8 @@ jobs:
153157
with:
154158
terraform_deploy_role: ${{ vars.TERRAFORM_DEPLOY_ROLE }}
155159
terraform_workspace: terraform-example
160+
gcp_workload_identity_provider: ${{ vars.GCP_WORKLOAD_IDENTITY_PROVIDER }}
161+
gcp_service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
156162

157163
- name: Terraform Plan for Cost Analysis
158164
id: plan-cost

.github/workflows/manual.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ jobs:
2020
with:
2121
terraform_deploy_role: ${{ vars.TERRAFORM_DEPLOY_ROLE }}
2222
terraform_workspace: terraform-example
23+
gcp_workload_identity_provider: ${{ vars.GCP_WORKLOAD_IDENTITY_PROVIDER }}
24+
gcp_service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
2325

2426
- name: Terraform Plan
2527
id: plan

.github/workflows/signals-demo.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ jobs:
113113
with:
114114
terraform_deploy_role: ${{ vars.TERRAFORM_DEPLOY_ROLE }}
115115
terraform_workspace: terraform-example
116+
gcp_workload_identity_provider: ${{ vars.GCP_WORKLOAD_IDENTITY_PROVIDER }}
117+
gcp_service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
116118

117119
- name: Terraform Plan
118120
run: terraform plan -out=tfplan

.terraform.lock.hcl

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

main.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,14 @@ module "agm_talk" {
250250
source = "./modules/agm-talk"
251251
}
252252

253+
# Simple GCS bucket to validate GCP provider connectivity in CI
254+
resource "google_storage_bucket" "test" {
255+
name = "${var.gcp_project_id}-tf-test"
256+
location = var.gcp_region
257+
force_destroy = true
258+
uniform_bucket_level_access = true
259+
}
260+
253261
module "api_access" {
254262
count = var.enable_api_access ? 1 : 0
255263
source = "./modules/signals-demo"

outputs.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
# value = aws_iam_role.deploy_role.arn
33
# }
44

5+
# GCP Workload Identity Federation outputs (needed for CI platform configuration)
6+
output "gcp_workload_identity_provider" {
7+
description = "Full resource name of the GitHub Actions WIF provider (for google-github-actions/auth)"
8+
value = google_iam_workload_identity_pool_provider.github.name
9+
}
10+
11+
output "gcp_service_account_email" {
12+
description = "Email of the GCP deploy service account"
13+
value = google_service_account.deploy.email
14+
}
15+
516
# API Server outputs
617
output "api_server_url" {
718
description = "URL to access the API server"

terraform.tf

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ provider "aws" {
55
region = "eu-west-2"
66
}
77

8+
provider "google" {
9+
project = var.gcp_project_id
10+
region = var.gcp_region
11+
}
12+
813
# Disable this temporarily during bootstrapping and use `terraform init
914
# -migrate-state` to migrate the local state into S3 after all resources have
1015
# been deployed
@@ -17,6 +22,10 @@ terraform {
1722
# we expect this to be fixed over the coming weeks, as of 23/6/2025
1823
version = "< 6.38"
1924
}
25+
google = {
26+
source = "hashicorp/google"
27+
version = "~> 6.0"
28+
}
2029
archive = {
2130
source = "hashicorp/archive"
2231
version = "~> 2.0"
@@ -287,3 +296,146 @@ resource "aws_iam_openid_connect_provider" "env0" {
287296
client_id_list = ["hoMiq9PdkRh9LUvVpH4wIErWg50VSG1b"]
288297
thumbprint_list = [data.tls_certificate.env0.certificates[0].sha1_fingerprint]
289298
}
299+
300+
# =============================================================================
301+
# GCP Workload Identity Federation
302+
# Mirrors the AWS OIDC provider + deploy role pattern above.
303+
# See https://cloud.google.com/iam/docs/workload-identity-federation
304+
# =============================================================================
305+
306+
resource "google_iam_workload_identity_pool" "deploy" {
307+
workload_identity_pool_id = "${var.example_env}-deploy"
308+
display_name = "Deploy Pool (${var.example_env})"
309+
description = "Workload Identity Pool for CI/CD platforms to deploy infrastructure"
310+
}
311+
312+
# GitHub Actions OIDC provider
313+
resource "google_iam_workload_identity_pool_provider" "github" {
314+
workload_identity_pool_id = google_iam_workload_identity_pool.deploy.workload_identity_pool_id
315+
workload_identity_pool_provider_id = "github-actions"
316+
display_name = "GitHub Actions"
317+
318+
attribute_mapping = {
319+
"google.subject" = "assertion.sub"
320+
"attribute.actor" = "assertion.actor"
321+
"attribute.repository" = "assertion.repository"
322+
}
323+
324+
attribute_condition = "assertion.repository == 'overmindtech/terraform-example'"
325+
326+
oidc {
327+
issuer_uri = "https://token.actions.githubusercontent.com"
328+
}
329+
}
330+
331+
# Terraform Cloud OIDC provider
332+
resource "google_iam_workload_identity_pool_provider" "tfc" {
333+
count = var.example_env == "terraform-example" ? 1 : 0
334+
335+
workload_identity_pool_id = google_iam_workload_identity_pool.deploy.workload_identity_pool_id
336+
workload_identity_pool_provider_id = "terraform-cloud"
337+
display_name = "Terraform Cloud"
338+
339+
attribute_mapping = {
340+
"google.subject" = "assertion.sub"
341+
"attribute.terraform_workspace" = "assertion.terraform_workspace_name"
342+
"attribute.terraform_organization" = "assertion.terraform_organization_name"
343+
}
344+
345+
attribute_condition = "assertion.terraform_organization_name == 'Overmind'"
346+
347+
oidc {
348+
issuer_uri = "https://app.terraform.io"
349+
allowed_audiences = ["gcp.workload.identity"]
350+
}
351+
}
352+
353+
# env0 OIDC provider
354+
resource "google_iam_workload_identity_pool_provider" "env0" {
355+
count = var.example_env == "terraform-example" ? 1 : 0
356+
357+
workload_identity_pool_id = google_iam_workload_identity_pool.deploy.workload_identity_pool_id
358+
workload_identity_pool_provider_id = "env0"
359+
display_name = "env0"
360+
361+
attribute_mapping = {
362+
"google.subject" = "assertion.sub"
363+
}
364+
365+
oidc {
366+
issuer_uri = "https://login.app.env0.com/"
367+
allowed_audiences = ["https://prod.env0.com"]
368+
}
369+
}
370+
371+
# Spacelift OIDC provider
372+
resource "google_iam_workload_identity_pool_provider" "spacelift" {
373+
count = var.example_env == "terraform-example" ? 1 : 0
374+
375+
workload_identity_pool_id = google_iam_workload_identity_pool.deploy.workload_identity_pool_id
376+
workload_identity_pool_provider_id = "spacelift"
377+
display_name = "Spacelift"
378+
379+
attribute_mapping = {
380+
"google.subject" = "assertion.sub"
381+
"attribute.space" = "assertion.spaceId"
382+
"attribute.stack" = "assertion.callerId"
383+
"attribute.caller_type" = "assertion.callerType"
384+
}
385+
386+
oidc {
387+
issuer_uri = "https://overmindtech.app.spacelift.io"
388+
}
389+
}
390+
391+
# Deploy service account (GCP equivalent of aws_iam_role.deploy_role)
392+
resource "google_service_account" "deploy" {
393+
account_id = "${var.example_env}-deploy"
394+
display_name = "Terraform Deploy (${var.example_env})"
395+
description = "Service account used by CI/CD platforms to deploy infrastructure via Workload Identity Federation"
396+
}
397+
398+
resource "google_project_iam_member" "deploy_editor" {
399+
project = var.gcp_project_id
400+
role = "roles/editor"
401+
member = "serviceAccount:${google_service_account.deploy.email}"
402+
}
403+
404+
# Allow the Workload Identity Pool to impersonate the deploy service account
405+
resource "google_service_account_iam_member" "github_wif" {
406+
service_account_id = google_service_account.deploy.name
407+
role = "roles/iam.workloadIdentityUser"
408+
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.deploy.name}/attribute.repository/overmindtech/terraform-example"
409+
}
410+
411+
resource "google_service_account_iam_member" "tfc_wif" {
412+
count = var.example_env == "terraform-example" ? 1 : 0
413+
414+
service_account_id = google_service_account.deploy.name
415+
role = "roles/iam.workloadIdentityUser"
416+
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.deploy.name}/attribute.terraform_organization/Overmind"
417+
}
418+
419+
resource "google_service_account_iam_member" "env0_wif" {
420+
count = var.example_env == "terraform-example" ? 1 : 0
421+
422+
service_account_id = google_service_account.deploy.name
423+
role = "roles/iam.workloadIdentityUser"
424+
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.deploy.name}/*"
425+
condition {
426+
title = "env0-provider-only"
427+
expression = "request.auth.claims.iss == 'https://login.app.env0.com/'"
428+
}
429+
}
430+
431+
resource "google_service_account_iam_member" "spacelift_wif" {
432+
count = var.example_env == "terraform-example" ? 1 : 0
433+
434+
service_account_id = google_service_account.deploy.name
435+
role = "roles/iam.workloadIdentityUser"
436+
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.deploy.name}/*"
437+
condition {
438+
title = "spacelift-provider-only"
439+
expression = "request.auth.claims.iss == 'https://overmindtech.app.spacelift.io'"
440+
}
441+
}

terraform.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gcp_project_id = "overmind-terraform-example"

0 commit comments

Comments
 (0)