Skip to content

Attribute namespace_path on JWT payload should include only top level group

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Summary

The namespace_path attribute in the payload sent from GitLab to HashiCorp Vault includes subgroup information when it should contain only the top-level group. This results in an inconsistency where namespace_path and project_path both include subgroup details.

For example: 
Project _‘xyz’_ is under the group _/namespace/a/b_ so the namespace_path sent in the JWT payload from GitLab is /namespace/a/b_ instead of _/namespace/a_, which is what I'd expect after reading our docs on the topic.

Use cases where namespace_path is used in the bound claims lead to the creation of several unique entities/identities, depending on how many unique values are sent, which can become costly and inefficient.

References: Use HashiCorp Vault secrets in GitLab CI/CD#How it works


Steps to reproduce

  1. Set up a GitLab project within a nested group structure (e.g., group/subgroup/project).
  2. Configure HashiCorp Vault integration with GitLab.
  3. Trigger a payload to be sent from GitLab to Vault (e.g., by accessing a secret or initiating a CI/CD job).
  4. Observe the values of namespace_path and project_path in the payload.

Example Project

TBD


What is the current bug behavior?

  • namespace_path includes subgroup details (e.g., group/subgroup).
  • project_path includes the full path as expected (e.g., group/subgroup/project).

What is the expected correct behavior?

  • namespace_path should only include the top-level group (e.g., group).
  • project_path should continue to include the full path as expected (e.g., group/subgroup/project).

Relevant logs and/or screenshots

Here’s an example of the payload received by Vault:

{
  "namespace_id": "12345",
  "namespace_path": "maingroup/subgroup1",
  "project_id": "12345",
  "project_path": "maingroup/subgroup1/projectA",
  "user_id": "12345",
  "user_login": "xyz",
  "user_email": "xyz@email.com",
  "user_access_level": "developer",
  "pipeline_id": "12345678",
  "pipeline_source": "push",
  "job_id": "1234567",
  "ref": "Test",
  "ref_type": "branch",
  "ref_path": "refs/heads/Test",
  "ref_protected": "false",
  "groups_direct": [
    “maingroup/subgroup1
  ],
  "runner_id": 91234567,
  "runner_environment": "self-hosted",
  "sha": "xyzwrerererere",
  "project_visibility": "private",
  "ci_config_ref_uri": "gitlab.com/maingroup/subgroup1/projectA//.gitlab-ci.yml@refs/heads/Test",
  "ci_config_sha": "xyzwrerererere",
  "jti": "1234567-4321-1234-ae12-1233443455cdf",
  "iat": 123456789,
  "nbf": 123456789,
  "exp": 123456789,
  "iss": "https://gitlab.com",
  "sub": "project_path:/maingroup/subgroup1/projectA:ref_type:branch:ref:Test",
  "aud": "https://gitlab.com"
}

Expected payload:

{
  "namespace_path": "group",
  "project_path": "group/subgroup/project"
}

Workaround

Have an aud key sent in ID_TOKEN from GitLab to vault during authentication (see below for a CI script snippet), and it is common for all projects in a group. So in the JWT role, you can set the user_claim as user_claim:aud instead of setting user_claim:namespace_path:

id_tokens:
    JWT_VAULT:
      aud: XXXXXXXXXXXX

Output of checks

Possible fixes

Review the code responsible for constructing the namespace_path attribute in the Vault payload. Ensure it truncates the path to the top-level group.


Edited by 🤖 GitLab Bot 🤖