教程:更新 HashiCorp Vault 配置以使用 ID Tokens
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
从 Vault 1.17 开始,当 JWT 包含 aud 声明时,JWT 身份验证登录要求角色上有绑定受众。aud 声明可以是单个字符串或字符串列表。
本教程演示如何将您现有的 CI/CD 密钥配置转换为使用 ID Tokens。
CI_JOB_JWT 变量已被弃用,但更新到 ID 令牌需要一些重要的配置更改才能与 Vault 协同工作。如果您的工作数量较多,一次性转换所有内容是一项艰巨的任务。
没有一种标准方法可以迁移到 ID tokens,因此本教程包含两种转换现有 CI/CD 密钥的方法。请选择最适合您用例的方法:
- 更新您的 Vault 配置:
- 方法 A:将 JWT 角色迁移到新的 Vault 身份验证方法
- 方法 B:将
iss声明迁移到角色中用于迁移窗口
- 更新您的 CI/CD Jobs
前置条件
本教程假设您熟悉 GitLab CI/CD 和 Vault。
要跟随本教程,您必须具备:
- 运行 GitLab 16.0 或更高版本的实例,或使用 GitLab.com。
- 您已经在使用的 Vault 服务器。
- 使用
CI_JOB_JWT从 Vault 获取密钥的 CI/CD jobs。
在以下示例中,请替换:
vault.example.com为您的 Vault 服务器 URL。gitlab.example.com为您的 GitLab 实例 URL。jwt或jwt_v2为您的身份验证方法名称。
方法 A:将 JWT 角色迁移到新的 Vault 身份验证方法
此方法并行创建第二个 JWT 身份验证方法,与当前正在使用的方法并存。之后,所有用于 GitLab 集成的 Vault 角色都将在新的身份验证方法中重新创建。
在 Vault 中创建第二个 JWT 身份验证路径
作为从 CI_JOB_JWT 过渡到 ID 令牌的一部分,您必须更新 Vault 中的 bound_issuer 以包含 https://:
$ vault write auth/jwt/config \
oidc_discovery_url="https://gitlab.example.com" \
bound_issuer="https://gitlab.example.com"进行此更改后,使用 CI_JOB_JWT 的 jobs 将开始失败。
您可以在 Vault 中创建多个身份验证路径,这使您能够按项目和 job 逐步过渡到 ID 令牌,而不会造成中断。
-
配置名称为
jwt_v2的新身份验证路径,运行:vault auth enable -path jwt_v2 jwt您可以选择不同的名称,但其余示例假设您使用的是
jwt_v2,因此请根据需要更新示例。 -
为您的实例配置新的身份验证路径:
$ vault write auth/jwt_v2/config \ oidc_discovery_url="https://gitlab.example.com" \ bound_issuer="https://gitlab.example.com"
重新创建角色以使用新的身份验证路径
角色绑定到特定的身份验证路径,因此您需要为每个 job 添加新角色。
如果 JWT 包含受众,则角色的 bound_audiences 参数是必需的,并且必须匹配 JWT 至少一个关联的 aud 声明。
-
重新创建用于暂存的名为
myproject-staging的角色:$ vault write auth/jwt_v2/role/myproject-staging - <<EOF { "role_type": "jwt", "policies": ["myproject-staging"], "token_explicit_max_ttl": 60, "user_claim": "user_email", "bound_audiences": ["https://vault.example.com"], "bound_claims": { "project_id": "22", "ref": "master", "ref_type": "branch" } } EOF -
重新创建用于生产的名为
myproject-production的角色:$ vault write auth/jwt_v2/role/myproject-production - <<EOF { "role_type": "jwt", "policies": ["myproject-production"], "token_explicit_max_ttl": 60, "user_claim": "user_email", "bound_audiences": ["https://vault.example.com"], "bound_claims_type": "glob", "bound_claims": { "project_id": "22", "ref_protected": "true", "ref_type": "branch", "ref": "auto-deploy-*" } } EOF
您只需要在 vault 命令中将 jwt 更新为 jwt_v2,不要更改角色内的 role_type。
方法 B:将 iss 声明迁移到角色中用于迁移窗口
此方法不需要 Vault 管理员创建第二个 JWT 身份验证方法并重新创建所有与 GitLab 相关的角色。
为每个角色添加 bound_issuers 声明映射
Vault 不允许在 JWT 身份验证方法级别上有多个 iss 声明,因为该级别的 bound_issuer
指令只接受单个值。但是,可以通过使用 bound_claims
映射配置指令在角色级别配置多个声明。
使用此方法,您可以为 Vault 提供多个 iss 声明验证选项。这支持 id_tokens 带有的 https:// 前缀的 GitLab 实例主机名声明,以及旧的非前缀声明。
要将 bound_claims 配置添加到所需角色,请运行:
$ vault write auth/jwt/role/myproject-staging - <<EOF
{
"role_type": "jwt",
"policies": ["myproject-staging"],
"token_explicit_max_ttl": 60,
"user_claim": "user_email",
"bound_audiences": ["https://vault.example.com"],
"bound_claims": {
"iss": [
"https://gitlab.example.com",
"gitlab.example.com"
],
"project_id": "22",
"ref": "master",
"ref_type": "branch"
}
}
EOF除了 bound_claims 部分外,您不需要更改任何现有角色配置。
请确保添加如上所示的 iss 配置,以确保 Vault 接受此角色的前缀和非前缀 iss 声明。
在进行下一步之前,您必须将此更改应用于所有用于 GitLab 集成的 JWT 角色。
如果需要,在所有项目都已迁移并且您不再需要 CI_JOB_JWT 和 ID 令牌的并行支持后,您可以将 iss 声明验证从身份验证方法迁移回角色。
从身份验证方法中移除 bound_issuers 声明
在所有角色都已使用 bound_claims.iss 声明更新后,您可以移除此验证的身份验证方法级别配置:
$ vault write auth/jwt/config \
oidc_discovery_url="https://gitlab.example.com" \
bound_issuer=""将 bound_issuer 指令设置为空字符串会移除身份验证方法级别的发行者验证。
但是,由于我们将此验证移到了角色级别,此配置仍然安全。
更新您的 CI/CD Jobs
Vault 有两种不同的 KV Secrets Engines,您使用的版本会影响您在 CI/CD 中定义密钥的方式。
请查看 HashiCorp 支持门户上的 Which Version is my Vault KV Mount? 文章,以检查您的 Vault 服务器。
此外,如有需要,您可以查看 CI/CD 文档:
以下示例展示如何获取写入到 secret/myproject/staging/db 中 password 字段的暂存数据库密码。
VAULT_AUTH_PATH 变量的值取决于您使用的迁移方法:
- 方法 A(将 JWT 角色迁移到新的 Vault 身份验证方法):使用
jwt_v2。 - 方法 B(将
iss声明迁移到角色中用于迁移窗口):使用jwt。
KV Secrets Engine v1
secrets:vault 关键字默认使用 KV Mount 的 v2 版本,因此您需要显式配置 job 以使用 v1 引擎:
job:
variables:
VAULT_SERVER_URL: https://vault.example.com
VAULT_AUTH_PATH: jwt_v2 # 如果使用方法 B,则为 "jwt"
VAULT_AUTH_ROLE: myproject-staging
id_tokens:
VAULT_ID_TOKEN:
aud: https://vault.example.com
secrets:
PASSWORD:
vault:
engine:
name: kv-v1
path: secret
field: password
path: myproject/staging/db
file: false如果需要,VAULT_SERVER_URL 和 VAULT_AUTH_PATH 都可以 定义为项目或组 CI/CD 变量。
我们使用 secrets:file:false 是因为 ID 令牌默认将密钥放在文件中,但我们需要它作为常规变量工作以匹配旧的行为。
KV Secrets Engine v2
对于 v2 引擎,您可以使用两种格式。
长格式:
job:
variables:
VAULT_SERVER_URL: https://vault.example.com
VAULT_AUTH_PATH: jwt_v2 # 如果使用方法 B,则为 "jwt"
VAULT_AUTH_ROLE: myproject-staging
id_tokens:
VAULT_ID_TOKEN:
aud: https://vault.example.com
secrets:
PASSWORD:
vault:
engine:
name: kv-v2
path: secret
field: password
path: myproject/staging/db
file: false这与 v1 引擎的示例相同,但 secrets:vault:engine:name: 设置为 kv-v2 以匹配引擎。
您也可以使用短格式:
job:
variables:
VAULT_SERVER_URL: https://vault.example.com
VAULT_AUTH_PATH: jwt_v2 # 如果使用方法 B,则为 "jwt"
VAULT_AUTH_ROLE: myproject-staging
id_tokens:
VAULT_ID_TOKEN:
aud: https://vault.example.com
secrets:
PASSWORD:
vault: myproject/staging/db/password@secret
file: false提交更新的 CI/CD 配置后,您的 jobs 将使用 ID 令牌获取密钥,恭喜!
如果您已将所有项目迁移为使用 ID 令牌获取密钥,并且使用方法 B 进行了迁移,那么现在如果需要,可以将 iss 声明验证移回身份验证方法配置。