The mint creates each client's secret in the swarm secret store and writes only the digest to disk. It mints only when the store answers and holds none. A new unit moves the plaintext files an earlier release left into the store and removes each once the store holds the same value. The bridge reads its secret from the store into /run before each start. The secret publisher unit and its path unit are gone.
52 lines
2.3 KiB
Nix
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 authelia's mint 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";
|
|
}
|
|
];
|
|
};
|
|
}
|