---
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