[分享] GitLab CI/CD 使用 Vault 由 CI_JOB_JWT 转换为 id_tokens 时的注意事项

官方参考:

id_tokens用法发布之前,在GitLab CI/CD 中使用外部的密码器 vault,都是使用CI_JOB_JWT的验证方式,在使用此变量获取令牌时一切工作都是 okay 的,没有任何的异常。当您切换到id_tokens时出现如下认证错误:

出现以上问题后我们可以通过 pyjwt 的命令解密 CI_JOB_JWT 或者 VAULT_ID_TOKEN 来查看二者的差异:

  • CI_JOB_JWT
default:
    services:
      - name: vault:latest
        alias: vault
        variables:
            VAULT_DEV_ROOT_TOKEN_ID: "myroot"
            VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"

variables:
    VAULT_ADDR: "http://vault:8200"
    VAULT_TOKEN: "myroot"
    VAULT_AUTH_PATH: "jwt"

stages:
    - prepare
    - ping

prepare:
    stage: prepare
    image: centos:7.9.2009
    id_tokens:
        VAULT_ID_TOKEN:
            aud: https://jihulab.com
    script:
        # prepare linux system environment
        - yum install -y yum-utils python-jwt
        - yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
        - yum install -y vault 

        # prepare vault server service
        - sh vault/secrets/secretsCreate.sh
        - sh vault/policy/policiesCreate.sh
        - sh vault/role/rolesCreate.sh
        - sh vault/config/jwtConfig.sh
        - vault read auth/jwt/config
        
        # normal retrieve secrets from vault 
        - pyjwt decode --no-verify $CI_JOB_JWT

查看结果:

{
    "ref_protected": "true",
    "namespace_path": "xxxxxe",
    "user_id": "xxx",
    "job_id": "7291691",
    "iss": "jihulab.com", 
    "user_login": "xxxx",
    "project_path": "xxxxxxx",
    "nbf": xxxxx,
    "pipeline_id": "xxxxx",
    "namespace_id": "xxxxx",
    "jti": "d79d3cfa-ee4a-441b-82f3-774a70f519c8",
    "exp": 1681465203,
    "iat": 1681461603,
    "ref_type": "branch",
    "project_id": "xxxxxx",
    "ref": "production",
    "pipeline_source": "push",
    "user_email": "xxxxxxx",
    "sub": "xxxxxx"
}
  • id_tokens
default:
    services:
      - name: vault:latest
        alias: vault
        variables:
            VAULT_DEV_ROOT_TOKEN_ID: "myroot"
            VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"

variables:
    VAULT_ADDR: "http://vault:8200"
    VAULT_TOKEN: "myroot"
    VAULT_AUTH_PATH: "jwt"

stages:
    - prepare
    - ping

prepare:
    stage: prepare
    image: centos:7.9.2009
    id_tokens:
        VAULT_ID_TOKEN:
            aud: https://jihulab.com
    script:
        # prepare linux system environment
        - yum install -y yum-utils python-jwt
        - yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
        - yum install -y vault 

        # prepare vault server service
        - sh vault/secrets/secretsCreate.sh
        - sh vault/policy/policiesCreate.sh
        - sh vault/role/rolesCreate.sh
        - sh vault/config/jwtConfig.sh
        - vault read auth/jwt/config
        
        # normal retrieve secrets from vault 
        - pyjwt decode --no-verify $VAULT_ID_TOKEN

查看结果:

{
    "ref_protected": "true",
    "aud": "https://jihulab.com",
    "namespace_path": "xxxxxxx",
    "user_id": "xxxx",
    "job_id": "xxxxxx",
    "iss": "https://jihulab.com",
    "user_login": "xxxxx",
    "project_path": "xxxxxx",
    "nbf": 1681462273,
    "pipeline_id": "xxxxx",
    "namespace_id": "xxxxxx",
    "jti": "6c724cf4-30b7-45bc-ac98-e759ac5b0465",
    "exp": 1681465878,
    "iat": 1681462278,
    "ref_type": "branch",
    "project_id": "xxxxxx",
    "ref": "production",
    "pipeline_source": "push",
    "user_email": "xxxxxx",
    "sub": "xxxxxxxxx"
}

结合官方文档我们可以看出,两种使用方式的 issuer claims 是不一致的,在旧的使用方式中仅使用域名即可,但是新的方式中需要使用 url 的方式。因此切换使用方法时需要修改 vault 的 auth/jwt/config.bound_issuer才可以,不过官方文档并没有针对此改变进行补充说明,在实际使用过程中需要注意,此外为了预防CI_JOB_JWT在 16.x 版本后过期,请及时更新使用id_tokens