Skip to content

GitHub Provider

The GitHub provider enables SecretZero to store and manage secrets in GitHub Actions. It supports token authentication for managing repository secrets and environment-specific secrets.

Overview

The GitHub provider is ideal for:

  • CI/CD pipelines using GitHub Actions workflows
  • Repository automation requiring secure credential management
  • Multi-repository deployments needing consistent secrets across repos
  • Environment-specific deployments (production, staging, development)
  • Teams using GitHub Enterprise with custom API endpoints

Supported Target Types

Target Type Description Use Case
github_secret GitHub Actions secret (repository or environment) Workflow credentials, API keys, deployment tokens, environment-specific secrets

Authentication

Token Authentication

The GitHub provider uses Personal Access Tokens (PAT) or GitHub Apps for authentication.

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

When to use: All scenarios with GitHub Actions secret management.

Creating a Personal Access Token

  1. Navigate to GitHub Settings:
  2. Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)

  3. Generate new token (classic):

  4. Click "Generate new token (classic)"
  5. Give it a descriptive name (e.g., "SecretZero Token")
  6. Set expiration (recommended: 90 days with rotation)

  7. Select scopes:

  8. repo - Full control of private repositories (required for repository secrets)
  9. workflow - Update GitHub Action workflows (optional, for workflow management)

  10. Generate and save token:

  11. Click "Generate token"
  12. Copy the token immediately (it won't be shown again)
  13. Store securely or export as environment variable

  14. Set environment variable:

    export GITHUB_TOKEN=ghp_your_token_here
    

GitHub Enterprise Support

For GitHub Enterprise Server, specify a custom API URL:

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}
        api_url: https://github.mycompany.com/api/v3

Configuration

Basic Configuration

version: '1.0'

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  - name: api_key
    kind: random_string
    config:
      length: 32
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorganization
          repo: myrepo

Multi-Repository Configuration

Deploy secrets to multiple repositories:

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  - name: shared_api_key
    kind: random_string
    config:
      length: 32
    targets:
      # Backend repository
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: backend-service

      # Frontend repository
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: frontend-app

      # Mobile repository
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: mobile-app

Environment-Specific Configuration

Use environment secrets for production, staging, and development:

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  - name: database_password
    kind: random_password
    config:
      length: 32
      special: true
    targets:
      # Production environment
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp
          environment: production

      # Staging environment
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp
          environment: staging

      # Development environment (repository-level)
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp

Target Types

GitHub Secret

The github_secret target type stores secrets in GitHub Actions. It supports both repository-level and environment-specific secrets based on configuration.

Configuration Options

Option Type Required Default Description
owner string Yes - Repository owner (user or organization)
repo string Yes - Repository name
environment string No - Environment name for environment-specific secrets
secret_name string No secret name Custom secret name (defaults to secret name in uppercase)

Example: Repository Secret

secrets:
  - name: api_key
    kind: random_string
    config:
      length: 32
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorganization
          repo: myrepo

The secret will be available in workflows as ${{ secrets.API_KEY }}.

Example: Custom Secret Name

secrets:
  - name: database_password
    kind: random_password
    config:
      length: 32
      special: true
      exclude_characters: '"@/\`'
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp
          secret_name: DB_PASSWORD_PROD

The secret will be available as ${{ secrets.DB_PASSWORD_PROD }}.

Example: Environment Secret

Environment secrets are created by adding an environment parameter:

secrets:
  - name: database_url
    kind: static
    config:
      default: postgresql://prod-db.example.com:5432/myapp
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp
          environment: production

Example: Multi-Environment Secrets

Deploy the same secret to multiple environments:

secrets:
  - name: api_endpoint
    kind: static
    config:
      default: https://api.example.com
    targets:
      # Production
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp
          environment: production
          secret_name: API_ENDPOINT

      # Staging
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp
          environment: staging
          secret_name: API_ENDPOINT

Complete Examples

Example 1: Simple Application Secrets

version: '1.0'

variables:
  github_org: myorganization
  github_repo: myapp
  environment: production

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  # API Key
  - name: api_key
    kind: random_string
    config:
      length: 32
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"

  # Database Password
  - name: database_password
    kind: random_password
    rotation_period: 90d
    config:
      length: 32
      special: true
      exclude_characters: '"@/\`'
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"
          environment: "{{var.environment}}"

  # JWT Signing Secret
  - name: jwt_secret
    kind: random_string
    config:
      length: 64
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"

metadata:
  project: "{{var.github_repo}}"
  owner: backend-team

Example 2: Multi-Environment Setup

version: '1.0'

variables:
  github_org: myorganization
  github_repo: myapp

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  # Database credentials for all environments
  - name: database_password
    kind: random_password
    config:
      length: 32
      special: true
      exclude_characters: '"@/\'
    targets:
      # Production environment
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"
          environment: production

      # Staging environment
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"
          environment: staging

      # Development (repository-level)
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"

  # API endpoints (static values)
  - name: api_url
    kind: static
    config:
      default: https://api.example.com
    targets:
      # Production endpoint
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"
          environment: production
          secret_name: API_URL

  - name: api_url_staging
    kind: static
    config:
      default: https://staging-api.example.com
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: "{{var.github_repo}}"
          environment: staging
          secret_name: API_URL

Example 3: Multi-Repository Deployment

version: '1.0'

variables:
  github_org: myorganization

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  # Shared API key across services
  - name: external_api_key
    kind: random_string
    config:
      length: 32
      charset: alphanumeric
    targets:
      # Backend service
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: backend-service
          environment: production

      # Frontend app
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: frontend-app
          environment: production

      # Worker service
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: worker-service
          environment: production

  # Service-specific secrets
  - name: database_password
    kind: random_password
    config:
      length: 32
      special: true
    targets:
      # Only backend needs database access
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: backend-service
          environment: production

      # Worker also needs database
      - provider: github
        kind: github_secret
        config:
          owner: "{{var.github_org}}"
          repo: worker-service
          environment: production

PAT Permissions and Scopes

Required Token Scopes

For Repository Secrets

  • repo - Full control of private repositories
  • Grants access to create, update, and delete repository secrets
  • Required for both public and private repositories

For Environment Secrets

  • repo - Full control of private repositories
  • Environment secrets require repository admin access
  • Same permissions as repository secrets

Token Best Practices

  1. Use fine-grained tokens when available:
  2. Limit token scope to specific repositories
  3. Set shorter expiration periods
  4. Revoke tokens after use in CI/CD

  5. Rotate tokens regularly:

    # Document token expiration
    metadata:
      token_expires: 2024-12-31
      token_owner: devops-team
    

  6. Use different tokens for different purposes:

  7. Separate tokens for production and non-production
  8. Different tokens per team or project
  9. Dedicated tokens for automation

  10. Audit token usage:

  11. Review token activity in GitHub Settings
  12. Monitor API rate limits
  13. Track secret updates through lockfile

Integration with GitHub Actions Workflows

Using Secrets in Workflows

Once synced, secrets are available in your GitHub Actions workflows:

Repository Secret Usage

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Deploy with secrets
        run: |
          echo "API_KEY=${{ secrets.API_KEY }}" >> .env
          echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env
          ./deploy.sh
        env:
          JWT_SECRET: ${{ secrets.JWT_SECRET }}

Environment Secret Usage

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy-prod:
    runs-on: ubuntu-latest
    environment: production  # Must specify environment
    steps:
      - uses: actions/checkout@v3

      - name: Deploy to production
        run: |
          echo "Deploying to production..."
          ./deploy.sh
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          API_KEY: ${{ secrets.API_KEY }}

Environment Protection Rules

Combine environment secrets with protection rules:

# .github/workflows/deploy.yml
name: Deploy with Approval

on:
  push:
    branches: [main]

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Deploy to staging
        run: ./deploy.sh staging
        env:
          DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production  # Requires manual approval
    steps:
      - name: Deploy to production
        run: ./deploy.sh production
        env:
          DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}

Configure environment protection rules in GitHub: 1. Repository Settings → Environments → production 2. Required reviewers: Select team members 3. Wait timer: Optional deployment delay 4. Deployment branches: Limit to specific branches

Best Practices

1. Use Environment Secrets for Production

# Good: Environment-specific secrets with protection
secrets:
  - name: prod_db_password
    kind: random_password
    config:
      length: 32
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp
          environment: production  # Enables environment protection

# Avoid: Repository-level secrets for production
secrets:
  - name: prod_db_password
    kind: random_password
    config:
      length: 32
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp  # No environment protection

2. Rotate Tokens Regularly

secrets:
  - name: api_key
    kind: random_string
    rotation_period: 90d  # Automatic rotation
    config:
      length: 32
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: myapp

3. Use the Lockfile

# Generate lockfile on first sync
secretzero sync -f Secretfile.yml

# Commit lockfile to track secret lifecycle
git add .secretzero.lock
git commit -m "Update secret lockfile"

# Verify lockfile before syncing
secretzero sync -f Secretfile.yml --verify-lock

4. Implement Naming Conventions

# Good: Clear, consistent naming
secrets:
  - name: database_password      # Becomes DATABASE_PASSWORD
  - name: api_external_key       # Becomes API_EXTERNAL_KEY
  - name: jwt_signing_secret     # Becomes JWT_SIGNING_SECRET

# Avoid: Ambiguous names
secrets:
  - name: secret1
  - name: key
  - name: password

5. Deploy to Multiple Repositories Consistently

When you need the same secret in multiple repositories, deploy it consistently:

# Good: Deploy same secret to multiple repositories
secrets:
  - name: shared_api_key
    kind: random_string
    config:
      length: 32
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: backend-service
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: frontend-app
      - provider: github
        kind: github_secret
        config:
          owner: myorg
          repo: worker-service

# Track with lockfile to ensure consistency

6. Audit Secret Access

# Use GitHub audit log to track secret access
# Organization Settings → Audit log → Filter by "secret"

# Monitor secret updates with lockfile
git log .secretzero.lock

# Review workflow runs that use secrets
# Actions → Select workflow → Review runs

7. Never Commit Tokens

# Add to .gitignore
echo "GITHUB_TOKEN" >> .gitignore
echo ".env" >> .gitignore
echo "*.secret" >> .gitignore

# Remove committed token
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch .env' --prune-empty --tag-name-filter cat -- --all

Troubleshooting

Authentication Failed

Error: GitHub authentication failed. Check credentials and configuration.

Solutions:

  1. Verify token is set:

    echo $GITHUB_TOKEN
    

  2. Test token with GitHub CLI:

    gh auth status
    # Or manually test
    curl -H "Authorization: token $GITHUB_TOKEN" \
      https://api.github.com/user
    

  3. Check token hasn't expired:

  4. Go to GitHub Settings → Developer settings → Personal access tokens
  5. Verify token expiration date

  6. Verify token scopes:

    curl -H "Authorization: token $GITHUB_TOKEN" \
      -I https://api.github.com/user | grep X-OAuth-Scopes
    

  7. For GitHub Enterprise, verify API URL:

    curl -H "Authorization: token $GITHUB_TOKEN" \
      https://github.mycompany.com/api/v3/user
    

Permission Denied

Error: Resource not accessible by integration or 403 Forbidden

Solutions:

  1. For repository secrets, ensure token has repo scope:

    # Check token scopes
    gh auth status
    
    # Regenerate token with correct scopes
    # Go to GitHub Settings → Developer settings → Personal access tokens
    # Select: repo (full control)
    

  2. For environment secrets, ensure repository admin access:

  3. Environment secrets require admin access to the repository
  4. Check repository Settings → Manage access

  5. Test permissions:

    # Test repository access
    gh api repos/myorg/myrepo/actions/secrets
    

Secret Not Appearing in Workflows

Error: Secret is synced but not available in workflows

Solutions:

  1. Verify secret name (case-sensitive):

    # If secret name in SecretZero is: api_key
    # It becomes in GitHub: API_KEY (uppercase with underscores)
    
    # In workflow, use exact uppercase name:
    env:
      API_KEY: ${{ secrets.API_KEY }}  # Correct
      api_key: ${{ secrets.api_key }}  # Wrong - won't work
    

  2. For environment secrets, ensure workflow specifies environment:

    jobs:
      deploy:
        runs-on: ubuntu-latest
        environment: production  # Must specify environment
        steps:
          - name: Use environment secret
            run: echo ${{ secrets.DATABASE_PASSWORD }}
    

  3. Check secret in GitHub UI:

  4. Repository Settings → Secrets and variables → Actions
  5. Verify secret exists and name matches

  6. Workflow permissions:

    # Ensure workflow has secrets access
    permissions:
      secrets: read  # May be needed in some setups
    

Rate Limits

Error: API rate limit exceeded or 403 rate_limit_exceeded

Solutions:

  1. Check current rate limit:

    curl -H "Authorization: token $GITHUB_TOKEN" \
      https://api.github.com/rate_limit
    

  2. Authenticated requests have higher limits:

  3. Unauthenticated: 60 requests/hour
  4. Authenticated: 5,000 requests/hour
  5. GitHub Enterprise: Often higher limits

  6. Implement backoff strategy:

    # Space out secret syncs
    # Don't sync all repositories simultaneously
    

  7. Deploy to multiple repositories efficiently:

    # Batch secret deployments to minimize API calls
    # Use variables to manage multiple repositories
    

  8. Cache SecretZero operations:

    # Use --dry-run to test without API calls
    secretzero sync --dry-run -f Secretfile.yml
    
    # Sync only changed secrets
    secretzero sync -f Secretfile.yml --incremental
    

Secret Encryption Failed

Error: Failed to encrypt secret or Public key not found

Solutions:

  1. SecretZero automatically handles encryption, but if issues occur:
  2. Verify repository exists and is accessible
  3. Check repository settings allow Actions

  4. Test repository access:

    gh api repos/myorg/myrepo
    

  5. Ensure Actions is enabled:

  6. Repository Settings → Actions → General
  7. Actions permissions: Allow all actions

Environment Not Found

Error: Environment does not exist

Solutions:

  1. Create environment first:
  2. Repository Settings → Environments → New environment
  3. Enter environment name (e.g., "production")

  4. Environment names are case-sensitive:

    # Must match exactly
    config:
      environment: production  # Must match GitHub UI
    

  5. Create environments via GitHub CLI:

    # Create production environment
    gh api repos/myorg/myrepo/environments/production -X PUT
    

  6. Verify environment exists:

    gh api repos/myorg/myrepo/environments
    

GitHub Enterprise Support

Configuration

providers:
  github_enterprise:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_ENTERPRISE_TOKEN}
        api_url: https://github.mycompany.com/api/v3

secrets:
  - name: api_key
    kind: random_string
    config:
      length: 32
    targets:
      - provider: github_enterprise
        kind: github_secret
        config:
          owner: myorg
          repo: myrepo

API URL Format

  • GitHub Cloud: https://api.github.com (default)
  • GitHub Enterprise Server: https://github.mycompany.com/api/v3
  • GitHub AE: https://github.ae/api/v3

Testing Enterprise Connection

# Test API connectivity
curl -H "Authorization: token $GITHUB_ENTERPRISE_TOKEN" \
  https://github.mycompany.com/api/v3/user

# Test with SecretZero
secretzero test -f Secretfile.yml

Enterprise-Specific Considerations

  1. SSL Certificates:
  2. Ensure valid SSL certificate
  3. For self-signed certificates, configure trust

  4. Network Access:

  5. Verify network connectivity to enterprise server
  6. Check firewall rules and proxy settings

  7. API Version:

  8. Use /api/v3 endpoint for GitHub Enterprise Server
  9. Verify API version compatibility

  10. Rate Limits:

  11. Enterprise may have different rate limits
  12. Contact GitHub Enterprise admin for limits

Cost and Limits

GitHub Actions Usage

  • Public repositories: Unlimited Actions minutes
  • Private repositories: Free tier includes minutes (varies by plan)
  • Secrets: No additional cost, included in GitHub plan

Limits

  • Repository secrets: Up to 100 secrets per repository
  • Environment secrets: Up to 100 secrets per environment
  • Secret size: Maximum 64 KB per secret
  • Secret name: Maximum 512 characters

Best Practices for Limits

  1. Combine multiple values in JSON secrets when appropriate
  2. Use environment variables for non-sensitive configuration
  3. Implement secret cleanup for unused secrets
  4. Plan secret naming conventions to stay within limits

See Also