Skip to main content

在 GitHub Actions 中使用机密

借助密钥可以在组织、存储库或存储库环境中存储敏感信息。

Tool navigation

关于机密

机密是在组织、存储库或存储库环境中创建的变量。 您创建的机密可用于 GitHub Actions 工作流程。 仅当在工作流中显式包含机密时,GitHub Actions 才能读取机密。

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

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

注意: 如果 GitHub Actions 工作流需要访问支持 OpenID Connect (OIDC) 的云提供商提供的资源,则可以将工作流配置为直接向云提供商进行身份验证。 这样就可以停止将这些凭据存储为长期存在的机密,并提供其他安全优势。 有关详细信息,请参阅“关于使用 OpenID Connect 进行安全强化”。

命名您的密码

以下规则适用于密码名称:

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

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

  • 名称不能以数字开头。

  • 名称不区分大小写。

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

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

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

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

访问您的密码

为使密码用于操作,必须将密码设置为工作流程文件中的输入或环境变量。 查看操作的自述文件以了解操作预期的输入和环境变量。 有关详细信息,请参阅“GitHub Actions 的工作流语法”。

如果你有权编辑工作流文件,则可以使用和读取该文件中的机密。 有关详细信息,请参阅“GitHub 上的访问权限”。

警告:**** 如果在作业中使用了机密,GitHub 会自动对输出到日志中的机密进行编辑。 应避免故意将机密输出到日志中。

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

您还可以使用 REST API 管理密码。 有关详细信息,请参阅“GitHub Actions 机密的 REST API 终结点”。

限制凭据权限

生成凭据时,建议尽可能授予最低的权限。 例如,请改为使用部署密钥或服务帐户,而不是使用个人凭据。 请考虑授予只读权限(如果这是所需的全部权限)并尽可能限制访问。

生成 personal access token (classic) 时,请选择所需的最小范围。生成 fine-grained personal access token 时,请选择所需的最小权限和存储库访问权限。

请考虑使用 GitHub App(而不是使用 personal access token),它使用细粒度权限和短生存期令牌,类似于 fine-grained personal access token。 与 personal access token 不同,GitHub App 不绑定到用户,因此即使安装了该应用的用户离开组织,工作流仍将继续工作。 有关详细信息,请参阅“使用 GitHub Actions 工作流中的 GitHub App 发出经过身份验证的 API 请求”。

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

为存储库创建机密

若要在 GitHub 上为个人帐户存储库创建机密或变量,你必须是存储库所有者。 若要在 GitHub 上为组织存储库创建机密或变量,你必须拥有 admin 访问权限。 最后,若要通过 REST API 为个人帐户存储库或组织存储库创建机密或变量,你必须拥有协作者访问权限。

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

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

    存储库标头的屏幕截图,其中显示了选项卡。 “设置”选项卡以深橙色边框突出显示。

  3. 在边栏的“安全性”部分中,选择** 机密和变量**、然后单击“操作”****。

  4. 单击“机密”选项卡。 “操作机密和变量”页的屏幕截图

  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. 在存储库名称下,单击 “设置”。 如果看不到“设置”选项卡,请选择“”下拉菜单,然后单击“设置”********。

    存储库标头的屏幕截图,其中显示了选项卡。 “设置”选项卡以深橙色边框突出显示。

  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

为组织创建机密

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

组织所有者和拥有“管理组织操作变量”或“管理组织操作机密”权限的用户可以在组织级别创建机密或变量。

有关详细信息,请参阅“关于自定义组织角色”。

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

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

    组织配置文件中选项卡的屏幕截图。 “设置”选项卡以深橙色标出。

  3. 在边栏的“安全性”部分中,选择** 机密和变量**、然后单击“操作”****。

  4. 单击“机密”选项卡。

    “Actions 机密和变量”页的屏幕截图。 标记有“机密”的选项卡用深橙色框出。

    **** 注意:“操作机密和变量”页可能不会根据你的权限显示机密和变量的不同选项卡。 组织所有者和拥有“管理组织操作变量”和“管理组织操作机密”权限的用户将看到“变量”**** 和“机密”**** 选项卡。 有关详细信息,请参阅“关于自定义组织角色”。

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

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

    组织配置文件中选项卡的屏幕截图。 “设置”选项卡以深橙色标出。

  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 shellshell: bash 结合使用,以使用上述 run 步骤中的命令。

编辑工作流运行日志中的机密

虽然 GitHub 自动对输出到工作流日志的机密进行编辑,但运行器仅能删除其有权访问的机密。 这意味着只有在作业中使用机密时才会对机密进行编辑。 作为安全措施,可以删除工作流运行日志,从而防止敏感值泄露。 有关详细信息,请参阅“使用工作流运行日志”。