Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/nix/host-modules/glue-controller-oidc-client.nix
atlas 1e8c398132 swarm-controller: get its otlp pushes past the collector, log failures
The collector's oidc/swarm authenticator verifies the bearer offline as a
JWT. The controller's authelia client was registered without
accessTokenSignedResponseAlg, so authelia mints it an opaque
authelia_at_ handle, which that authenticator cannot verify: by config,
no push from the vcs or jobq exporter can be accepted. Register it with
RS256 like every other client whose token lands on an oidc/* receiver.

The SDK logs a failed export at debug only, so a refused push never
reached the journal. AuthenticatedHttpClient now warns on a failed token
mint, a transport error, or a non-2xx answer (status plus a body
snippet), once per kind of failure and again every 10 minutes with a
count, and logs once when a push succeeds after failing.

Refs #5393
2026-10-17 09:44:33 +02:00

52 lines
2.3 KiB
Nix

# Glue: register the swarm controller as an OIDC client wherever authelia runs.
#
# ONE PAIRING PER FILE — swarm-controller ← authelia, and nothing else. Deleting
# this leaves a controller whose token requests authelia answers with a 401, and
# no minted secret for swarm-secret-publish to put in the store.
#
# ⚠️ Gated on authelia being HERE, and NOT on this host running the controller.
# A client is a row in THIS host's provider config, so it is declared where that
# config is rendered; ./swarm-controller.nix's `config` hangs off
# `deploy.swarm-controller.enable`, which answers a question about a different
# host. Same shape as ./glue-grafana-oidc-client.nix.
#
# Registered whether or not the swarm runs a controller: nothing in `swarm.*`
# records that, so the cost of a swarm without one is one unused client and one
# unused minted secret.
{
lib,
config,
...
}:
let
hyperhiveCfg = config.services.hyperhive;
deployCfg = hyperhiveCfg.deploy;
queueClientId = hyperhiveCfg.swarm.controller.queueClientId;
in
{
config = lib.mkIf deployCfg.authelia.enable {
# One declaration, two readers: the id is the read-only option the
# controller authenticates under, so a mismatch cannot be introduced here.
services.hyperhive.swarm.authelia.oidc.clients = [
{
id = queueClientId;
description = "HyperHive swarm controller";
# `client_credentials`: a daemon authenticating as itself, with nobody
# to redirect. Declared rather than inferred from an empty redirect
# list, because authelia permits only the grants a client names and an
# omitted `grant_types` means authorization-code alone.
kind = "machine";
# Its own id as its own permitted audience. The controller mints a
# token for `SWARM_CONTROLLER_OTEL_AUDIENCE` (./glue-controller-env.nix),
# and ./swarm-otel.nix's `oidc/swarm` authenticator checks for this
# same id; either half without the other is a 401 several layers from
# this line.
audience = [ queueClientId ];
# `oidc/swarm` verifies the token offline against `/jwks.json`, which
# authelia's default opaque handle fails. The queue and the authelia
# bridge introspect, which reads a JWT just as well.
accessTokenSignedResponseAlg = "RS256";
}
];
};
}