security2023-10-22·7 min·337/348

GitHub Actions Secrets 관리 방법

GitHub Actions에서 Secrets를 안전하게 관리하고 사용하는 방법을 알아봅니다.

GitHub Actions Secrets 관리 방법

GitHub Actions에서 Secrets는 민감한 정보(API 키, 비밀번호 등)를 안전하게 저장하고 워크플로우에서 사용할 수 있게 해줍니다.

Environment

$ gh --version
gh version 2.40.1 (2024-01-11)

$ gh auth status
github.com
  ✓ Logged in to github.com account joel-park (keyring)
  - Active account: true

Problem: Secrets가 로그에 노출됨

# BAD PRACTICE - Never do this!
steps:
  - name: Debug secrets
    run: |
      echo "API Key: $API_KEY"  # Logged in plain text!
    env:
      API_KEY: ${{ secrets.API_KEY }}

또는 Secrets를 제대로 사용하지 않아 빈 값이 전달됨:

# Common mistake
steps:
  - name: Deploy
    run: |
      echo $API_KEY  # Empty because env var name is wrong
    env:
      API_KEY: ${{ secrets.MISSING_SECRET }}  # Returns empty

Analysis: Secrets 동작 원리

# Secrets are encrypted at rest
# They are decrypted only during workflow run
# They are masked in logs (***)
# They cannot be downloaded from Actions UI

# Environment-level secrets
# Organization-level secrets
# Repository-level secrets
# Check existing secrets
$ gh secret list

# List organization secrets
$ gh api orgs/{org}/actions/secrets

# List repository secrets
$ gh api repos/{owner}/{repo}/actions/secrets

Solution: Secrets 안전한 관리 방법

방법 1: 기본 Secrets 사용

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

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to production
        run: |
          ./deploy.sh
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
      
      # This will be masked in logs
      - name: Debug (safe)
        run: |
          echo "Deploying to $TARGET_ENV"
        env:
          TARGET_ENV: ${{ secrets.TARGET_ENV }}

방법 2: 환경별 Secrets (Environments)

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

on:
  push:
    branches: [main]

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - run: echo "Deploying to staging"
        env:
          API_URL: ${{ secrets.STAGING_API_URL }}
  
  deploy-production:
    runs-on: ubuntu-latest
    environment: production
    needs: deploy-staging
    steps:
      - run: echo "Deploying to production"
        env:
          API_URL: ${{ secrets.PRODUCTION_API_URL }}

방법 3: Organization Secrets

# Shared across multiple repositories
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: |
          curl -H "Authorization: Bearer ${{ secrets.SHARED_API_KEY }}" \
               https://api.example.com/deploy
# Set organization secret
$ gh secret set SHARED_API_KEY \
  --org myorg \
  --visibility selected \
  --repos "repo1,repo2,repo3" \
  --body "your-api-key"

방법 4: Encrypted Secrets 사용

steps:
  - name: Use encrypted secret
    run: |
      echo "Secret value is available but not logged"
      echo $SECRET_VALUE | wc -c  # Show length only
    env:
      SECRET_VALUE: ${{ secrets.MY_SECRET }}
  
  # Never do this
  # - run: echo $MY_SECRET  # Security risk!

방법 5: OIDC for Cloud Providers

# No long-lived secrets needed
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/GitHubActions
          aws-region: us-east-1
      
      - run: aws s3 sync ./dist s3://my-bucket

Security Best Practices

# 1. Limit permissions
permissions:
  contents: read
  actions: read

# 2. Use environment protection rules
environment:
  name: production
  protection-rules:
    - type: required_reviewers
      review_count: 2

# 3. Audit secret access
steps:
  - name: Log secret usage (metadata only)
    run: |
      echo "Secret used at $(date)" >> $GITHUB_STEP_SUMMARY

Lessons Learned

  1. 로그 주의: Secrets가 로그에 노출되지 않도록 주의하세요. GitHub는 자동으로 마스킹하지만, 완전하지 않습니다.

  2. Environment 활용: 환경별 Secrets을 사용하면 프로덕션 Secrets이 스테이징에서 사용되는 것을 방지할 수 있습니다.

  3. OIDC 전환: AWS, GCP 등에서 장기 사용 자격증명 대신 OIDC를 사용하면 더 안전합니다.

  4. 최소 권한 원칙: Secrets에 접근할 수 있는 워크플로우의 권한을 최소화하세요.

  5. 정기 교체: Secrets는 정기적으로 교체하여 유출 시 피해를 최소화하세요.


This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.