跳至主要内容

在 GitHub Actions 中使用机密

机密允许您在您的组织、存储库或存储库环境中存储敏感信息。

关于机密

机密是在组织、存储库或存储库环境中创建的变量。您创建的机密可在 GitHub Actions 工作流中使用。只有当您在工作流中明确包含机密时,GitHub Actions 才能读取该机密。

对于存储在组织级别的密钥,您可以使用访问策略来控制哪些仓库可以使用组织密钥。组织级密钥允许您在多个仓库之间共享密钥,从而减少创建重复密钥的需要。在一个位置更新组织密钥还可以确保更改在使用该密钥的所有仓库工作流中生效。

对于存储在环境级别的密钥,您可以启用必需的审阅者来控制对密钥的访问。在必需的批准者授予批准之前,工作流作业无法访问环境密钥。

注意

如果您的 GitHub Actions 工作流需要访问支持 OpenID Connect (OIDC) 的云提供商的资源,您可以配置您的工作流以直接向云提供商进行身份验证。这将允许您停止将这些凭据存储为长期密钥,并提供其他安全优势。有关更多信息,请参阅“使用 OpenID Connect 加强安全性的简介

密钥命名

以下规则适用于密钥名称

  • 名称只能包含字母数字字符 ([a-z][A-Z][0-9]) 或下划线 (_)。不允许使用空格。

  • 名称不得以 GITHUB_ 前缀开头。

  • 名称不得以数字开头。

  • 名称不区分大小写。

  • 名称在其创建的级别上必须唯一。

    例如,在环境级别创建的密钥必须在该环境中具有唯一的名称,在仓库级别创建的密钥必须在该仓库中具有唯一的名称,在组织级别创建的密钥必须在该级别具有唯一的名称。

    如果在多个级别存在具有相同名称的密钥,则最低级别的密钥优先。例如,如果组织级密钥与仓库级密钥具有相同的名称,则仓库级密钥优先。同样,如果组织、仓库和环境都具有相同名称的密钥,则环境级密钥优先。

为了帮助确保 GitHub 在日志中删除您的密钥,请避免使用结构化数据作为密钥的值。例如,避免创建包含 JSON 或编码 Git blob 的密钥。

访问您的密钥

要使密钥可供操作使用,您必须在工作流文件中将密钥设置为输入或环境变量。查看操作的 README 文件以了解操作期望的输入和环境变量。有关更多信息,请参阅“GitHub Actions 的工作流语法”。

如果您有权编辑文件,则可以在工作流文件中使用和读取密钥。有关更多信息,请参阅“GitHub 上的访问权限”。

警告

如果作业中使用了密钥,GitHub 会自动删除打印到日志中的密钥。您应该避免故意将密钥打印到日志中。

组织和仓库密钥在工作流运行排队时读取,环境密钥在引用环境的作业开始时读取。

您还可以使用 REST API 管理密钥。有关更多信息,请参阅“GitHub Actions 密钥的 REST API 端点”。

限制凭据权限

在生成凭据时,我们建议您授予尽可能少的权限。例如,不要使用个人凭据,而是使用部署密钥或服务帐户。如果只需要读取权限,请考虑授予读取权限,并尽可能限制访问。

在生成个人访问令牌(经典)时,请选择最少的必要范围。在生成细粒度个人访问令牌时,请选择所需的最低权限和仓库访问权限。

不要使用个人访问令牌,而是考虑使用 GitHub App,它使用细粒度权限和短期令牌,类似于细粒度个人访问令牌。与个人访问令牌不同,GitHub App 不与用户绑定,因此即使安装该 App 的用户离开您的组织,工作流也将继续工作。有关更多信息,请参阅“在 GitHub Actions 工作流中使用 GitHub App 进行身份验证的 API 请求”。

注意

具有仓库协作者访问权限的用户可以使用 REST API 管理该仓库的密钥,而具有组织管理员访问权限的用户可以使用 REST API 管理该组织的密钥。有关更多信息,请参阅“GitHub Actions 密钥的 REST API 端点”。

为仓库创建密钥

要为个人帐户仓库创建密钥或变量,您必须是仓库所有者。要为组织仓库创建密钥或变量,您必须具有 admin 访问权限。最后,要通过 REST API 为个人帐户仓库或组织仓库创建密钥或变量,您必须具有协作者访问权限。

  1. 在 GitHub 上,导航到仓库的主页。

  2. 在您的仓库名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置

    Screenshot of a repository header showing the tabs. The "Settings" tab is highlighted by a dark orange outline.

  3. 在侧边栏的“安全”部分,选择 密钥和变量,然后单击操作

  4. 单击密钥选项卡。

    Screenshot of the "Actions secrets and variables" page. The "Secrets" tab is outlined in dark orange.

  5. 单击新建仓库密钥

  6. 名称字段中,键入密钥的名称。

  7. 密钥字段中,输入密钥的值。

  8. 单击添加密钥

如果您的仓库具有环境密钥或可以访问父组织中的密钥,则这些密钥也会在此页面上列出。

要了解有关 GitHub CLI 的更多信息,请参阅“关于 GitHub CLI”。

要添加仓库密钥,请使用 gh secret set 子命令。将 secret-name 替换为密钥的名称。

gh secret set SECRET_NAME

CLI 将提示您输入密钥值。或者,您可以从文件中读取密钥的值。

gh secret set SECRET_NAME < secret.txt

要列出仓库的所有密钥,请使用 gh secret list 子命令。

为环境创建密钥

要为个人帐户仓库中的环境创建密钥或变量,您必须是仓库所有者。要为组织仓库中的环境创建密钥或变量,您必须具有 admin 访问权限。有关环境的更多信息,请参阅“管理部署环境”。

  1. 在 GitHub 上,导航到仓库的主页。

  2. 在您的仓库名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置

    Screenshot of a repository header showing the tabs. The "Settings" tab is highlighted by a dark orange outline.

  3. 在左侧边栏中,单击环境

  4. 单击要向其添加密钥的环境。

  5. 环境密钥下,单击添加密钥

  6. 名称输入框中键入密钥的名称。

  7. 输入密钥的值。

  8. 单击添加密钥

要为环境添加密钥,请使用 gh secret set 子命令,并使用 --env-e 标志,后跟环境名称。

gh secret set --env ENV_NAME SECRET_NAME

要列出环境的所有密钥,请使用 gh secret list 子命令,并使用 --env-e 标志,后跟环境名称。

gh secret list --env ENV_NAME

为组织创建密钥

注意

对于 GitHub Free,组织级密钥和变量无法被私有仓库访问。有关升级 GitHub 订阅的更多信息,请参阅“升级帐户的计划”。

在组织中创建密钥或变量时,您可以使用策略来限制仓库的访问权限。例如,您可以授予所有仓库的访问权限,或仅限制私有仓库或指定仓库列表的访问权限。

组织所有者可以在组织级别创建密钥或变量。

  1. 在 GitHub 上,导航到组织的主页。

  2. 在您的组织名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置

    Screenshot of the tabs in an organization's profile. The "Settings" tab is outlined in dark orange.

  3. 在侧边栏的“安全”部分,选择 密钥和变量,然后单击操作

  4. 单击密钥选项卡。

    Screenshot of the "Actions secrets and variables" page. The "Secrets" tab is outlined in dark orange.

  5. 单击新建组织密钥

  6. 名称输入框中键入密钥的名称。

  7. 输入密钥的

  8. 仓库访问下拉列表中选择访问策略。

  9. 单击添加密钥

注意

默认情况下,GitHub CLI 使用 reporead:org 范围进行身份验证。要管理组织密钥,您还必须授权 admin:org 范围。

gh auth login --scopes "admin:org"

要为组织添加密钥,请使用 gh secret set 子命令,并使用 --org-o 标志,后跟组织名称。

gh secret set --org ORG_NAME SECRET_NAME

默认情况下,密钥仅对私有仓库可用。要指定密钥应对组织内的所有仓库可用,请使用 --visibility-v 标志。

gh secret set --org ORG_NAME SECRET_NAME --visibility all

要指定机密对组织内的选定仓库可用,请使用--repos-r标志。

gh secret set --org ORG_NAME SECRET_NAME --repos REPO-NAME-1, REPO-NAME-2

要列出组织的所有机密,请使用gh secret list子命令,并使用--org-o标志,后跟组织名称。

gh secret list --org ORG_NAME

查看对组织级机密的访问权限

您可以检查组织中应用于某个机密的哪些访问策略。

  1. 在 GitHub 上,导航到组织的主页。

  2. 在您的组织名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置

    Screenshot of the tabs in an organization's profile. The "Settings" tab is outlined in dark orange.

  3. 在侧边栏的“安全”部分,选择 密钥和变量,然后单击操作

  4. 机密列表包含任何已配置的权限和策略。有关每个机密已配置权限的更多详细信息,请单击**更新**。

在工作流中使用机密

注意

  • GITHUB_TOKEN外,当从派生仓库触发工作流时,不会将机密传递给运行器。
  • 机密不会自动传递给可重用的工作流。有关更多信息,请参阅“重用工作流”。

要向操作提供机密作为输入或环境变量,您可以使用secrets上下文访问在仓库中创建的机密。有关更多信息,请参阅“访问有关工作流运行的上下文信息”和“GitHub Actions 的工作流语法”。

steps:
  - name: Hello world action
    with: # Set the secret as an input
      super_secret: ${{ secrets.SuperSecret }}
    env: # Or as an environment variable
      super_secret: ${{ secrets.SuperSecret }}

无法在if:条件语句中直接引用机密。相反,请考虑将机密设置为作业级环境变量,然后引用环境变量以有条件地运行作业中的步骤。有关更多信息,请参阅“访问有关工作流运行的上下文信息”和jobs.<job_id>.steps[*].if

如果未设置机密,则引用该机密的表达式的返回值(例如,示例中的${{ secrets.SuperSecret }})将为空字符串。

尽可能避免从命令行在进程之间传递机密。命令行进程可能对其他用户可见(使用ps命令)或被安全审计事件捕获。为了帮助保护机密,请考虑使用环境变量、STDIN或目标进程支持的其他机制。

如果必须在命令行中传递机密,则将其括在正确的引用规则内。机密通常包含可能意外影响 shell 的特殊字符。要转义这些特殊字符,请使用环境变量进行引用。例如

使用 Bash 的示例

steps:
  - shell: bash
    env:
      SUPER_SECRET: ${{ secrets.SuperSecret }}
    run: |
      example-command "$SUPER_SECRET"

使用 PowerShell 的示例

steps:
  - shell: pwsh
    env:
      SUPER_SECRET: ${{ secrets.SuperSecret }}
    run: |
      example-command "$env:SUPER_SECRET"

使用 Cmd.exe 的示例

steps:
  - shell: cmd
    env:
      SUPER_SECRET: ${{ secrets.SuperSecret }}
    run: |
      example-command "%SUPER_SECRET%"

机密的限制

您可以存储最多 1,000 个组织机密、100 个仓库机密和 100 个环境机密。

在仓库中创建的工作流可以访问以下数量的机密

  • 所有 100 个仓库机密。
  • 如果仓库被分配了访问超过 100 个组织机密的权限,则工作流只能使用前 100 个组织机密(按机密名称字母顺序排序)。
  • 所有 100 个环境机密。

机密大小限制为 48 KB。要存储更大的机密,请参阅下面“存储大型机密”中的解决方法。

存储大型机密

要使用大于 48 KB 的机密,您可以使用一种解决方法,将机密存储在仓库中,并将解密密码短语作为机密保存在 GitHub 上。例如,您可以在将加密文件检入 GitHub 上的仓库之前,使用gpg在本地加密包含机密的文 件。有关更多信息,请参阅“gpg 手册页”。

警告

请注意,您的机密在工作流运行时不会被打印出来。使用此解决方法时,GitHub 不会屏蔽日志中打印的机密。

  1. 从终端运行以下命令,使用gpg和 AES256 密码算法加密包含机密的文 件。在此示例中,my_secret.json是包含机密的文 件。

    gpg --symmetric --cipher-algo AES256 my_secret.json
    
  2. 系统将提示您输入密码短语。请记住密码短语,因为您需要在 GitHub 上创建一个新的机密,该机密使用密码短语作为值。

  3. 创建一个包含密码短语的新机密。例如,创建一个名为LARGE_SECRET_PASSPHRASE的新机密,并将机密的值设置为上一步中使用的密码短语。

  4. 将加密的文件复制到仓库中的路径并提交。在此示例中,加密的文件是my_secret.json.gpg

    警告

    确保复制以.gpg文件扩展名结尾的加密my_secret.json.gpg文件,而**不是**未加密的my_secret.json文件。

    git add my_secret.json.gpg
    git commit -m "Add new secret JSON file"
    
  5. 在仓库中创建一个 shell 脚本以解密机密文件。在此示例中,脚本名为decrypt_secret.sh

    Shell
    #!/bin/sh
    
    # Decrypt the file
    mkdir $HOME/secrets
    # --batch to prevent interactive command
    # --yes to assume "yes" for questions
    gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" \
    --output $HOME/secrets/my_secret.json my_secret.json.gpg
    
  6. 在将 shell 脚本检入仓库之前,请确保它是可执行的。

    chmod +x decrypt_secret.sh
    git add decrypt_secret.sh
    git commit -m "Add new decryption script"
    git push
    
  7. 在您的 GitHub Actions 工作流中,使用step调用 shell 脚本并解密机密。要在工作流运行的环境中拥有仓库的副本,您需要使用actions/checkout操作。使用相对于仓库根目录的run命令引用 shell 脚本。

    name: Workflows with large secrets
    
    on: push
    
    jobs:
      my-job:
        name: My Job
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - name: Decrypt large secret
            run: ./decrypt_secret.sh
            env:
              LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}
          # This command is just an example to show your secret being printed
          # Ensure you remove any print statements of your secrets. GitHub does
          # not hide secrets that use this workaround.
          - name: Test printing your secret (Remove this step in production)
            run: cat $HOME/secrets/my_secret.json
    

将 Base64 二进制 Blob 存储为机密

您可以使用 Base64 编码将小型二进制 Blob 存储为机密。然后,您可以在工作流中引用该机密,并对其进行解码以在运行器上使用。有关大小限制,请参阅“在 GitHub Actions 中使用机密”。

注意

请注意,Base64 仅将二进制数据转换为文本,不能替代实际的加密。

  1. 使用base64将文件编码为 Base64 字符串。例如

    在 macOS 上,您可以运行

    base64 -i cert.der -o cert.base64
    

    在 Linux 上,您可以运行

    base64 -w 0 cert.der > cert.base64
    
  2. 创建一个包含 Base64 字符串的机密。例如

    $ gh secret set CERTIFICATE_BASE64 < cert.base64
    ✓ Set secret CERTIFICATE_BASE64 for octocat/octorepo
    
  3. 要从运行器访问 Base64 字符串,请将机密传递到base64 --decode。例如

    name: Retrieve Base64 secret
    on:
      push:
        branches: [ octo-branch ]
    jobs:
      decode-secret:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - name: Retrieve the secret and decode it to a file
            env:
              CERTIFICATE_BASE64: ${{ secrets.CERTIFICATE_BASE64 }}
            run: |
              echo $CERTIFICATE_BASE64 | base64 --decode > cert.der
          - name: Show certificate information
            run: |
              openssl x509 -in cert.der -inform DER -text -noout
    

注意

使用其他 shell 可能需要不同的命令才能将机密解码到文件。在 Windows 运行器上,我们建议使用带有shell: bash的 bash shell以使用上面run步骤中的命令。

从工作流运行日志中屏蔽机密

GitHub Actions 会自动屏蔽打印到工作流日志中的所有 GitHub 机密的内容。

GitHub Actions 还会屏蔽识别为敏感但未存储为机密的信息。目前 GitHub 支持以下内容

  • 32 字节和 64 字节 Azure 密钥
  • Azure AD 客户端应用密码
  • Azure 缓存密钥
  • Azure 容器注册表密钥
  • Azure 函数主机密钥
  • Azure 搜索密钥
  • 数据库连接字符串
  • HTTP Bearer 令牌标头
  • JWT
  • NPM 作者令牌
  • NuGet API 密钥
  • v1 GitHub 安装令牌
  • v2 GitHub 安装令牌(ghpghoghughsghr
  • v2 GitHub PAT

注意

如果您希望自动屏蔽其他类型的敏感信息,请在我们的社区讨论中与我们联系。

作为最佳实践习惯,您应该使用::add-mask::VALUE屏蔽所有不是 GitHub 机密的敏感信息。这会导致该值被视为机密,并从日志中屏蔽。有关屏蔽数据的更多信息,请参阅“GitHub Actions 的工作流命令”。

机密的屏蔽由您的工作流运行器执行。这意味着,只有当机密在作业中使用且运行器可以访问时,才会对其进行屏蔽。如果未屏蔽的机密发送到工作流运行日志,则应删除日志并轮换机密。有关删除日志的信息,请参阅“使用工作流运行日志”。