{{< details >}}

  • Tier: 基础版, 专业版, 旗舰版
  • Offering: JihuLab.com, 私有化部署

{{< /details >}}

{{< history >}}

  • 引入于极狐GitLab 15.7。

{{< /history >}}

您可以使用极狐GitLab CI/CD 的 ID 令牌 进行第三方服务的身份验证。

ID 令牌

ID 令牌 是可以添加到极狐GitLab CI/CD 作业中的 JSON Web Tokens (JWTs)。它们可以用于与第三方服务的 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 令牌的主题 (“subject” 声明)。默认为 project_path:{group}/{project}:ref_type:{type}:ref:{branch_name}。可以使用项目 API配置项目。
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_access_level 总是 执行作业的用户访问级别。在极狐GitLab 16.9 中引入。
user_identities 用户首选项设置 用户的外部身份列表(在极狐GitLab 16.0 中引入)。
pipeline_id 总是 流水线的 ID。
pipeline_source 总是 流水线来源
job_id 总是 作业的 ID。
ref 总是 作业的 Git 引用。
ref_type 总是 Git 引用类型,可以是 branchtag
ref_path 总是 作业的完全限定引用。例如,refs/heads/main。在极狐GitLab 16.0 中引入。
ref_protected 总是 如果 Git 引用受保护为 true,否则为 false
groups_direct 用户直接属于 0 到 200 个群组 用户直接所属群组的路径。如果用户直接属于超过 200 个群组,则省略。(在极狐GitLab 16.11 中引入,并在极狐GitLab 17.3 中放置在 ci_jwt_groups_direct 功能标志 后面。
environment 作业指定环境 此作业部署到的环境。
environment_protected 作业指定环境 如果部署环境受保护为 true,否则为 false
deployment_tier 作业指定环境 作业指定的环境的 部署层级。(在极狐GitLab 15.2 中引入)。
environment_action 作业指定环境 作业中指定的 环境操作 (environment:action)。(在极狐GitLab 16.5 中引入)。
runner_id 总是 执行作业的 runner 的 ID。在极狐GitLab 16.0 中引入
runner_environment 总是 作业使用的 runner 类型。可以是 gitlab-hostedself-hosted。在极狐GitLab 16.0 中引入。
sha 总是 作业的提交 SHA。在极狐GitLab 16.0 中引入。
ci_config_ref_uri 总是 顶级流水线定义的引用路径,例如,gitlab.example.com/my-group/my-project//.gitlab-ci.yml@refs/heads/main。在极狐GitLab 16.2 中引入。除非流水线定义位于同一项目中,否则此声明为 null
ci_config_sha 总是 ci_config_ref_uri 的 Git 提交 SHA。在极狐GitLab 16.2 中引入。除非流水线定义位于同一项目中,否则此声明为 null
project_visibility 总是 流水线运行所在项目的 可见性。可以是 internalprivatepublic。在极狐GitLab 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",
  "groups_direct": ["mygroup/mysubgroup", "myothergroup/myothersubgroup"],
  "environment": "test-environment2",
  "environment_protected": "false",
  "deployment_tier": "testing",
  "environment_action": "start",
  "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 身份验证。例如:

疑难解答

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