{{< details >}}
- Tier: 专业版, 旗舰版
- Offering: JihuLab.com, 私有化部署
{{< /details >}}
{{< alert type=”note” >}}
从 Vault 1.17 开始,当 JWT 包含 aud
声明时,JWT 认证登录需要在角色上绑定受众。aud
声明可以是单个字符串或字符串列表。
{{< /alert >}}
这篇教程演示了如何将现有的 CI/CD 密钥配置转换为使用 ID Tokens。
CI_JOB_JWT
变量已被弃用,但更新为 ID 令牌需要进行一些重要的配置更改,以便与 Vault 一起使用。如果你有多个作业,一次性转换所有内容是一项艰巨的任务。
没有一种标准方法来迁移到 ID Tokens,因此本教程包括两种转换现有 CI/CD 密钥的方法。选择最适合你用例的方法:
- 更新你的 Vault 配置:
- 方法 A:迁移 JWT 角色到新的 Vault 认证方法
- 方法 B:在迁移窗口中将
iss
声明移动到角色
- 更新你的 CI/CD 作业
先决条件
本教程假设你熟悉极狐GitLab CI/CD 和 Vault。
要跟随本教程,你必须拥有:
- 运行极狐GitLab 16.0 或更高版本的实例,或在 JihuLab.com 上。
- 一个你已经在使用的 Vault 服务器。
- 使用
CI_JOB_JWT
从 Vault 检索密钥的 CI/CD 作业。
在下面的示例中,替换:
-
vault.example.com
为你的 Vault 服务器的 URL。 -
gitlab.example.com
为你的极狐GitLab 实例的 URL。 -
jwt
或jwt_v2
为你的认证方法名称。
方法 A:迁移 JWT 角色到新的 Vault 认证方法
此方法在并行使用的现有 JWT 认证方法中创建了第二个 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
的作业将开始失败。
你可以在 Vault 中创建多个认证路径,这使你能够在项目的作业基础上过渡到 ID Tokens 而不会中断。
-
使用名称
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"
重新创建角色以使用新的认证路径
角色绑定到特定的认证路径,因此你需要为每个作业添加新角色。如果 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
声明验证。这支持带有 https://
前缀的极狐GitLab 实例主机名声明,该声明附带 id_tokens
,以及旧的无前缀声明。
要将 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 Tokens 的并行支持后,将 iss
声明验证的迁移从认证方法恢复到角色。
从认证方法中移除 bound_issuers
声明
在所有角色都更新了 bound_claims.iss
声明后,你可以移除此验证的认证方法级别配置:
$ vault write auth/jwt/config \
oidc_discovery_url="https://gitlab.example.com" \
bound_issuer=""
将 bound_issuer
指令设置为空字符串会移除认证方法级别的发行者验证。然而,由于我们已将此验证移动到角色级别,此配置仍然是安全的。
更新你的 CI/CD 作业
Vault 有两个不同的 KV Secrets Engines,你使用的版本会影响你在 CI/CD 中定义密钥的方式。
此外,如果需要,你可以查看以下 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,因此需要显式配置作业以使用 v1 引擎:
job:
variables:
VAULT_SERVER_URL: https://vault.example.com
VAULT_AUTH_PATH: jwt_v2 # 或 "jwt" 如果你使用了方法 B
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 Tokens 默认情况下将密钥放入文件中,但我们需要它作为常规变量以匹配旧行为。
KV Secrets Engine v2
对于 v2 引擎,你可以使用两种格式。
长格式:
job:
variables:
VAULT_SERVER_URL: https://vault.example.com
VAULT_AUTH_PATH: jwt_v2 # 或 "jwt" 如果你使用了方法 B
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 # 或 "jwt" 如果你使用了方法 B
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 配置后,你的作业将使用 ID Tokens 获取密钥,恭喜你!
如果你已迁移所有项目以使用 ID Tokens 获取密钥,并且在迁移过程中使用了方法 B,现在可以选择将 iss
声明验证移回认证方法配置。