GitHub Actions 密钥管理 #

密钥(Secrets)用于安全存储敏感信息,如API密钥、访问令牌等。本节详细介绍密钥的配置和使用。

密钥概述 #

什么是密钥? #

密钥是加密存储的环境变量,用于:

  • 存储API密钥
  • 存储访问令牌
  • 存储密码
  • 存储证书

密钥特点 #

  • 加密存储
  • 在日志中自动掩码
  • 无法在UI中查看
  • 可以在工作流中使用

密钥作用域 #

作用域 描述
组织级 所有仓库可用
仓库级 当前仓库可用
环境级 特定环境可用

创建密钥 #

通过网页创建 #

仓库密钥 #

  1. 进入仓库设置
  2. 点击 “Secrets and variables” → “Actions”
  3. 点击 “New repository secret”
  4. 输入名称和值
  5. 点击 “Add secret”

组织密钥 #

  1. 进入组织设置
  2. 点击 “Secrets and variables” → “Actions”
  3. 点击 “New organization secret”
  4. 输入名称、值和仓库访问权限
  5. 点击 “Add secret”

环境密钥 #

  1. 进入仓库设置
  2. 点击 “Environments”
  3. 选择或创建环境
  4. 在 “Environment secrets” 添加密钥

通过API创建 #

bash
curl -X PUT \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/owner/repo/actions/secrets/MY_SECRET \
  -d '{
    "encrypted_value": "'$(echo -n "my-secret-value" | openssl enc -aes-256-cbc -pass pass:"$KEY" -base64)'",
    "key_id": "key-id"
  }'

通过GitHub CLI创建 #

bash
# 仓库密钥
gh secret set MY_SECRET --body "secret-value"

# 从文件读取
gh secret set MY_SECRET < secret.txt

# 组织密钥
gh secret set MY_SECRET --org my-org --repos "repo1,repo2"

# 环境密钥
gh secret set MY_SECRET --env production

使用密钥 #

基本用法 #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Use secret
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          echo "Using API key"
          curl -H "Authorization: Bearer $API_KEY" https://api.example.com

在Action中使用 #

yaml
steps:
  - uses: actions/checkout@v4
    with:
      token: ${{ secrets.GITHUB_TOKEN }}

  - uses: docker/login-action@v3
    with:
      username: ${{ secrets.DOCKER_USERNAME }}
      password: ${{ secrets.DOCKER_PASSWORD }}

在环境中使用 #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
        run: ./deploy.sh

GITHUB_TOKEN #

什么是GITHUB_TOKEN? #

GITHUB_TOKEN是每次工作流运行时自动创建的令牌,用于:

  • 访问GitHub API
  • 推送代码
  • 创建PR
  • 创建Release

使用GITHUB_TOKEN #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Create issue
        uses: actions/github-script@v7
        with:
          script: |
            await github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: 'Automated issue',
              body: 'Created by GitHub Actions'
            })

GITHUB_TOKEN权限 #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4

权限级别 #

权限 描述
contents 仓库内容读写
pull-requests PR读写
issues Issue读写
packages 包读写
deployments 部署读写
actions Actions读写

密钥继承 #

组织到仓库 #

yaml
# 组织密钥自动继承到仓库
jobs:
  deploy:
    steps:
      - env:
          ORG_SECRET: ${{ secrets.ORG_SECRET }}

环境密钥 #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - env:
          # 环境密钥优先
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}

密钥限制 #

数量限制 #

  • 每个仓库最多500个密钥
  • 每个组织最多1000个密钥

大小限制 #

  • 每个密钥最大64KB
  • 组织密钥最大64KB

命名规则 #

  • 只能包含字母、数字和下划线
  • 不能以GITHUB_开头
  • 不区分大小写

安全最佳实践 #

1. 使用最小权限 #

yaml
permissions:
  contents: read
  pull-requests: write

2. 使用环境保护 #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com

3. 不要打印密钥 #

yaml
# 错误
- run: echo ${{ secrets.API_KEY }}

# 正确
- env:
    API_KEY: ${{ secrets.API_KEY }}
  run: curl -H "Authorization: Bearer $API_KEY" https://api.example.com

4. 使用环境密钥保护生产环境 #

yaml
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - run: ./deploy.sh staging

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production
    steps:
      - run: ./deploy.sh production

5. 定期轮换密钥 #

bash
# 更新密钥
gh secret set API_KEY --body "new-api-key"

6. 使用OpenID Connect #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/myRole
          aws-region: us-east-1

密钥示例 #

Docker Hub登录 #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

NPM发布 #

yaml
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'
      
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

AWS部署 #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1

SSH部署 #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /app
            git pull
            npm install
            npm run build
            pm2 restart all

Slack通知 #

yaml
jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Send Slack notification
        uses: slackapi/slack-github-action@v1
        with:
          channel-id: 'C0123456789'
          slack-message: 'Deployment completed!'
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

密钥管理 #

列出密钥 #

bash
# 列出仓库密钥
gh secret list

# 列出组织密钥
gh secret list --org my-org

# 列出环境密钥
gh secret list --env production

删除密钥 #

bash
# 删除仓库密钥
gh secret delete MY_SECRET

# 删除组织密钥
gh secret delete MY_SECRET --org my-org

# 删除环境密钥
gh secret delete MY_SECRET --env production

更新密钥 #

bash
# 更新密钥值
gh secret set MY_SECRET --body "new-value"

审计密钥使用 #

查看审计日志 #

  1. 进入组织或仓库设置
  2. 点击 “Audit log”
  3. 筛选 “secret” 相关事件

密钥使用事件 #

事件 描述
secret.created 密钥创建
secret.updated 密钥更新
secret.deleted 密钥删除

常见问题 #

Q: 密钥可以在fork的仓库中使用吗? #

不可以。Fork的仓库无法访问原仓库的密钥。

Q: 如何在PR中使用密钥? #

来自fork的PR无法访问密钥。可以使用 pull_request_target 事件,但需要谨慎使用。

Q: 密钥值可以更新吗? #

可以。更新密钥后,新的工作流运行会使用新值。

Q: 如何调试密钥问题? #

使用 ::add-mask:: 掩码输出:

yaml
steps:
  - run: |
      echo "::add-mask::${{ secrets.MY_SECRET }}"
      echo "Secret is set"

下一步学习 #

小结 #

  • 密钥用于安全存储敏感信息
  • 支持组织、仓库和环境三个级别
  • GITHUB_TOKEN自动创建,用于API访问
  • 使用最小权限原则
  • 使用环境保护生产环境
  • 定期轮换密钥
  • 不要在日志中打印密钥
最后更新:2026-03-28