使用 ID 令牌的 OpenID Connect (OIDC) 身份验证
引入于 15.7 版本。
您可以使用极狐GitLab CI/CD 的 ID 令牌对第三方服务进行身份验证。
ID 令牌
ID 令牌是可以添加到极狐GitLab CI/CD 作业的 JSON Web 令牌 (JWT)。它们可用于第三方服务的 OIDC 身份验证,并被 secrets
关键字用于与 HashiCorp Vault 进行身份验证。
ID 令牌在 .gitlab-ci.yml
中配置。例如:
job_with_id_tokens:
id_tokens:
FIRST_ID_TOKEN:
aud: https://first.service.com
SECOND_ID_TOKEN:
aud: https://second.service.com
script:
- first-service-authentication-script.sh $FIRST_ID_TOKEN
- second-service-authentication-script.sh $SECOND_ID_TOKEN
在此示例中,这两个令牌具有不同的 aud
声明。第三方服务可以配置为拒绝没有匹配其绑定受众的 aud
声明的令牌。您可以使用此功能来减少令牌可以用来进行身份验证的服务数量,降低令牌泄露的严重性。
令牌负载
每个 ID 令牌中包含以下标准声明:
字段 | 描述 |
---|---|
iss |
令牌的颁发者,是极狐GitLab 实例的域名 (“issuer” 声明)。 |
sub |
project_path:{group}/{project}:ref_type:{type}:ref:{branch_name} (“subject” 声明)。 |
aud |
令牌的目标受众 (“audience” 声明)。在 ID 令牌 配置中指定。默认情况下为极狐GitLab 实例的域。 |
exp |
过期时间 (“expiration time” 声明)。 |
nbf |
令牌生效后的时间 (“not before” 声明)。 |
iat |
JWT 发布时间 (“issued at” 声明)。 |
jti |
令牌的唯一标识符 (“JWT ID” 声明)。 |
该令牌还包括极狐GitLab 提供的自定义声明:
字段 | 何时有效 | 描述 |
---|---|---|
namespace_id |
总是 | 使用它来按 ID 将范围限定为群组或用户级别的命名空间。 |
namespace_path |
总是 | 使用它来按路径将范围限定为群组或用户级别的命名空间。 |
project_id |
总是 | 使用它来按 ID 确定项目范围。 |
project_path |
总是 | 使用它来按路径确定项目范围。 |
user_id |
总是 | 执行作业的用户 ID。 |
user_login |
总是 | 执行作业的用户的用户名。 |
user_email |
总是 | 执行作业的用户的电子邮件。 |
user_identities |
用户偏好设置 | 用户外部身份列表(引入于 16.0)。 |
pipeline_id |
总是 | 流水线的 ID。 |
pipeline_source |
总是 | 流水线源。 |
job_id |
总是 | 作业 ID。 |
ref |
总是 | 作业的 Git ref。 |
ref_type |
总是 | Git ref 类型,branch 或 tag 。 |
ref_path |
总是 | 作业的完整 ref。例如,refs/heads/main 。引入于 16.0 版本。 |
ref_protected |
总是 | 如果 Git ref 受保护,则为 true ,否则为 false 。 |
environment |
作业指定一个环境时 | 此作业部署到的环境(引入于 13.9 版本)。 |
environment_protected |
作业指定一个环境时 | 如果部署的环境受到保护,则为 true ,否则为 false (引入于 13.9 版本)。 |
deployment_tier |
作业指定一个环境时 | 作业指定的环境的部署级别(引入于 15.2 版本)。 |
runner_id |
总是 | 执行作业的 runner 的 ID。引入于 16.0 版本。 |
runner_environment |
总是 | 作业使用的 runner 类型,gitlab-hosted 或 self-hosted 。引入于 16.0 版本。 |
sha |
总是 | 作业的提交 SHA。引入于 16.0 版本。 |
ci_config_ref_uri |
总是 | 访问顶级流水线定义的引用路径,例如 gitlab.example.com/my-group/my-project//.gitlab-ci.yml@refs/heads/main 。引入于 16.2。除非流水线定义位于同一项目中,否则此声明为 null 。 |
ci_config_sha |
总是 |
ci_config_ref_uri 的 Git 提交 SHA。引入于 16.2。除非流水线定义位于同一项目中,否则此声明为 null 。 |
project_visibility |
总是 | 运行流水线的项目的可见性,可以是 internal 、private 或 public 。引入于 16.3。 |
{
"namespace_id": "72",
"namespace_path": "my-group",
"project_id": "20",
"project_path": "my-group/my-project",
"user_id": "1",
"user_login": "sample-user",
"user_email": "sample-user@example.com",
"user_identities": [
{"provider": "github", "extern_uid": "2435223452345"},
{"provider": "bitbucket", "extern_uid": "john.smith"},
],
"pipeline_id": "574",
"pipeline_source": "push",
"job_id": "302",
"ref": "feature-branch-1",
"ref_type": "branch",
"ref_path": "refs/heads/feature-branch-1",
"ref_protected": "false",
"environment": "test-environment2",
"environment_protected": "false",
"deployment_tier": "testing",
"runner_id": 1,
"runner_environment": "self-hosted",
"sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"project_visibility": "public",
"ci_config_ref_uri": "gitlab.example.com/my-group/my-project//.gitlab-ci.yml@refs/heads/main",
"ci_config_sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"jti": "235b3a54-b797-45c7-ae9a-f72d7bc6ef5b",
"iss": "https://gitlab.example.com",
"iat": 1681395193,
"nbf": 1681395188,
"exp": 1681398793,
"sub": "project_path:my-group/my-project:ref_type:branch:ref:feature-branch-1",
"aud": "https://vault.example.com"
}
ID 令牌使用 RS256 编码并使用专用私钥签名。如果指定,则令牌的到期时间设置为作业的超时时间,如果未指定超时时间,则设置为 5 分钟。
手动 ID 令牌身份验证
您可以使用 ID 令牌通过第三方服务进行 OIDC 身份验证。例如:
manual_authentication:
variables:
VAULT_ADDR: http://vault.example.com:8200
image: vault:latest
id_tokens:
VAULT_ID_TOKEN:
aud: http://vault.example.com:8200
script:
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-example jwt=$VAULT_ID_TOKEN)"
- export PASSWORD="$(vault kv get -field=password secret/myproject/example/db)"
- my-authentication-script.sh $VAULT_TOKEN $PASSWORD
使用 HashiCorp Vault 进行自动 ID 令牌身份验证
您可以使用 ID 令牌通过 secrets
关键字自动从 HashiCorp Vault 获取 secret。
如果您之前使用 CI_JOB_JWT
从 Vault 获取 secret,请了解如何使用更新 HashiCorp Vault 配置以使用 ID 令牌 教程切换到 ID 令牌。
配置自动 ID 令牌身份验证
如果定义了一个 ID 令牌,secrets
关键字会自动使用它来对 Vault 进行身份验证。例如:
job_with_secrets:
id_tokens:
VAULT_ID_TOKEN:
aud: https://example.vault.com
secrets:
PROD_DB_PASSWORD:
vault: example/db/password # authenticates using $VAULT_ID_TOKEN
script:
- access-prod-db.sh --token $PROD_DB_PASSWORD
如果定义了多个 ID 令牌,请使用 token
关键字指定应使用哪个令牌。例如:
job_with_secrets:
id_tokens:
FIRST_ID_TOKEN:
aud: https://first.service.com
SECOND_ID_TOKEN:
aud: https://second.service.com
secrets:
FIRST_DB_PASSWORD:
vault: first/db/password
token: $FIRST_ID_TOKEN
SECOND_DB_PASSWORD:
vault: second/db/password
token: $SECOND_ID_TOKEN
script:
- access-first-db.sh --token $FIRST_DB_PASSWORD
- access-second-db.sh --token $SECOND_DB_PASSWORD
启用自动 ID 令牌身份验证(已废弃)
要启用自动 ID 令牌身份验证:
- 在左侧边栏中,选择 搜索或转到 并找到您的项目。
- 选择 设置 > CI/CD。
- 展开 令牌访问。
- 打开 限制 JSON Web 令牌 (JWT) 访问 开关。
故障排除
400: missing token
状态码
此错误表明 ID 令牌所需的一个或多个基本组件丢失或未按预期配置。
要查找问题,管理员可以在实例的 exceptions_json.log
中查找失败的特定方法详情。
GitLab::Ci::Jwt::NoSigningKeyError
exceptions_json.log
文件中的此错误可能是因为数据库中缺少签名密钥并且无法生成令牌。要验证这是否是问题所在,请在实例的 PostgreSQL 终端上运行以下查询:
SELECT encrypted_ci_jwt_signing_key FROM application_settings;
如果返回的值为空,请使用下面的 Rails 代码片段生成一个新密钥并在内部进行替换:
key = OpenSSL::PKey::RSA.new(2048).to_pem
ApplicationSetting.find_each do |application_setting|
application_setting.update(ci_jwt_signing_key: key)
end