Proposed API for additional claims within CI_JOB_JWT
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Release notes
Adding API to control additional claims within CI_JOB_JWT
Problem to solve
Using the CI_JOB_JWT with external services is hampered by the inflexibility of the claims found within. While each CI_JOB_JWT contains useful claims, the inability to add claims make integration with external services difficult, if not impossible.
The JWT RFC7519 specifies a group of "Registered Claim Names". Despite suggesting "None of the claims...are intended to be mandatory to use or implement in all cases", some external services depend on the existence of these claims. For example, AWS requires the presence (and thus validation) of an "aud" claim to support AssumeRoleWithWebIdentity. Additionally, the current inflexible solution does not allow for adding any Public Claim Names or Private Claim Names to support external systems requiring any other claim.
Systems known to benefit from this proposal (due to their support/use of JWT tokens) include:
- AWS
- GCloud
- Azure
- Kubernetes
To facilitate individual job control of claims, the following proposal is offered as a solution to adding additional claims via an API, as an extension of the current job/stage spec.
Intended users
- Cameron (Compliance Manager)
- Devon (DevOps Engineer)
- Sidney (Systems Administrator)
- Sam (Security Analyst)
- Alex (Security Operations Engineer)
- Allison (Application Ops)
- Priyanka (Platform Engineer)
User experience goal
The user should be able to specify any additional claim for a project like this:
MyJob:
jwt_claims:
- aud:
sts.amazonaws.com
script:
- aws sts assume-role-with-web-identity --role-arn "${AWS_ROLE_ARN}" --role-session-name "${CI_JOB_ID}:${CI_ENVIRONMENT_SLUG}" --web-identity-token "${CI_JOB_JWT}"
Proposal
- Add an optional "jwt_claims" section for each job, giving users the ability to supply additional claims.
- Additional claims defined at group/subgroup/project level default to immutable (
mutable:false). - Additional claims defined at group/subgroup/project level are inherited by the job running within, and honor mutability rules (ie, if a claim at the group level is
mutable:false, the claim cannot be modified at the subgroup/project level - this results in a failed job exeuction). - Jobs MAY add claims not explicitly enumerated at group/subgroup/project level.
- Jobs MAY modify claims set at group/subgroup/project level ONLY if these claims are defined with
mutable:true. - Jobs MAY NOT modify claims set at group/subgroup/project level if these claims are defined with
mutable:false. This will be enforced at the linter level, as well as failing jobs which attempt to violate the rule. - Jobs MAY NOT modify built-in claims. These built-in claims are treated as
mutable:false. This will be enforced at the linter level, as well as failing jobs which attempt violate the rule.
Further details
unknown
Permissions and Security
Adding this claim will have no impact on permissions/security of Gitlab itself.
However, control of claims should be considered carefully to prevent privilege escalation in external services. Specifically, additional claims found in "jwt_claims" section SHALL NOT overwrite the default claims currently supplied in each CI_JOB_JWT. For example, if the user supplies a "nbf" or "user_email" claim, these will be discarded. Their values within the CI_JOB_JWT will continue to be autogenerated and considered immutable (from the perspective of the user creating/running the job).
Documentation
Related to this ticket to support Terraform
Availability & Testing
unknown
What does success look like, and how can we measure that?
- When no additional job claims are made, CI_JOB_JWT contains only built-in claims.
- The entire job execution fails if any additional job claim is an attempt to modify an existing claim which has
mutable:falseset. This includes built-in claims. - The CI_JOB_JWT contains built-in claims, as well as any claims set for this job (in the
.gitlab-ci.ymlfile), AND those inherited from the group/subgroup/project hierarchy the job runs in.
What is the type of buyer?
This should be built-in for every user to facilitate easy/safe integration with any services consuming JWT tokens.
Is this a cross-stage feature?
unknown