暗号化されたシークレットを作成する
GitHub Actions ワークフローでは、多くの場合、API キー、パスワード、証明書、トークンなどの機密情報にアクセスする必要があります。 GitHub には、暗号化されたシークレットが用意されており、コードやワークフロー ファイルに公開することなく、この機密データを安全に格納してアクセスできます。
GitHub シークレットについて
GitHub シークレットは暗号化された環境変数であり、GitHub 組織内のさまざまなレベルで作成できます。 作成されると、シークレットは暗号化され、承認されたコンテキストでのワークフローの実行中にのみ復号化できます。
GitHub シークレットの主な特性:
- 暗号化されたストレージ: すべてのシークレットは業界標準の暗号化を使用して暗号化されます
- アクセスの制御: 承認されたワークフローのみがシークレットにアクセスできます
- ログでマスク: シークレット値はワークフロー ログで自動的にマスクされます
- 不変: 作成されると、シークレット値を表示できず、置き換えるだけです
シークレットのスコープと階層
リポジトリ レベルのシークレット
リポジトリ シークレットは、その特定のリポジトリ内のワークフローでのみ使用できます。
# Using repository secret in workflow
name: Deploy Application
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to production
env:
API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_CONNECTION_STRING }}
run: |
echo "Deploying with API key starting with: ${API_KEY:0:8}..."
./deploy.sh
Organization レベルのシークレット
組織のシークレットは、アクセスが制御された複数のリポジトリ間で共有できます。
# Organization secret with repository access control
name: Shared CI Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run integration tests
env:
# This secret is available to authorized repositories
SHARED_TEST_API_KEY: ${{ secrets.INTEGRATION_TEST_API_KEY }}
run: |
npm test -- --api-key="$SHARED_TEST_API_KEY"
環境レベルのシークレット
環境シークレットは、デプロイ環境をきめ細かく制御します。
name: Multi-Environment Deploy
on:
push:
branches: [main, develop]
jobs:
deploy-staging:
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
environment: staging
steps:
- name: Deploy to staging
env:
# Environment-specific secrets
DEPLOYMENT_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}
API_ENDPOINT: ${{ secrets.STAGING_API_URL }}
run: ./deploy.sh staging
deploy-production:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to production
env:
DEPLOYMENT_KEY: ${{ secrets.PRODUCTION_DEPLOY_KEY }}
API_ENDPOINT: ${{ secrets.PRODUCTION_API_URL }}
run: ./deploy.sh production
シークレットの作成と管理
リポジトリ シークレットのセットアップ
リポジトリの設定に移動します。
- GitHub でリポジトリに移動する
- [ 設定] タブを クリックする
- シークレットと変数の選択>Actions
新しいリポジトリ シークレットを作成します。
Name: PRODUCTION_API_KEY Value: your-actual-api-key-valueワークフローでの使用:
env: API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
組織のシークレット管理
# Example of organization secret usage with access policies
name: Organization-wide CI
on: [push]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Security vulnerability scan
env:
# Organization secret with controlled repository access
SECURITY_SCAN_TOKEN: ${{ secrets.ORG_SECURITY_SCAN_TOKEN }}
run: |
security-scanner --token="$SECURITY_SCAN_TOKEN" .
組織のシークレット アクセス ポリシー:
- すべてのリポジトリ: 組織内のすべてのリポジトリで使用可能
- プライベート リポジトリ: プライベート リポジトリでのみ使用できます
- 選択したリポジトリ: 特に選択したリポジトリでのみ使用できます
保護規則を使用した環境シークレット
name: Protected Production Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://myapp.production.com
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Deploy with environment protection
env:
# Protected by environment rules (approvals, wait timers)
PROD_DEPLOY_TOKEN: ${{ secrets.PRODUCTION_DEPLOY_TOKEN }}
PROD_DB_PASSWORD: ${{ secrets.PRODUCTION_DATABASE_PASSWORD }}
run: |
echo "Deploying to production environment..."
./scripts/deploy-production.sh
シークレットのセキュリティのベスト プラクティス
シークレットの名前付け規則
# Good: Clear, descriptive names
secrets:
PRODUCTION_API_KEY
STAGING_DATABASE_URL
AWS_ACCESS_KEY_ID
AZURE_CLIENT_SECRET
DOCKER_REGISTRY_TOKEN
# Avoid: Vague or generic names
secrets:
KEY
PASSWORD
TOKEN
SECRET
最小特権の原則
# Good: Specific secrets for specific purposes
name: Database Migration
jobs:
migrate:
runs-on: ubuntu-latest
steps:
- name: Run database migration
env:
# Read-only database connection for migrations
DB_MIGRATION_URL: ${{ secrets.DB_MIGRATION_CONNECTION }}
run: |
migrate up --database-url="$DB_MIGRATION_URL"
backup:
runs-on: ubuntu-latest
steps:
- name: Create database backup
env:
# Backup-specific credentials with limited scope
BACKUP_ACCESS_KEY: ${{ secrets.DB_BACKUP_ACCESS_KEY }}
run: |
backup-db --credentials="$BACKUP_ACCESS_KEY"
シークレットローテーションとライフサイクル管理
name: Secret Health Check
on:
schedule:
- cron: "0 6 * * 1" # Weekly on Monday at 6 AM
jobs:
check-secret-health:
runs-on: ubuntu-latest
steps:
- name: Test API key validity
env:
API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
run: |
# Test if API key is still valid
response=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $API_KEY" \
https://api.example.com/health)
if [ "$response" != "200" ]; then
echo "API key may be expired or invalid"
# Create issue or notify team
gh issue create --title "API Key Health Check Failed" \
--body "The production API key failed health check. Response code: $response"
else
echo "API key is healthy"
fi
条件付きシークレットの使用
name: Flexible Secret Usage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run tests
env:
# Use different secrets based on event type
API_KEY: ${{ github.event_name == 'push' && secrets.INTEGRATION_API_KEY || secrets.TESTING_API_KEY }}
DATABASE_URL: ${{ github.ref == 'refs/heads/main' && secrets.PROD_DB_URL || secrets.TEST_DB_URL }}
run: |
echo "Running tests with appropriate credentials..."
npm test
高度なシークレット パターン
複数値シークレット (JSON 構成)
name: Complex Configuration
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Parse complex secret
env:
# Store complex configuration as JSON in secret
AWS_CONFIG: ${{ secrets.AWS_DEPLOYMENT_CONFIG }}
run: |
# Parse JSON secret
echo "$AWS_CONFIG" | jq -r '.access_key_id' > /tmp/aws_key
echo "$AWS_CONFIG" | jq -r '.secret_access_key' > /tmp/aws_secret
echo "$AWS_CONFIG" | jq -r '.region' > /tmp/aws_region
# Configure AWS CLI
aws configure set aws_access_key_id "$(cat /tmp/aws_key)"
aws configure set aws_secret_access_key "$(cat /tmp/aws_secret)"
aws configure set default.region "$(cat /tmp/aws_region)"
# Clean up temporary files
rm -f /tmp/aws_*
秘密の継承と合成
name: Composed Secrets
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Build connection string
env:
DB_HOST: ${{ secrets.DATABASE_HOST }}
DB_USER: ${{ secrets.DATABASE_USER }}
DB_PASS: ${{ secrets.DATABASE_PASSWORD }}
DB_NAME: ${{ secrets.DATABASE_NAME }}
run: |
# Compose connection string from individual secrets
CONNECTION_STRING="postgresql://$DB_USER:$DB_PASS@$DB_HOST:5432/$DB_NAME"
# Use composed string (never log it)
echo "Connecting to database..."
psql "$CONNECTION_STRING" -c "SELECT version();"
シークレットの検証とテスト
name: Secret Validation
jobs:
validate-secrets:
runs-on: ubuntu-latest
steps:
- name: Validate API credentials
env:
API_KEY: ${{ secrets.API_KEY }}
API_SECRET: ${{ secrets.API_SECRET }}
run: |
# Test API credentials without exposing values
if [ -z "$API_KEY" ] || [ -z "$API_SECRET" ]; then
echo "Missing required API credentials"
exit 1
fi
# Test key format (without revealing the key)
if [[ ${#API_KEY} -lt 32 ]]; then
echo "API key appears to be invalid (too short)"
exit 1
fi
# Test authentication
response=$(curl -s -w "%{http_code}" -o /dev/null \
-H "Authorization: Bearer $API_KEY" \
https://api.example.com/auth/test)
if [ "$response" = "200" ]; then
echo "API credentials validated successfully"
else
echo "API credential validation failed (HTTP $response)"
exit 1
fi
一般的な落とし穴とセキュリティに関する考慮事項
秘密の露出の回避
# DON'T: Never echo or log secrets directly
- name: Bad secret usage
env:
API_KEY: ${{ secrets.API_KEY }}
run: |
echo "Using API key: $API_KEY" # This will expose the secret!
# DO: Use secrets safely without exposure
- name: Safe secret usage
env:
API_KEY: ${{ secrets.API_KEY }}
run: |
# Use the secret without logging it
curl -H "Authorization: Bearer $API_KEY" https://api.example.com/data
echo "API request completed successfully"
適切なエラー処理
- name: Secure error handling
env:
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
run: |
# Set error handling to avoid secret leaks
set +x # Disable command echoing
if ! psql "postgresql://user:$DATABASE_PASSWORD@host/db" -c "SELECT 1"; then
# Log error without exposing secret
echo "Database connection failed"
exit 1
fi
echo "Database connection successful"
シークレット スコープの管理
# Good: Limit secret scope to specific steps
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# No secrets available here
- name: Deploy application
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # Secret only in this step
run: |
./deploy.sh
- name: Run post-deploy tests
# No secrets available here
run: |
./test.sh
CI/CD パイプラインのセキュリティを維持するには、適切なシークレット管理が重要です。 常に最小限の特権の原則に従い、わかりやすい名前付けを使用し、適切な検証を実装して、強力な自動化機能を有効にしながらシークレットをセキュリティで保護します。