Skip to content

Modify /jwt/auth endpoint for registry tag protection feature

João Pereira requested to merge registry-jwt-ptags into master

What does this MR do and why?

Related to https://gitlab.com/gitlab-org/gitlab/-/issues/499874.

The rational behind the changes in this MR is described in detail here. These changes sit behind a new feature flag (https://gitlab.com/gitlab-org/gitlab/-/issues/505455+).

References

Please include cross links to any resources that are relevant to this MR This will give reviewers and future readers helpful context to give an efficient review of the changes introduced.

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

Not applicable as the corresponding frontend changes (https://gitlab.com/gitlab-org/gitlab/-/issues/499871) are not yet implemented.

How to set up and validate locally

We'll assume that you have a gitlab-org/gitlab-test project in your GDK, and a PAT from a user with Owner role with read/write registry permissions. Set the CR_PAT environment variable to the PAT value and CR_USER to the username.

For these tests I'm going to use the jq and jwt CLI tools to facilitate parsing the output of requests. Adjust the curl commands if you don't want to use them (in which case you'll have to manually parse and decode the tokens).

  1. First make a test with the FF disabled (default). To do so we need to obtain a token from the /jwt/auth endpoint:

    curl -s -u "$CR_USER:$CR_PAT" \
        -G \
        --data-urlencode "service=container_registry" \
        --data-urlencode "scope=repository:gitlab-org/gitlab-test:pull,push" \
        http://gdk.test:3000/jwt/auth | jq -r '.token' | jwt decode -j - | jq -r '.payload.access'
    [
      {
        "actions": [
          "pull",
          "push"
        ],
        "meta": {
          "project_id": 2,
          "project_path": "gitlab-org/gitlab-test",
          "root_namespace_id": 24
        },
        "name": "gitlab-org/gitlab-test",
        "type": "repository"
      }
    ]

Note that there is no meta.tag_deny_access_patterns key.

  1. Now let's enable the FF for our project in the Rails console:

    project = Project.find_by_full_path 'gitlab-org/gitlab-test'
    Feature.enable(:container_registry_protected_tags, project)
  2. Repeat the request. You should see exactly the same output as there are no configured rules for this project.

  3. Now let's create some rules:

    project.container_registry_protection_tag_rules.create(tag_name_pattern: 'latest', minimum_access_level_for_push: Gitlab::Access::MAINTAINER, minimum_access_level_for_delete: Gitlab::Access::MAINTAINER)
    project.container_registry_protection_tag_rules.create(tag_name_pattern: 'precious', minimum_access_level_for_push: Gitlab::Access::OWNER, minimum_access_level_for_delete: Gitlab::Access::OWNER)
  4. Repeat the request. You should see:

    [
      {
        "actions": [
          "pull",
          "push"
        ],
        "meta": {
          "project_id": 2,
          "project_path": "gitlab-org/gitlab-test",
          "root_namespace_id": 24,
          "tag_deny_access_patterns": {
            "push": []
          }
        },
        "name": "gitlab-org/gitlab-test",
        "type": "repository"
      }
    ]

Note the meta.tag_deny_access_patterns object is now present, and the empty push array within, even though our user (as an admin) has no tag restrictions.

  1. Now set the CR_USER and CR_PAT variables to a username/PAT of a user with the Developer role in this project.

  2. Repeat the request. You should see:

    [
      {
        "actions": [
          "pull",
          "push"
        ],
        "meta": {
          "project_id": 2,
          "project_path": "gitlab-org/gitlab-test",
          "root_namespace_id": 24,
          "tag_deny_access_patterns": {
            "push": [
              "latest",
              "precious"
            ]
          }
        },
        "name": "gitlab-org/gitlab-test",
        "type": "repository"
      }
    ]
  3. Promote the user to Maintainer in this project, and then repeat the request. We can also test the delete action:

    curl -s -u "$CR_USER:$CR_PAT" \
        -G \
        --data-urlencode "service=container_registry" \
        --data-urlencode "scope=repository:gitlab-org/gitlab-test:pull,push,delete" \
        http://gdk.test:3000/jwt/auth | jq -r '.token' | jwt decode -j - | jq -r '.payload.access'
    [
      {
        "actions": [
          "pull",
          "push",
          "delete"
        ],
        "meta": {
          "project_id": 2,
          "project_path": "gitlab-org/gitlab-test",
          "root_namespace_id": 24,
          "tag_deny_access_patterns": {
            "delete": [
              "precious"
            ],
            "push": [
              "precious"
            ]
          }
        },
        "name": "gitlab-org/gitlab-test",
        "type": "repository"
      }
    ]

Database Review

See !171566 (comment 2245129044).

Edited by João Pereira

Merge request reports

Loading