跳至主要内容

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

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

为仓库创建密钥

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

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

  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.com 上,导航到仓库的主页。

  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.com 上,导航到组织的主页。

  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 使用 `repo` 和 `read: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.com 上,导航到组织的主页。

  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 运行器上,我们建议使用 使用 bash shell 以及 shell: bash 来使用上面 run 步骤中的命令。

从工作流程运行日志中删除秘密

虽然 GitHub 会自动删除打印到工作流程日志中的秘密,但运行器只能删除它们有权访问的秘密。这意味着只有在作业中使用秘密时才会删除该秘密。作为安全措施,您可以删除工作流程运行日志,以防止敏感值泄露。有关更多信息,请参阅“使用工作流程运行日志”。