概述
OpenID Connect (OIDC) 允许您的 GitHub Actions 工作流程访问云提供商中的资源,而无需将任何凭据存储为长期 GitHub 机密。
要使用 OIDC,需要先配置云提供商信任 GitHub 的 OIDC 作为联合身份,然后必须更新工作流程以使用令牌进行验证。
先决条件
-
若要了解 GitHub 如何使用 OpenID Connect (OIDC) 及其体系结构和优势的基本概念,请参阅“关于使用 OpenID Connect 进行安全强化”。
-
在继续之前,必须规划安全策略,以确保仅以可预测的方式分配访问令牌。 要控制云提供商颁发访问令牌的方式,必须至少定义一个条件,以便不受信任的存储库无法为云资源请求访问令牌。 有关详细信息,请参阅“关于使用 OpenID Connect 进行安全强化”。
更新 GitHub Actions 工作流程
要更新 OIDC 的工作流程,您需要对 YAML 进行两项更改:
- 为令牌添加权限设置。
- 使用云提供商的官方操作将 OIDC 令牌 (JWT) 交换为云访问令牌。
如果您的云提供商尚未提供官方操作,您可以更新工作流程以手动执行这些步骤。
添加权限设置
作业或工作流运行需要具有 id-token: write
的 permissions
设置。 如果 id-token
的 permissions
设置已设置为 read
或 none
,则无法请求 OIDC JWT ID 令牌。
id-token: write
设置允许使用下列方法之一从 GitHub 的 OIDC 提供程序请求 JWT:
- 在运行器上使用环境变量(
ACTIONS_ID_TOKEN_REQUEST_URL
和ACTIONS_ID_TOKEN_REQUEST_TOKEN
)。 - 使用“操作”工具包中的
getIDToken()
。
如果需要为工作流提取 OIDC 令牌,则可以在工作流级别设置权限。 例如:
permissions: id-token: write # This is required for requesting the JWT contents: read # This is required for actions/checkout
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
如果只需要为单个作业提取 OIDC 令牌,则可在该作业中设置此权限。 例如:
permissions: id-token: write # This is required for requesting the JWT
permissions:
id-token: write # This is required for requesting the JWT
可能需要在此处指定额外权限,具体取决于你的工作流要求。
对于与调用方工作流属于同一用户、组织或企业的可重用工作流,可以从调用方的上下文访问在可重用工作流中生成的 OIDC 令牌。
对于企业或组织外部的可重用工作流,应在调用方工作流级别或在调用可重用工作流的特定作业中将 id-token
的 permissions
设置显式设置为 write
。
这可确保仅允许可重用工作流中生成的 OIDC 令牌按预期在调用方工作流中使用。
有关详细信息,请参阅“重新使用工作流”。
使用官方操作
如果您的云提供商已创建将 OIDC 与 GitHub Actions 结合使用的官方操作,它将允许您轻松地将 OIDC 令牌交换为访问令牌。 然后,可以更新工作流程,以便在访问云资源时使用此令牌。
使用自定义操作
如果您的云提供商没有官方操作,或者您更喜欢创建自定义脚本,则可以手动向 GitHub的 OIDC 提供商请求 JSON Web 令牌 (JWT)。
如果您没有使用官方操作,则 GitHub 建议您使用 Actions 核心工具包。 也可使用以下环境变量来检索令牌:ACTIONS_RUNTIME_TOKEN
、ACTIONS_ID_TOKEN_REQUEST_URL
。
要使用此方法更新工作流程,您需要对 YAML 进行三项更改:
- 为令牌添加权限设置。
- 添加从 GitHub 的 OIDC 提供商请求 OIDC 令牌的代码。
- 添加用于将 OIDC 令牌与您的云提供商交换为访问令牌的代码。
使用 Actions 核心工具包请求 JWT
以下示例演示如何将 actions/github-script
与 core
工具包一起使用,从 GitHub 的 OIDC 提供商那里请求 JWT。 有关详细信息,请参阅“创建 JavaScript 操作”。
jobs:
job:
environment: Production
runs-on: ubuntu-latest
steps:
- name: Install OIDC Client from Core Package
run: npm install @actions/core@1.6.0 @actions/http-client
- name: Get Id Token
uses: actions/github-script@v6
id: idtoken
with:
script: |
const coredemo = require('@actions/core')
let id_token = await coredemo.getIDToken()
coredemo.setOutput('id_token', id_token)
使用环境变量请求 JWT
下面的示例演示如何使用环境变量来请求 JSON Web 令牌。
对于部署作业,需要使用 actions/github-script
和 core
工具包来定义令牌设置。 有关详细信息,请参阅“创建 JavaScript 操作”。
例如:
jobs:
job:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
id: script
timeout-minutes: 10
with:
debug: true
script: |
const token = process.env['ACTIONS_RUNTIME_TOKEN']
const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']
core.setOutput('TOKEN', token.trim())
core.setOutput('IDTOKENURL', runtimeUrl.trim())
然后,可使用 curl
从 GitHub OIDC 提供商那里检索 JWT。 例如:
- run: |
IDTOKEN=$(curl -H "Authorization: bearer ${{steps.script.outputs.TOKEN}}" ${{steps.script.outputs.IDTOKENURL}} -H "Accept: application/json; api-version=2.0" -H "Content-Type: application/json" -d "{}" | jq -r '.value')
echo $IDTOKEN
jwtd() {
if [[ -x $(command -v jq) ]]; then
jq -R 'split(".") | .[0],.[1] | @base64d | fromjson' <<< "${1}"
echo "Signature: $(echo "${1}" | awk -F'.' '{print $3}')"
fi
}
jwtd $IDTOKEN
echo "idToken=${IDTOKEN}" >> $GITHUB_OUTPUT
id: tokenid
从云提供商获取访问令牌
您需要向云提供商提供 OIDC JSON Web 令牌,以便获取访问令牌。
对于每个部署,您的工作流程必须使用云登录操作(或自定义脚本),以提取 OIDC 令牌并将其提供给您的云提供商。 然后,云提供商验证令牌中的声明;如果成功,它将提供仅可用于该作业运行的云访问令牌。 然后,作业中的后续操作可以使用提供的访问令牌连接到云并部署到其资源。
将 OIDC 令牌交换为访问令牌的步骤因每个云提供商而异。
访问云提供商中的资源
获取访问令牌后,可以使用特定的云操作或脚本向云提供商进行身份验证并部署到其资源。 对于每个云提供商,这些步骤可能会有所不同。 此外,此访问令牌的默认过期时间可能因每个云而异,并且可以在云提供商端进行配置。