feat(#3517): register the swarm collector as an audienced oauth2 client

The forge's `/metrics` is published behind the gateway and denied to
everyone, waiting on a client to allow. This is that client.

An audience is a URL: authelia validates a bearer token against the
address being requested, and a client may only request an audience it is
registered for, so registration is the authorisation. The URLs are owned
by the services that publish them while audiences attach to one client,
so services contribute to a list and this module builds the single entry
— the `gateway.localNames` split, forced here by client definitions
concatenating rather than merging into a shared entry.

The access-control rule asks the client list whether the collector is
registered rather than re-deriving the conditions that register it. The
two drifting is not a build failure: authelia refuses a rule naming an
unknown client in its startup validator, so SSO fails to restart.
This commit is contained in:
atlas 2026-08-24 12:53:23 +02:00
commit 3895a1e21d
3 changed files with 145 additions and 26 deletions

View file

@ -442,6 +442,18 @@ in
url = "https://${cfg.domain}/";
};
# The address a scraper has to hold a token for. Same `behindGateway`
# guard, and for a stronger reason than the two above: with it off
# there is no `= /metrics` location and no `auth_request` in front of
# it, so the URL this names does not exist to be authorised.
#
# ⚠️ Written as the exact URL a collector requests, because that is
# what authelia compares against — this string agreeing with the
# `location` block above it is the whole mechanism. A near miss is a
# correctly minted token refused at the target.
services.hyperhive.swarm.otel.collectorAudiences =
lib.optional cfg.behindGateway "https://${cfg.domain}/metrics";
# `server_name = forge.domain`, proxies all `/` → forgejo. Tuned for
# git: `client_max_body_size 1G`, `proxy_read_timeout 1h` (multi-GB
# clones). SSH stays direct on `forge.sshPort`. See