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
- Automatically reads outputs from
wif_publishermodule - Populates secrets across multiple repositories
- Supports multi-environment configurations (staging, production, etc.)
- Generates helper scripts for manual updates
- Creates documentation of populated secrets
Prerequisites
- GitHub personal access token with
reposcope - Terraform GitHub provider
- Outputs from the
wif_publishermodule
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
Option 1: Environment Variable (Recommended)
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
- Go to GitHub Settings → Developer settings → Personal access tokens
- Click "Generate new token (classic)"
- Give it a descriptive name (e.g., "Terraform Secret Management")
- Select the
reposcope (full control of private repositories) - Click "Generate token"
- 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:
- secrets_summary.md: Documentation of all populated secrets
- 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
- Never commit tokens: Always use environment variables or secure storage
- Limit token scope: Use minimal required permissions
- Rotate tokens regularly: Update tokens periodically
- Use separate tokens: Different tokens for different environments
- 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.