Fix how maven dependency proxy credentials are sent
🔭 Context
The Maven dependency proxy is a feature where users can put the GitLab instance in the middle between package manager clients and (upstream) registries:
We are looking to the dependency proxy for maven packages:
$ mvn <-> GitLab <-> Maven compatible registry
Since, GitLab is located in the middle, we take this opportunity to "cache" the responses going through so that when the exact same request is received we can reply back with the cached version.
To make sure that the cached version is the same one as the upstream registry, we HEAD
the registry.
The upstream registry can be public or private which means that users can pass credentials. In case of Maven registries, credentials are passed using Basic Auth (username+password).
In Maven dependency proxy: invalid urls in HEADs (#471052), it has been found out that we have an issue when the username contains the @
character. The problem was identified in the logic that checks the upstream registry.
In this logic, we inline the basic auth credentials in the upstream url (example: https://<username>:<password>@<upstream url>
). The problem with the inline approach is that if we have an @
in the username (or even password actually), we could have http clients that gets confused. It seems that it's the case for the client used to check the upstream registry, we end up in a similar situation like:
URI.parse("http://me@email.com:password@test.org/test")
which ends up
URI::InvalidURIError: bad URI(is not URI?): "http://me@email.com:password@test.org/test"
🤔 What does this MR do and why?
This MR changes how credentials are sent to upstream in the maven dependency proxy.
- Generate the correct
Authorization
header when interacting with the upstream registry. - Remove the inline credentials from the upstream url generation logic.
- Update the related specs.
🏎 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
⚙ How to set up and validate locally
- Create a project.
- Have a PAT ready (
maintainer+
level). - Let's simulate a (dummy) upstream registry locally with
sinatra
:require 'sinatra' set :bind, 'gdk.test' use Rack::Auth::Basic,"Protected Area" do |username, password| username == 'user@test.com' && password == 'password' end get "/*" do "Hello World!" end
- In the project settings,
Packages and registries settings
, enable the maven dependency proxy with:
- url:
http://gdk.test:4567
- username:
user@test.com
- password:
password
All ready!
Now, let's pull a file through the maven dependency proxy. We're going to use $ curl
to simulate that request.
$ curl "http://<username>:<pat>@gdk.test:8000/api/v4/projects/<project_id>/dependency_proxy/packages/maven/gl/pru/My.Ananas/13.0.3/My.Ananas-13.0.3.pom"
This very first request will succeed and create the cached version on GitLab. You can see it in the Package Registry
(under the Deploy
menu).
Let's request it again (second time).
master
On $ curl "http://<username>:<pat>@gdk.test:8000/api/v4/projects/<project_id>/dependency_proxy/packages/maven/gl/pru/My.Ananas/13.0.3/My.Ananas-13.0.3.pom"
{"message":"500 Internal Server Error"}
The URI.parse
failing.
MR
With this $ curl "http://<username>:<pat>@gdk.test:8000/api/v4/projects/<project_id>/dependency_proxy/packages/maven/gl/pru/My.Ananas/13.0.3/My.Ananas-13.0.3.pom"
Hello World!
Fixed!