跳至主要内容

在 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 端点”。

创建仓库密钥

要在 GitHub 上为个人帐户仓库创建密钥或变量,您必须是仓库所有者。要在 GitHub 上为组织仓库创建密钥或变量,您必须具有 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外,当工作流从fork的仓库触发时,不会将密钥传递给运行器。
  • 密钥不会自动传递给可重用的工作流。更多信息,请参阅“重用工作流”。

要向操作提供密钥作为输入或环境变量,可以使用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: bashbash 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 的工作流命令

密钥的删除由您的工作流运行器执行。这意味着只有在作业中使用并可供运行器访问的密钥才会被删除。如果未删除的密钥被发送到工作流运行日志,则应删除日志并轮换密钥。有关删除日志的信息,请参阅使用工作流运行日志