@@ -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+ }
0 commit comments