关于密钥
密钥是在组织、仓库或仓库环境中创建的变量。您创建的密钥可在 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 为个人帐户仓库或组织仓库创建密钥或变量,您必须具有协作者访问权限。
-
在 GitHub 上,导航到仓库的主页。
-
在您的仓库名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置。
-
在侧边栏的“安全”部分,选择 密钥和变量,然后单击操作。
-
单击密钥选项卡。
-
单击新建仓库密钥。
-
在名称字段中,键入密钥的名称。
-
在密钥字段中,输入密钥的值。
-
单击添加密钥。
如果您的仓库具有环境密钥或可以访问父组织中的密钥,则这些密钥也会在此页面上列出。
要了解有关 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
访问权限。有关环境的更多信息,请参见“管理部署环境”。
-
在 GitHub 上,导航到仓库的主页。
-
在您的仓库名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置。
-
在左侧边栏中,单击环境。
-
单击要向其添加密钥的环境。
-
在环境密钥下,单击添加密钥。
-
在名称输入框中键入密钥的名称。
-
输入密钥的值。
-
单击添加密钥。
要添加环境密钥,请使用 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 订阅的更多信息,请参见“升级您的帐户计划”。
在组织中创建密钥或变量时,您可以使用策略来限制仓库的访问权限。例如,您可以授予所有仓库的访问权限,或仅限于私有仓库或指定的仓库列表。
组织所有者可以在组织级别创建密钥或变量。
-
在 GitHub 上,导航到组织的主页。
-
在您的组织名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置。
-
在侧边栏的“安全”部分,选择 密钥和变量,然后单击操作。
-
单击密钥选项卡。
-
单击新建组织密钥。
-
在名称输入框中键入密钥的名称。
-
输入密钥的值。
-
从仓库访问下拉列表中选择访问策略。
-
单击添加密钥。
注意
默认情况下,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
查看对组织级密钥的访问权限
您可以检查正在应用于组织中密钥的哪些访问策略。
-
在 GitHub 上,导航到组织的主页。
-
在您的组织名称下,单击 设置。如果您看不到“设置”选项卡,请选择下拉菜单,然后单击设置。
-
在侧边栏的“安全”部分,选择 密钥和变量,然后单击操作。
-
密钥列表包含任何已配置的权限和策略。有关每个密钥的已配置权限的更多详细信息,请单击更新。
在工作流中使用密钥
注意
- 除
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 不会删除日志中打印的密钥。
-
从您的终端运行以下命令,使用
gpg
和 AES256 密码算法加密包含密钥的文件。在此示例中,my_secret.json
是包含密钥的文件。gpg --symmetric --cipher-algo AES256 my_secret.json
-
系统会提示您输入密码。请记住密码,因为您需要在 GitHub 上创建一个使用该密码作为值的新密钥。
-
创建一个包含密码的新密钥。例如,创建一个名为
LARGE_SECRET_PASSPHRASE
的新密钥,并将密钥的值设置为上一步中使用的密码。 -
将加密的文件复制到仓库中的路径并提交。在此示例中,加密的文件为
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"
-
在您的仓库中创建一个 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
#!/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
-
在将其检入仓库之前,请确保您的 shell 脚本是可执行的。
chmod +x decrypt_secret.sh git add decrypt_secret.sh git commit -m "Add new decryption script" git push
-
在您的 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 仅将二进制数据转换为文本,不能替代实际加密。
-
使用
base64
将文件编码为 Base64 字符串。例如在 macOS 上,您可以运行
base64 -i cert.der -o cert.base64
在 Linux 上,您可以运行
base64 -w 0 cert.der > cert.base64
-
创建一个包含 Base64 字符串的密钥。例如
$ gh secret set CERTIFICATE_BASE64 < cert.base64 ✓ Set secret CERTIFICATE_BASE64 for octocat/octorepo
-
要从您的运行器访问 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 安装令牌(
ghp
、gho
、ghu
、ghs
、ghr
) - v2 GitHub PAT
注意
如果您希望自动删除其他类型的敏感信息,请在我们的社区讨论中与我们联系。
作为最佳实践习惯,您应该使用::add-mask::VALUE
屏蔽所有不是 GitHub 密钥的敏感信息。这会导致该值被视为密钥并从日志中删除。有关屏蔽数据的更多信息,请参阅GitHub Actions 的工作流命令。
密钥的删除由您的工作流运行器执行。这意味着只有在作业中使用并可供运行器访问的密钥才会被删除。如果未删除的密钥被发送到工作流运行日志,则应删除日志并轮换密钥。有关删除日志的信息,请参阅使用工作流运行日志。