Trouble with Claims in Gitlab CI

Cross-posted on the Gitlab Forum: Trouble with Vault Claims - GitLab CI/CD - GitLab Forum

I have Gitlab CI set up to load secrets from vault.
I usually use it like this:

deploy:dev:
  secrets:
    SSH_KEY_FILE:
      vault: web/deployer/ssh/private_key@gitlabci

I have a group dept-1 with group-level variables:

  • VAULT_SERVER_URL: https://myvault.example.com
  • VAULT_AUTH_PATH: gitlabjwt

In vault, I have a policy to allow access:

$ vault read auth/gitlabjwt/config
Key                       Value
---                       -----
bound_issuer              gitlab.example.com
default_role              dept-1
jwks_ca_pem               n/a
jwks_url                  https://gitlab.example.com/-/jwks
jwt_supported_algs        []
jwt_validation_pubkeys    []
namespace_in_state        false
oidc_client_id            n/a
oidc_discovery_ca_pem     n/a
oidc_discovery_url        n/a
oidc_response_mode        n/a
oidc_response_types       []
provider_config           map[]
$ vault read auth/gitlabjwt/role/dept-1
Key                        Value
---                        -----
allowed_redirect_uris      <nil>
bound_audiences            <nil>
bound_claims               map[namespace_path:dept-1/*]
bound_claims_type          glob
bound_subject              n/a
claim_mappings             <nil>
clock_skew_leeway          0
expiration_leeway          0
groups_claim               n/a
max_age                    0
not_before_leeway          0
oidc_scopes                <nil>
policies                   [gitlabci]
role_type                  jwt
token_bound_cidrs          []
token_explicit_max_ttl     1m
token_max_ttl              0s
token_no_default_policy    false
token_num_uses             0
token_period               0s
token_policies             [gitlabci]
token_ttl                  0s
token_type                 default
user_claim                 user_email
user_claim_json_pointer    false
verbose_oidc_logging       false
$ vault policy read gitlabci
path "gitlabci/*" {
  capabilities = ["read", "list"]
}
$

This all works fine.

I want to add another group using the same jwt, so I added this vault policy:

$ vault read auth/gitlabjwt/role/dept-2
Key                        Value
---                        -----
allowed_redirect_uris      <nil>
bound_audiences            <nil>
bound_claims               map[namespace_path:dept-2/*]
bound_claims_type          glob
bound_subject              n/a
claim_mappings             <nil>
clock_skew_leeway          0
expiration_leeway          0
groups_claim               n/a
max_age                    0
not_before_leeway          0
oidc_scopes                <nil>
policies                   [gitlabci]
role_type                  jwt
token_bound_cidrs          []
token_explicit_max_ttl     1m
token_max_ttl              0s
token_no_default_policy    false
token_num_uses             0
token_period               0s
token_policies             [gitlabci]
token_ttl                  0s
token_type                 default
user_claim                 user_email
user_claim_json_pointer    false
verbose_oidc_logging       false
$

In group dept-2, I set these group-level variables:

  • VAULT_SERVER_URL: https://myvault.example.com
  • VAULT_AUTH_PATH: gitlabjwt
  • VAULT_AUTH_ROLE: dept-2

When I run jobs in dept-2, I get this error:

ERROR: Job failed (system failure): resolving secrets: initializing Vault service: preparing authenticated client: authenticating Vault client: writing to Vault: api error: status code 400: error validating claims: claim "namespace_path" does not match any associated bound claim values

What am I missing?

On a quick glance I’m not seeing anything obvious.

However, I’ve run into similar issues before. Is the GitLab namespace/group Display Name different than what’s in the URI? The claim needs to match what you see in the address bar or it’ll fail with the same message you’re seeing.

And now it is resolved - it turns out all the projects in dept-1 are in subgroups, but all the projects in dept-2 are in the main group. namespace_path:dept-2/* only matches subgroups, but does not match the group itself. We changed to namespace_path:dept-2 and now it works.

Interesting. Does the /* match any subgroup recursively or just a single level?