概述
OpenID Connect (OIDC) 允许您的 GitHub Actions 工作流程访问云提供商中的资源,而无需将任何凭据存储为长期 GitHub 机密。
要使用 OIDC,需要先配置云提供商信任 GitHub 的 OIDC 作为联合身份,然后必须更新工作流程以使用令牌进行验证。
先决条件
-
若要了解 GitHub 如何使用 OpenID Connect (OIDC) 及其体系结构和优势的基本概念,请参阅“关于使用 OpenID Connect 进行安全强化”。
-
在继续之前,必须规划安全策略,以确保仅以可预测的方式分配访问令牌。 要控制云提供商颁发访问令牌的方式,必须至少定义一个条件,以便不受信任的存储库无法为云资源请求访问令牌。 有关详细信息,请参阅“关于使用 OpenID Connect 进行安全强化”。
更新 GitHub Actions 工作流程
要更新 OIDC 的工作流程,您需要对 YAML 进行两项更改:
- 为令牌添加权限设置。
- 使用云提供商的官方操作将 OIDC 令牌 (JWT) 交换为云访问令牌。
如果您的云提供商尚未提供官方操作,您可以更新工作流程以手动执行这些步骤。
Note
在工作流或 OIDC 策略中使用环境时,建议将保护规则添加到环境中以提高安全性。 例如,可以在环境中配置部署规则,以限制可以部署到环境或访问环境机密的分支和标记。 有关详细信息,请参阅“管理部署环境”。
添加权限设置
作业或工作流运行需要使用 id-token: write
的 permissions
设置,以允许 GitHub 的 OIDC 提供程序为每个运行创建 JSON Web 令牌。 如果 id-token
的 permissions
未设置为 write
,则无法请求 OIDC JWT ID 令牌,但是此值并不表示授予对任何资源的写权限,而只能提取和设置操作或步骤的 OIDC 令牌,以启用通过短期访问令牌进行身份验证。 任何实际信任设置均通过 OIDC 声明定义,有关详细信息,请参阅“关于使用 OpenID Connect 进行安全强化”。
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 令牌交换为访问令牌。 然后,可以更新工作流程,以便在访问云资源时使用此令牌。
例如,阿里云创建了 aliyun/configure-aliyun-credentials-action
,用于将 OIDC 与 GitHub 集成。
使用自定义操作
如果您的云提供商没有官方操作,或者您更喜欢创建自定义脚本,则可以手动向 GitHub的 OIDC 提供商请求 JSON Web 令牌 (JWT)。
如果您没有使用官方操作,则 GitHub 建议您使用 Actions 核心工具包。 也可使用以下环境变量来检索令牌:ACTIONS_ID_TOKEN_REQUEST_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 令牌交换为访问令牌的步骤因每个云提供商而异。
访问云提供商中的资源
获取访问令牌后,可以使用特定的云操作或脚本向云提供商进行身份验证并部署到其资源。 对于每个云提供商,这些步骤可能会有所不同。
例如,阿里云维护自己的 OIDC 身份验证说明。 有关详细信息,请参阅阿里云文档中基于 OIDC 的 SSO 概述。
此外,此访问令牌的默认过期时间可能因每个云而异,并且可以在云提供商端进行配置。