Skip to content

Embed dedicated JWT container user info in container registry JWT

Adie (she/her) requested to merge 394965-add-user-info-to-jwt into master

What does this MR do and why?

In this MR, we add an encrypted user field to the JWT claims. This new fields contains fields that Rails will need to identify which user or deploy token made the request and increment usage metrics. The registry, upon receiving this encrypted user object, will simply pass it back to Rails as part of the event notification payload.

Background

As part of Container Registry GMAU: Track usage (&8213), we keep track of container registry usage by using webhook notifications emitted by the registry and consumed by GitLab Rails. In Container Registry: Process webhook notificatio... (#385497 - closed) we started tracking tag creation and deletion, followed by Container Registry: Process webhook notificatio... (#382568 - closed).

The event notification payload contains an actor: {} object with a name and a user_type key in it as defined in the registry documentation. The registry populates this information, based on the JWT claims offered by the /jwt/auth endpoint on a successful user authentication

With `name it is not enough to fetch which deploy token it is so we need more information which is added in this MR.

Current behavior

  1. Checkout the master branch (git checkout master)
  2. In your terminal, obtain a JWT token (i.e. with pull permissions for repository gitlab-org/gitlab-test/foo). Replace password with your local password:
   http -a root:'password' http://gdk.test:3000/jwt/auth  client_id=="docker"  service=="container_registry" scope=="repository:gitlab-org/gitlab-test/foo:pull" | jq -r '.token' | jwt decode -

Output (timestamps will vary):

Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "MZ6P:4ZAC:TVCN:SJ7O:MP5A:OVMJ:KQL5:FC43:SBDR:6H2K:HBO2:IZ7M"
}

Token claims
------------
{
  "access": [
    {
      "actions": [
        "pull"
      ],
      "meta": {
        "project_path": "gitlab-org/gitlab-test"
      },
      "name": "gitlab-org/gitlab-test/foo",
      "type": "repository"
    }
  ],
  "aud": "container_registry",
  "auth_type": "gitlab_or_ldap",
  "exp": 1690617690,
  "iat": 1690617390,
  "iss": "gitlab-issuer",
  "jti": "db6b2f72-60f3-40d2-8259-4a2a6751468f",
  "nbf": 1690617385,
  "sub": "root"
}

New behavior

  1. Check out this MR's branch: git checkout 394965-add-user-info-to-jwt
  2. Obtain a JWT, same as above, and observe the new user field
   http -a root:'password' http://gdk.test:3000/jwt/auth  client_id=="docker"  service=="container_registry" scope=="repository:gitlab-org/gitlab-test/foo:pull" | jq -r '.token' | jwt decode -
Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "MZ6P:4ZAC:TVCN:SJ7O:MP5A:OVMJ:KQL5:FC43:SBDR:6H2K:HBO2:IZ7M"
}

Token claims
------------
{
  "access": [
    {
      "actions": [
        "pull"
      ],
      "meta": {
        "project_path": "gitlab-org/gitlab-test"
      },
      "name": "gitlab-org/gitlab-test/foo",
      "type": "repository"
    }
  ],
  "aud": "container_registry",
  "auth_type": "gitlab_or_ldap",
  "exp": 1690616353,
  "iat": 1690616053,
  "iss": "gitlab-issuer",
  "jti": "436c0373-af8a-4efd-bf3a-abc7ce1e98ab",
  "nbf": 1690616048,
  "sub": "root",
  "user": "eyJraWQiOiJNWjZQOjRaQUM6VFZDTjpTSjdPOk1QNUE6T1ZNSjpLUUw1OkZDNDM6U0JEUjo2SDJLOkhCTzI6SVo3TSIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJ1c2VyX2luZm8iOnsidG9rZW5fdHlwZSI6ImdpdGxhYl9vcl9sZGFwIiwidXNlcm5hbWUiOiJyb290IiwidXNlcl9pZCI6MX0sImp0aSI6IjBhMjU5YzRhLTUwZjQtNDRlNS05ODlhLWE0MGE4M2E3ZDE4OCIsImlhdCI6MTY5MDYxNjA1MywibmJmIjoxNjkwNjE2MDQ4LCJleHAiOjE2OTA2MTYxMTN9.aSqUCvCUTvgmbbcSOA-FGYG2suRS1SOm6kreeaYWk7FEnq9ZV7p1bGXbH7EQyZxyk7n9i3vWk6gbThLQJlnb0GmFfhbVC1cU9ndSBz07PNXl-1qu5sNQDeEjM0mtyMNtyMXGFYeBXh6YF8ic6YISyLS-co9INy9neyu1Vqs00HbdACGKnHrio2tSfUgXPwLWFG-t6_sUal0xk0vbqKu77SkmWKsqrTb27sMXHnJFwkmfN2AaAaNuXkwF4GRO5XfTU2pkTz2M7N5XIljC4lA_GYqRSgjdaFB_-ZijE55mFM3DRbXKwxEDD-jQOOZLiztxzvsnZF4n6Bv6VEiunA3ukA"
}
  1. Copy the value of user and paste it into a JWT decoder like https://jwt.io or you can also use the command line:
jwt decode "eyJraWQiOiJNWjZQOjRaQUM6VFZDTjpTSjdPOk1QNUE6T1ZNSjpLUUw1OkZDNDM6U0JEUjo2SDJLOkhCTzI6SVo3TSIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJ1c2VyX2luZm8iOnsidG9rZW5fdHlwZSI6ImdpdGxhYl9vcl9sZGFwIiwidXNlcm5hbWUiOiJyb290IiwidXNlcl9pZCI6MX0sImp0aSI6IjBhMjU5YzRhLTUwZjQtNDRlNS05ODlhLWE0MGE4M2E3ZDE4OCIsImlhdCI6MTY5MDYxNjA1MywibmJmIjoxNjkwNjE2MDQ4LCJleHAiOjE2OTA2MTYxMTN9.aSqUCvCUTvgmbbcSOA-FGYG2suRS1SOm6kreeaYWk7FEnq9ZV7p1bGXbH7EQyZxyk7n9i3vWk6gbThLQJlnb0GmFfhbVC1cU9ndSBz07PNXl-1qu5sNQDeEjM0mtyMNtyMXGFYeBXh6YF8ic6YISyLS-co9INy9neyu1Vqs00HbdACGKnHrio2tSfUgXPwLWFG-t6_sUal0xk0vbqKu77SkmWKsqrTb27sMXHnJFwkmfN2AaAaNuXkwF4GRO5XfTU2pkTz2M7N5XIljC4lA_GYqRSgjdaFB_-ZijE55mFM3DRbXKwxEDD-jQOOZLiztxzvsnZF4n6Bv6VEiunA3ukA"

Output:

Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "MZ6P:4ZAC:TVCN:SJ7O:MP5A:OVMJ:KQL5:FC43:SBDR:6H2K:HBO2:IZ7M"
}

Token claims
------------
{
  "exp": 1690616113,
  "iat": 1690616053,
  "jti": "0a259c4a-50f4-44e5-989a-a40a83a7d188",
  "nbf": 1690616048,
  "user_info": {
    "token_type": "gitlab_or_ldap",
    "user_id": 1,
    "username": "root"
  }
}

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #394965 (closed)

Edited by Adie (she/her)

Merge request reports