Bootstrap (Stage 0)
Repository: gcp-foundations-bootstrap
Purpose
The bootstrap stage is a one-time manual setup that creates the foundational infrastructure required by all subsequent pipeline stages. It establishes the seed project, CI/CD project, granular Terraform service accounts, the shared GCS state bucket, and GitHub OIDC configuration for keyless CI/CD authentication.
This stage uses the terraform-google-modules/bootstrap/google module (version ~> 11.0).
Prerequisites
Before running the bootstrap stage, you must have:
- GCP Organization with Organization Admin access
- Billing Account with Billing Admin access
- Google Groups for org admins and billing admins (pre-created or created by this stage)
- GitHub App configured with appropriate permissions for the
badal-ioorganization - Terraform Cloud token and GitHub App OAuth ID
- Default labels for cost-center, owner-name, and owner-email
Resources Created
Projects
| Project | Purpose |
|---|---|
prj-b-seed | Hosts Terraform state bucket, service accounts, KMS keys |
prj-b-cicd-wif-gh | Hosts GitHub Actions Workload Identity Federation (OIDC) |
Folder
| Folder | Purpose |
|---|---|
fldr-bootstrap | Contains both bootstrap projects |
Service Accounts
Five granular Terraform service accounts are created in the seed project, each with least-privilege roles scoped to their pipeline stage:
| Service Account | Pipeline Stage | Key Org-Level Roles |
|---|---|---|
sa-terraform-bootstrap | 0-bootstrap | resourcemanager.organizationAdmin, accesscontextmanager.policyAdmin, serviceusage.serviceUsageConsumer |
sa-terraform-org | 1-org | orgpolicy.policyAdmin, logging.configWriter, resourcemanager.organizationAdmin, securitycenter.notificationConfigEditor, accesscontextmanager.policyAdmin, resourcemanager.tagAdmin, cloudasset.owner |
sa-terraform-env | 2-environments | resourcemanager.tagUser, assuredworkloads.admin |
sa-terraform-net | 3-networks | accesscontextmanager.policyAdmin, compute.xpnAdmin, resourcemanager.tagAdmin, resourcemanager.tagUser |
sa-terraform-proj | 4-projects | accesscontextmanager.policyAdmin, resourcemanager.organizationAdmin, orgpolicy.policyAdmin, iam.workloadIdentityPoolAdmin, iam.serviceAccountAdmin, iam.organizationRoleAdmin |
All service accounts additionally receive:
roles/browserat the org level (for ancestry reads)roles/billing.userandroles/billing.adminon the billing accountroles/storage.objectAdminon the seed project (for state read/write)- Stage-specific folder-level roles (e.g.,
roles/resourcemanager.folderAdmin)
GCS State Bucket
- Name:
bkt-prj-b-seed-tfstate-* - Encryption: KMS-encrypted with auto-rotating keys (90-day rotation)
- Location: Default region (northamerica-northeast1)
- Purpose: Shared Terraform state for all 5 pipeline stages
GitHub OIDC / Workload Identity Federation
- OIDC Pool:
foundation-pool - OIDC Provider:
foundation-gh-provider - SA Mapping: Each pipeline SA is mapped to its corresponding GitHub repository via
attribute.repository/{owner}/{repo} - GitHub Secrets: Automatically provisioned to each foundation repo (PROJECT_ID, WIF_PROVIDER_NAME, TF_BACKEND, SERVICE_ACCOUNT_EMAIL, etc.)
Google Groups
The bootstrap stage can optionally create Google Groups:
Required Groups:
group_org_admins-- GCP Organization Administratorsgroup_billing_admins-- GCP Billing Administratorsbilling_data_users-- Billing data viewersaudit_data_users-- Audit log viewersmonitoring_workspace_users-- Monitoring workspace users
Optional Groups:
gcp_platform_viewer,gcp_security_reviewer,gcp_network_viewergcp_scc_admin,gcp_global_secrets_admin,gcp_audit_viewer
Key Variables
| Variable | Description | Default |
|---|---|---|
org_id | GCP Organization ID | -- |
billing_account | Billing account ID | -- |
default_region | Primary region | us-central1 |
default_region_2 | Secondary region | us-west1 |
project_prefix | Project name prefix (max 3 chars) | prj |
folder_prefix | Folder name prefix | fldr |
bucket_prefix | State bucket name prefix | bkt |
gh_repos | GitHub repo names for each stage | -- |
gh_app_id | GitHub App ID (sensitive) | -- |
gh_app_installation_id | GitHub App installation ID (sensitive) | -- |
default_labels | Required labels: cost-center, owner-name, owner-email | -- |
Key Outputs
These outputs are consumed by all subsequent stages via terraform_remote_state:
| Output | Description | Consumed By |
|---|---|---|
common_config | org_id, billing_account, regions, prefixes, parent_id | All stages |
seed_project_id | Seed project ID | All stages |
gcs_bucket_tfstate | State bucket name | All stages |
cicd_project_id | CI/CD project ID | Bootstrap |
*_step_terraform_service_account_email | SA email per stage | Each respective stage |
group_org_admins | Org admins group | 1-org |
group_billing_admins | Billing admins group | 1-org |
Running Bootstrap
The bootstrap stage is run manually by an operator with Organization Admin privileges. It cannot be run via CI/CD because the CI/CD infrastructure does not yet exist.
Preparation Checklist
- Ensure you have
roles/resourcemanager.organizationAdminandroles/billing.adminon the GCP organization - Create or identify Google Groups for org admins and billing admins
- Register a GitHub App in the
badal-ioorganization with repository permissions - Configure a
terraform.tfvarsfile with all required variables - Run
terraform initandterraform applyfrom theenvs/shareddirectory
cd envs/shared
terraform init
terraform plan
terraform apply
After bootstrap completes, all subsequent stages can be deployed via GitHub Actions CI/CD using the service accounts and OIDC configuration created by this stage.
Directory Structure
gcp-foundations-bootstrap/
+-- envs/
+-- shared/
+-- main.tf # Seed bootstrap module, folder
+-- sa.tf # 5 granular service accounts + IAM
+-- github.tf # GitHub OIDC, CI/CD project, secrets
+-- groups.tf # Google Groups creation
+-- backstage.tf # Backstage-specific config
+-- outputs.tf # Outputs consumed by later stages
+-- variables.tf # Input variables
+-- versions.tf # Provider versions
+-- backend.tf # GCS backend config
+-- provider.tf # Provider configuration
+-- modules/
+-- cb-private-pool/ # Cloud Build private worker pool
+-- gitlab-oidc/ # GitLab OIDC (alternative)
+-- parent-iam-member/
+-- parent-iam-remove-role/
+-- tfc-agent-gke/ # TFC agent on GKE (alternative)