跳至主要内容

在 GitHub 操作中使用机密

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

关于机密

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

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

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

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

为你的机密命名

以下规则适用于机密名称

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

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

  • 名称不得以数字开头。

  • 名称不区分大小写。

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

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

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

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

访问您的机密

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

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

警告:如果在作业中使用了机密,GitHub 会自动编辑打印到日志中的机密。您应避免故意将机密打印到日志中。

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

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

限制凭据权限

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

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

考虑使用 GitHub App,而不是使用个人访问令牌,它使用细粒度权限和短期令牌,类似于细粒度个人访问令牌。与个人访问令牌不同,GitHub App 与用户无关,因此即使安装该应用的用户离开你的组织,工作流仍将继续工作。有关更多信息,请参阅“在 GitHub Actions 工作流中使用 GitHub App 进行经过身份验证的 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 使用 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. 在组织名称下,点击 设置。如果你看不到“设置”选项卡,请选择下拉菜单,然后单击设置

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

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

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

在工作流中使用秘密

注意

  • 除了 GITHUB_TOKEN 之外,当从一个分支存储库触发工作流时,不会将秘密传递给运行程序。

  • 秘密不会自动传递给可重用工作流。有关更多信息,请参阅“重用工作流”。

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

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 的新机密,并将机密的 value 设置为在上述步骤中使用的密码。

  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 存储为机密。然后,你可以在工作流中引用机密,并对其进行解码以便在 runner 上使用。有关大小限制,请参阅“在 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. 要从 runner 访问 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 runner 上,我们建议 使用 bash shell,并使用 shell: bash 在上述 run 步骤中使用命令。

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

虽然 GitHub 会自动对打印到工作流日志中的机密进行编辑,但 Runner 只能删除他们有权访问的机密。这意味着只有在作业中使用了机密,它才会被编辑。作为一项安全措施,你可以删除工作流运行日志,以防止泄露敏感值。有关更多信息,请参阅“使用工作流运行日志”。