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
- Set up a GitLab project within a nested group structure (e.g.,
group/subgroup/project). - Configure HashiCorp Vault integration with GitLab.
- Trigger a payload to be sent from GitLab to Vault (e.g., by accessing a secret or initiating a CI/CD job).
- Observe the values of
namespace_pathandproject_pathin the payload.
Example Project
TBD
What is the current bug behavior?
-
namespace_pathincludes subgroup details (e.g.,group/subgroup). -
project_pathincludes the full path as expected (e.g.,group/subgroup/project).
What is the expected correct behavior?
-
namespace_pathshould only include the top-level group (e.g.,group). -
project_pathshould 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.