Gracefully handle space-delimited scopes in registry /jwt/auth requests
What does this MR do and why?
Fixes Gracefully handle blank spaces in scope query p... (#425045 - closed). Please read the issue description as it provides all the required context.
Given that this change is on a central place (JWT controller), and despite the vast test coverage, we're rolling this out using a feature flag (#427881 (closed)), with a percentage based rollout.
How to set up and validate locally
We'll assume the existence of the gitlab-org/gitlab-test
project in your GDK instance and use it for these tests. You can pick any other project, as long as the Container Registry feature is enabled for it.
We'll also assume that your GDK Rails instance is listening at gdk.test:3000
and you have a user root
with a PAT foobar
, with read permissions on the container registry. Your GDK registry setup must have auth_enabled: true
(docs).
We need to query the Rails API and decode a few JWT tokens during these tests. To do so you can either decode it with a JWT debugger on the web (e.g. https://jwt.io/) or use a CLI tool such as jwt-cli
. We'll use the latter. We'll also use httpie
to make the requests and jq
to parse the token from the response, but you can do that with any other tools or manually.
Current behavior
-
Open up a Rails console and a terminal window/pane.
-
On your terminal, obtain a JWT token with e.g.
pull
permissions for repositorygitlab-org/gitlab-test/foo
(works fine):http -a root:foobar 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 (timestamp fields will vary, the important part is
access
):Token header ------------ ... Token claims ------------ { "access": [ { "actions": [ "pull" ], "meta": { "project_path": "gitlab-org/gitlab-test" }, "name": "gitlab-org/gitlab-test/foo", "type": "repository" } ], ... }
-
Now let's do the same, but request permissions for two repositories, using two
scope
parameters (works fine):http -a root:foobar http://gdk.test:3000/jwt/auth \ client_id=="docker" \ service=="container_registry" \ scope=="repository:gitlab-org/gitlab-test/b:pull,push" scope=="repository:gitlab-org/gitlab-test/a:pull" | jq -r '.token' | jwt decode -
Output (timestamp fields will vary, the important part is
access
):Token header ------------ ... Token claims ------------ { "access": [ { "actions": [ "pull", "push" ], "meta": { "project_path": "gitlab-org/gitlab-test" }, "name": "gitlab-org/gitlab-test/b", "type": "repository" }, { "actions": [ "pull" ], "meta": { "project_path": "gitlab-org/gitlab-test" }, "name": "gitlab-org/gitlab-test/a", "type": "repository" } ], ... }
-
Now let's repeat, but use a space-delimited
scope
parameter (bug! notice how the returnedaccess
only contains one element, the one prior to the blank space):http -a root:foobar http://gdk.test:3000/jwt/auth \ client_id=="docker" \ service=="container_registry" \ scope=="repository:gitlab-org/gitlab-test/b:pull,push repository:gitlab-org/gitlab-test/a:pull" | jq -r '.token' | jwt decode -
Output (timestamp fields will vary, the important part is
access
):Token header ------------ ... Token claims ------------ { "access": [ { "actions": [ "pull", "push" ], "meta": { "project_path": "gitlab-org/gitlab-test" }, "name": "gitlab-org/gitlab-test/b", "type": "repository" } ], ... }
New behavior
-
Enable the
jwt_auth_space_delimited_scopes
feature flag;Feature.enable(:jwt_auth_space_delimited_scopes)
-
Repeat all the tests above. Those that worked should continue to work, the last one (bug), should now work as well, returning two objects within
access
, just like when we used twoscope
parameters.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.