Skip to content
返回质量保障

密钥管理

存储、轮换和交付密钥(API key、数据库密码、签名密钥)而不泄露。

为什么

泄露的数据库密码或 API key 是云账户接管最常见原因,泄露几乎总通过当时认为方便的向量: 提交到 git 的 .env、为快速测试硬编码的密钥、打印环境的 CI 日志、结对编程时 Slack 分享的 key。密钥管理关于让安全路径成为容易路径——密钥管理器(Vault、AWS Secrets Manager、Doppler)运行时注入密钥,开发者永不碰原始密钥永无理由提交它们。泄露代价灾难性(账户接管、数据泄露、合规违规),预防代价是几小时设置永远回本。

何时使用

第一个密钥存在前就设好密钥管理器——补建痛苦因密钥已散到 .env、CI 变量、Slack。任何泄露疑似时立即轮换所有密钥。

如何做

1. 选密钥管理器使其成唯一密钥源
   - 云: AWS Secrets Manager / Parameter Store、GCP Secret Manager、Azure Key Vault
   - 自托管: HashiCorp Vault、Doppler、Infisical
   - 管理器是唯一源;.env 仅本地开发且 gitignore

2. 运行时注入密钥,绝不烤进镜像或提交
   - 容器: 启动时从管理器读,设为进程环境变量
   - CI: 用 OIDC 联合假设角色取密钥,绝不存 CI 变量
   - 本地开发: .env.local(gitignore)或 doppler run -- npm run dev

3. 持续扫泄露密钥
   - 每次提交(pre-commit 钩子)和每个 PR 跑 gitleaks 或 TruffleHog
   - 启用 GitHub 密钥扫描 + push protection(提交前阻止落地)
   - git 历史中发现密钥立即轮换——别只删文件

4. 按计划轮换密钥和每次团队成员离职时
   - 数据库密码: 每 90 天;API key: 按提供者策略每 30-180 天
   - 员工离职: 24 小时内轮换他们有权的所有密钥
   - 管理器支持处自动化轮换(AWS RDS 自动轮换)

5. 审计访问且绝不记密钥
   - 记哈希或"***"非原始值;确保序列化器编辑密钥字段
   - 审计谁何时访问哪个密钥;异常访问模式告警

示例

# .github/workflows/ci.yml — OIDC 联合,CI 中无长寿密钥
name: CI
on: [pull_request]
permissions:
  id-token: write   # OIDC 需要
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123:role/ci-deploy
          aws-region: us-east-1
      - name: 运行时取密钥
        run: |
          export DB_PASSWORD=$(aws secretsmanager get-secret-value             --secret-id prod/db-password --query SecretString --output text)
          npm test
      # 数据库密码永不出现在 CI 日志、永不存为 GitHub secret,
      # 且由 AWS 每 90 天自动轮换。

# Pre-commit 钩子: 提交前阻止密钥
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks
        # 若此钩子触发,提交被阻止。若密钥曾提交过则轮换——
        # git 历史是永远的。

常见问题

  • ⚠把密钥存为 CI 提供者变量(GitHub Secrets)当安全——CI 变量打印时在日志可见、任何有仓库写权者可访问、不自动轮换,所以累积泄露。
  • ⚠把 .env 提交到 git"只为团队有本地配置"——文件含生产数据库密码,现永远在 git 历史,后续提交删文件不从历史移除。
  • ⚠为快速测试在源码硬编码 Stripe key 忘删——key 发布到生产,若是前端 key 则在公开 bundle 中,被扫 GitHub 或部署 JS 的攻击者发现。
  • ⚠员工离职不轮换密钥——离职工程师本地 .env 仍有数据库密码,离职后可访问生产,这是真实内部威胁场景。

最佳实践

  • ✓CI 中用 OIDC 联合使 CI 提供者处无长寿密钥——CI 作业通过短寿令牌假设云角色、从管理器取密钥、凭证分钟级过期。
  • ✓启用 push protection(GitHub、GitLab)使含识别密钥模式的提交落地前被阻止——在源头止泄露,不到历史。
  • ✓密钥管理器支持处自动化轮换(AWS RDS 自动轮换、Vault 动态密钥)——手动轮换会被忘,永不轮换的密钥是离泄露一步的密钥。
  • ✓把 git 历史中发现的任何密钥当已泄露立即轮换——删文件不从历史移除,密钥提交那一刻起须假定已泄露。