GitHub Secrets Populator Module

Companion module to wif_publisher that automatically populates GitHub repository secrets using the Terraform GitHub provider. Perfect for mono-repos and multi-environment setups.

Features

Prerequisites

Usage

Basic Setup (Single Environment)

# First, create the WIF infrastructure
module "wif_publisher" {
  source = "../wif_publisher"

  project_id    = "my-prod-project"
  gar_location  = "us-central1"
  gar_py_repo   = "mizoki-python"
  gar_npm_repo  = "mizoki-npm"
  repo_owner    = "mediaintelligence"
  repo_name     = "MIZOKICloudRun"
}

# Then populate GitHub secrets
module "github_secrets" {
  source = "../github_secrets_populator"

  github_token = var.github_token  # Store in TF_VAR_github_token env var
  github_owner = "mediaintelligence"

  github_repositories = [
    "MIZOKICloudRun",
    "MIZOKIServices",
    "MIZOKIAnalytics"
  ]

  # Pass outputs from wif_publisher module
  wif_provider       = module.wif_publisher.wif_provider
  publisher_sa_email = module.wif_publisher.publisher_sa_email

  # GCP configuration
  gcp_project_id = "my-prod-project"
  gar_location   = "us-central1"
  gar_py_repo    = "mizoki-python"
  gar_npm_repo   = "mizoki-npm"
}

Multi-Environment Setup

# Production WIF
module "wif_prod" {
  source = "../wif_publisher"

  project_id       = "my-prod-project"
  gar_location     = "us-central1"
  gar_py_repo      = "mizoki-python-prod"
  gar_npm_repo     = "mizoki-npm-prod"
  repo_owner       = "mediaintelligence"
  repo_name        = "MIZOKICloudRun"
  pool_id          = "github-pool-prod"
  publisher_sa_id  = "mizoki-publisher-prod"
}

# Staging WIF
module "wif_staging" {
  source = "../wif_publisher"

  project_id       = "my-staging-project"
  gar_location     = "us-central1"
  gar_py_repo      = "mizoki-python-staging"
  gar_npm_repo     = "mizoki-npm-staging"
  repo_owner       = "mediaintelligence"
  repo_name        = "MIZOKICloudRun"
  pool_id          = "github-pool-staging"
  publisher_sa_id  = "mizoki-publisher-staging"
}

# Populate secrets for both environments
module "github_secrets_multi" {
  source = "../github_secrets_populator"

  github_token = var.github_token
  github_owner = "mediaintelligence"

  github_repositories = [
    "MIZOKICloudRun",
    "MIZOKIServices"
  ]

  # Default/production secrets
  wif_provider       = module.wif_prod.wif_provider
  publisher_sa_email = module.wif_prod.publisher_sa_email
  gcp_project_id     = "my-prod-project"
  gar_location       = "us-central1"
  gar_py_repo        = "mizoki-python-prod"
  gar_npm_repo       = "mizoki-npm-prod"

  # Additional environment-specific secrets
  environment_secrets = {
    staging = {
      wif_provider       = module.wif_staging.wif_provider
      publisher_sa_email = module.wif_staging.publisher_sa_email
      gcp_project_id     = "my-staging-project"
    }
  }
}

With Secret Prefixes

module "github_secrets_prefixed" {
  source = "../github_secrets_populator"

  github_token = var.github_token
  github_owner = "mediaintelligence"

  github_repositories = ["MIZOKICloudRun"]

  # Add prefix to all secrets
  secret_prefix = "PROD_"

  # Rest of configuration...
  wif_provider       = module.wif_publisher.wif_provider
  publisher_sa_email = module.wif_publisher.publisher_sa_email
  gcp_project_id     = "my-prod-project"
  gar_location       = "us-central1"
  gar_py_repo        = "mizoki-python"
  gar_npm_repo       = "mizoki-npm"
}

Setting Up GitHub Token

export TF_VAR_github_token="ghp_YOUR_PERSONAL_ACCESS_TOKEN"
terraform apply

Option 2: terraform.tfvars

# terraform.tfvars (add to .gitignore!)
github_token = "ghp_YOUR_PERSONAL_ACCESS_TOKEN"

Option 3: CLI Flag

terraform apply -var="github_token=ghp_YOUR_PERSONAL_ACCESS_TOKEN"

Creating GitHub Personal Access Token

  1. Go to GitHub Settings → Developer settings → Personal access tokens
  2. Click "Generate new token (classic)"
  3. Give it a descriptive name (e.g., "Terraform Secret Management")
  4. Select the repo scope (full control of private repositories)
  5. Click "Generate token"
  6. Copy the token immediately (you won't see it again)

Input Variables

Variable Type Default Description
github_token string - GitHub personal access token (required)
github_owner string - GitHub organization/owner (required)
github_repositories list(string) - List of repository names (required)
wif_provider string - WIF provider from wif_publisher (required)
publisher_sa_email string - SA email from wif_publisher (required)
gcp_project_id string - GCP project ID (required)
gar_location string - Artifact Registry location (required)
gar_py_repo string - Python repository name (required)
gar_npm_repo string - NPM repository name (required)
environment_secrets map(object) {} Additional environment configs
secret_prefix string "" Prefix for secret names
create_wif_secrets bool true Create WIF secrets
create_gar_secrets bool true Create GAR secrets
create_project_secrets bool true Create project ID secret

Outputs

Output Description
populated_repositories List of repositories where secrets were created
created_secrets List of all secret names created
repository_secret_count Number of secrets per repository
total_secrets_created Total count of all secrets created
secrets_summary Categorized summary of secrets
github_actions_usage_example Example workflow snippet

Generated Files

The module creates two helper files:

  1. secrets_summary.md: Documentation of all populated secrets
  2. update_secrets.sh: Bash script for manual secret updates using GitHub CLI

GitHub Actions Usage

After running this module, use the secrets in your workflows:

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write

    steps:
      - uses: actions/checkout@v4

      # Production authentication
      - name: Authenticate to GCP (Production)
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
          service_account: ${{ secrets.GCP_WIF_SA_EMAIL }}

      # Or staging authentication
      - name: Authenticate to GCP (Staging)
        if: github.ref != 'refs/heads/main'
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: ${{ secrets.STAGING_GCP_WIF_PROVIDER }}
          service_account: ${{ secrets.STAGING_GCP_WIF_SA_EMAIL }}

Security Best Practices

  1. Never commit tokens: Always use environment variables or secure storage
  2. Limit token scope: Use minimal required permissions
  3. Rotate tokens regularly: Update tokens periodically
  4. Use separate tokens: Different tokens for different environments
  5. Enable SSO: Use GitHub SSO if available in your organization

Troubleshooting

Token Permission Errors

Error: POST https://api.github.com/repos/owner/repo/actions/secrets/SECRET_NAME: 403

Solution: Ensure your token has the repo scope.

Repository Not Found

Error: GET https://api.github.com/repos/owner/repo: 404

Solution: Check that: - Repository name is correct - Token has access to the repository - Repository exists and is accessible

Viewing Current Secrets

# List all secrets in a repository
gh secret list -R mediaintelligence/MIZOKICloudRun

# View secret metadata (not values)
gh api repos/mediaintelligence/MIZOKICloudRun/actions/secrets

Complete Example

# terraform/main.tf
variable "github_token" {
  type      = string
  sensitive = true
}

module "wif" {
  source = "./modules/wif_publisher"

  project_id    = "mizoki-prod-123456"
  gar_location  = "us-central1"
  gar_py_repo   = "mizoki-python"
  gar_npm_repo  = "mizoki-npm"
  repo_owner    = "mediaintelligence"
  repo_name     = "MIZOKICloudRun"
}

module "secrets" {
  source = "./modules/github_secrets_populator"

  github_token = var.github_token
  github_owner = "mediaintelligence"

  github_repositories = [
    "MIZOKICloudRun",
    "MIZOKIServices",
    "MIZOKIAnalytics"
  ]

  wif_provider       = module.wif.wif_provider
  publisher_sa_email = module.wif.publisher_sa_email
  gcp_project_id     = "mizoki-prod-123456"
  gar_location       = "us-central1"
  gar_py_repo        = "mizoki-python"
  gar_npm_repo       = "mizoki-npm"
}

output "setup_complete" {
  value = "✅ WIF and GitHub secrets configured for ${length(module.secrets.populated_repositories)} repositories"
}

Run with:

export TF_VAR_github_token="ghp_YOUR_TOKEN"
terraform init
terraform apply

License

This module is provided as-is for MIZOKI Cloud Run deployment.

← All docsView source on GitHub →