Gracefully handle blank spaces in scope query params for the container registry /jwt/auth requests
Context
Related to Container Registry OCI Conformance (&10345 - closed). This was found to be the root cause for POST request to mount another repository's blob... (container-registry#1092 - moved).
Problem
Please see #425045 (comment 1556904912) for a detailed breakdown. The short version below should suffice though:
When making requests against the /jwt/auth endpoint of the Rails API (which must happen prior to making read/write requests against the container registry), clients send several query params, among which scope. The scope is usually comprised of a single value, as the vast majority of requests target a single repository. The format of this scope param looks like this:
repository:<path to container registry repository>:<operation(s) that a user is requesting permissions to>
And an example, when a token with pull and push permissions for the gitlab-com/registry-oci-conformance/repo-b container repository is being requested:
repository:gitlab-com/registry-oci-conformance/repo-b:pull,push
However, there is one type of registry operation (cross repository blob mounts) that require permissions for two separate repositories (the origin and the destination repositories for the blob mount). In those cases, we observe that most clients (like Docker) will use multiple scope params, one per repository, while others (like go-containerregistry) will use a single scope param with multiple values separated by a blank space.
For example, when mounting a blob from repo-a to repo-b, Docker will set the scope params as follows:
?scope="repository:repo-a:pull"&scope="repository:repo-b:push,pull"
While go-containerregistry will do:
?scope="repository:repo-a:pull repository:repo-b:push,pull"
The former is correct per the Docker Token Authentication Specification. The latter is also correct, but per RFC6749.
Right now, what's happening is that Rails discards whatever comes after the blank space in the scope param, which leads to a failure on the client side (for those that behave as go-containerregistry) as the token does not have the required permissions.
Solution
We should update the Rails logic for the container registry /jwt/auth requests so that it handles blank spaces gracefully, and splits the content of scope by blank space (if any). In summary, we expect the exact same behaviour and results regardless if the client sent a single scope with multiple values separated by a blank space or multiple scope parameters.