~zozs/srht-registry-devel

srht-registry: Add more documentation about sourcehut authentication flow v1 APPLIED

Linus Karlsson: 1
 Add more documentation about sourcehut authentication flow

 2 files changed, 94 insertions(+), 1 deletions(-)
#1290127 docker.yml success
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~zozs/srht-registry-devel/patches/54229/mbox | git am -3
Learn more about email & git

[PATCH srht-registry] Add more documentation about sourcehut authentication flow Export this patch

---
Add some documentation and stuff

 README.md                        |  2 +-
 docs/sourcehut_authentication.md | 93 ++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 docs/sourcehut_authentication.md

diff --git a/README.md b/README.md
index 1dc442a..b7da361 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ to perform authorization, and this separate service is implemented by this appli
srht-registry supports the following authentication methods:
* Username and password (regular `docker login`)
* Anonymous authentication (`docker pull` without previous login)
* Sourcehut CI/CD (builds.sr.ht) authentication by using the `oauth` grant in your build manifest
* [Sourcehut CI/CD (builds.sr.ht) authentication](docs/sourcehut_authentication.md) by using the `oauth` grant in your build manifest

The last method is the main benefit of using this implementation.
In short, it allows you to authorize a build running in builds.sr.ht to pull or push docker images, _without_ storing any long-lived secrets.
diff --git a/docs/sourcehut_authentication.md b/docs/sourcehut_authentication.md
new file mode 100644
index 0000000..f916d5d
--- /dev/null
+++ b/docs/sourcehut_authentication.md
@@ -0,0 +1,93 @@
# Sourcehut authentication

This is the main benefit of using `srht-registry`.

In short, it allows you to authorize a build running in builds.sr.ht to pull or push docker images, _without_ storing any long-lived secrets.
Instead, authentication to the container registry is done using the Sourcehut OAuth2 token.
This authorization server will then validate the token by contacting `meta.sr.ht`, and extract grants from the token, which is then used for authorization purposes.

## Flow

The flow looks like this, with these entities:
* Docker: The docker client of the user, on their local computer.
* Registry: The registry itself, i.e. an instance of [distribution/distribution](https://github.com/distribution/distribution/).
* srht-registry: An instance of this project.
* Sourcehut: A Sourcehut instance, e.g. sr.ht or a self-hosted instance.

```
Docker                   Registry         srht-registry           Sourcehut

| attempt pull from registry  
|--------------------------->|
                             |
       refer to authz server |
|<---------------------------|
|
| authenticate using sourcehut token
|---------------------------------------------->|   validate token
                                                |-------------------->|
                                                                      |
                                                    success/failure   |
                                                |<--------------------|
                                                |
               perform authorization and return |
                  token  with authorized grants |
|<----------------------------------------------|
|
|
| pull w. token
|--------------------------->|
                             |
                 return data |
|<---------------------------|
```

The steps are these:

1. The docker client attempts to pull something, e.g. using `docker pull registry.example.com/some/image:latest`. It contacts `registry.example.com` without any credentials.
2. The registry will return a response tell the client to authenticate by contacting a third-party service, in this case srht-registry. For example `auth.registry.examplec.com`.
3. The docker client sends credentials to srht-registry, in this case a placeholder username and as password a Sourcehut token with the correct grants.
4. srht-registry will validate the token, by performing the following steps:
   1. Send a test request to the Sourcehut instance, since this is the only way to check that the signature of the token is correct.
   2. If the token was signed correctly, srht-registry proceeds with parsing the token, extracting the grant string and expiry date.
   3. Check that the grant contains `registry.example.com/REGISTRY:RW` (or is empty), this ensures that token is not just any token, but meant for container images.
   4. Extracts the username and uses it to check the ACL for authorization.
5. Return a signed JWT to the Docker client.
6. The docker client attaches the signed JWT to the request to the registry. The registry checks that it is signed with the correct key (the public key or srht-registry is shared with the registry).
7. Registry allows push or pull.

## Sourcehut tokens in builds.sr.ht

The main purpose of srht-registry is to make it easy to push from a builds.sr.ht pipeline.
This is easily done by using a build manifest such as this.
Note specifically that the `oauth:` line requests a short-lived token with the correct grant.

```yaml
image: alpine/edge
packages:
- docker
- docker-cli-buildx
sources:
- https://git.sr.ht/~zozs/test
oauth: "registry.example.com/REGISTRY:RW" # important: will generate a sourcehut oauth2 token with the correct grant
tasks:
- setup: |
    sudo service docker start
    sudo addgroup $USER docker
- buildpush: |
    cd test
    set +x
    docker login registry.zozs.se -u sourcehut -p "$OAUTH2_TOKEN"
    set -x
    docker buildx build --push --tag registry.zozs.se:zozs/test:latest .
```

## Grant strings

Currently, srht-registry accepts either a grant string that contains `registry.example.com/REGISTRY:RW` (with the correct domain), or a completely empty grant string (which corresponds to all access in other parts of sourcehut).

Setting the grant string to `registry.example.com/REGISTRY:RW` is preferred, since this ensures that the token *can only be used for srht-registry*.
In particular, it means that you don't have to trust srht-registry, since the token *cannot* be used to read or modify any Sourcehut data.

Support for an empty grant string is included because it allows Personal Access Tokens to be used also for pushing or pulling images.
These tokens have a closed set of allowed grant strings, so they cannot include `registry.example.com/REGISTRY:RW`.
-- 
2.46.0
srht-registry/patches/docker.yml: SUCCESS in 4m17s

[Add more documentation about sourcehut authentication flow][0] from [Linus Karlsson][1]

[0]: https://lists.sr.ht/~zozs/srht-registry-devel/patches/54229
[1]: mailto:linus@zozs.se

✓ #1290127 SUCCESS srht-registry/patches/docker.yml https://builds.sr.ht/~zozs/job/1290127