Add basic auth support to Maven download endpoints
🌳 Context
The Maven Repository (docs) exposes a single download endpoint which is basically used to download files (be it .pom
, .xml
or .jar
files).
Now, the Maven Repository can be accessed at 3 different levels:
- project level. The url looks like:
GET /api/v4/projects/:id/packages/maven/*path/:file_name
. - group level. The url looks like:
GET /api/v4/groups/:id/-/packages/maven/*path/:file_name
. - instance level. The url looks like:
GET GET /api/v4/packages/maven/*path/:file_name
.
Effectively, we have 3
endpoints implemented but their logic is generally similar: check the credentials/permissions, locate the target package file and return it.
Regarding authentication, as documented, the Maven Repository only supports custom http headers.
The problem that we have is that we can have some clients of the Maven Repository, namely SBT, that doesn't support custom http headers. Instead, they support only basic auth. As such, $ sbt
can't pull dependencies from a GitLab Maven Repository. This is blocking some users from using the Maven Repository as seen in An alternate way to download binary packages fr... (#212854 - closed).
🚑 The solution
Well, the solution is to allow all accepted token types (pat, deploy tokens and ci job tokens) to be sent through basic auth. This means that all 3
download endpoints will need to be updated for that.
Why change only the download endpoints? Awesome, that is a very good question.
As seen here, $ sbt
allows uploading files to a Maven Repository. Unfortunately from what we have seen in local testing, it does it in a way that is not really compliant or better said expected by the backend. As such, we could have Maven Repository uploaded files that the backend will consider as incomplete or erroneous.
Applying the iteration value here, we're going to add support for $ sbt
incrementally:
- first the download endpoints to allow pulling dependencies. (This MR).
- if needed, the upload endpoint to allow publishing files. We created Support artifacts upload from SBT (#408479 - closed) for that.
🔍 What does this MR do and why?
- Adds basic auth support to all download endpoints of the Maven Repository.
- Updates the relevant specs.
- Updates the relevant documentation.
🔭 Screenshots or screen recordings
No UI changes
⚙ How to set up and validate locally
- Add a maven package that follows the naming convention. gl_pru can help here.
1️⃣ Using $ mvn
We're going to use $ mvn
to assert that our changes has no impact on sending credentials with a custom header.
We're using
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>gl.pru</groupId>
<artifactId>MyPackage</artifactId>
<packaging>jar</packaging>
<version>3.0.1</version>
<name>MyPackage</name>
<url>http://maven.apache.org</url>
<properties>
<maven.compiler.source>7</maven.compiler.source>
<maven.compiler.target>7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>### package maven group id ###</groupId>
<artifactId>### package maven artifact id ###</artifactId>
<version>### package version ###</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>gitlab-maven</id>
<url>### endpoint_url ###</url>
</repository>
</repositories>
</project>
settings.xml
<?xml version="1.0" encoding="utf-8"?>
<settings>
<servers>
<server>
<id>gitlab</id>
<configuration>
<httpHeaders>
<property>
<name>### token name, see https://docs.gitlab.com/ee/user/packages/maven_repository/#edit-the-settingsxml ###</name>
<value>### token value ###</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>
We will pull the dependency with
$ mvn compile -s settings.xml
Results
Project level endpoint:
token type | result |
---|---|
PAT | |
deploy token | |
ci job token |
Group level endpoint:
token type | result |
---|---|
PAT | |
deploy token | |
ci job token |
Instance level endpoint:
token type | result |
---|---|
PAT | |
deploy token | |
ci job token |
All cases are working!
2️⃣ Using $ sbt
Let's see how things go with sbt.
We're using
build.sbt
import Dependencies._
ThisBuild / scalaVersion := "2.12.8"
ThisBuild / version := "1.5.10"
ThisBuild / organization := "com.example"
ThisBuild / organizationName := "example"
lazy val root = (project in file("."))
.settings(
name := "hello",
libraryDependencies += scalaTest % Test
)
libraryDependencies += "<package maven group id>" % "<package maven artifact id>" % "<package version>"
resolvers += ("gitlab" at "<endpoint url>").withAllowInsecureProtocol(true)
credentials += Credentials("GitLab Packages Registry", "gdk.test", "<token name>", "<token>")
We will pull the dependency with
$ sbt compile
Results
Project level endpoint:
token type | result |
---|---|
PAT | |
deploy token | |
ci job token |
Group level endpoint:
token type | result |
---|---|
PAT | |
deploy token | |
ci job token |
Instance level endpoint:
token type | result |
---|---|
PAT | |
deploy token | |
ci job token |
$ sbt
was able to pull the dependency in all cases!
🔮 Conclusions
This MR is working as expected
🚥 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.