swarm-otel/swarm-controller: authenticate + route the swarm-tier OTLP producer through the gateway
This commit is contained in:
parent
f3be08f6b6
commit
350b4e9fb7
3 changed files with 170 additions and 81 deletions
|
|
@ -155,27 +155,39 @@ let
|
|||
# above, genuinely optional and gated on the option resolving rather
|
||||
# than assumed.
|
||||
#
|
||||
# Gated on THIS HOST running `swarm-otel`, not merely on it existing
|
||||
# somewhere in the swarm: its receiver for a swarm-tier producer binds
|
||||
# `127.0.0.1` only (see `swarm-otel.nix::producerPort`), so reaching it
|
||||
# needs co-location, and this checks that directly rather than assuming
|
||||
# it — the unasserted-co-location gap flagged elsewhere in this codebase
|
||||
# doesn't apply here because there is nothing to assert: a controller on
|
||||
# a host that doesn't run the collector simply exports nothing, the same
|
||||
# graceful absence `forgeEnv` already models.
|
||||
# By NAME through the gateway, never a loopback literal or a bare
|
||||
# `producerPort` — mara's ruling on this exact module: "the swarm
|
||||
# services dont have to run on the same host as the swarm controller."
|
||||
# A controller and the swarm's collector are two independently-placed
|
||||
# swarm services, exactly like a hive and the collector already are
|
||||
# (`otel.nix`'s own `endpoint`), so this reaches it the same way: by
|
||||
# its swarm-service name, resolved locally by dnsmasq on a co-located
|
||||
# host and over the real network otherwise — no loopback-vs-remote
|
||||
# knob to get wrong, and nothing here to gate on co-location because
|
||||
# there is no co-location requirement left to check.
|
||||
#
|
||||
# No trailing slash: `opentelemetry_otlp`'s http/json exporter appends
|
||||
# `/v1/metrics` to this base itself, and the swarm-otel gateway route
|
||||
# (`swarm-otel.nix`'s nginx `locations."/${producerName}/"`) strips the
|
||||
# `/${producerName}` prefix before the request reaches the receiver —
|
||||
# so the two ends agree on exactly one path, `/v1/metrics`, arrived at
|
||||
# from opposite directions.
|
||||
#
|
||||
# Gated on `otelSwarmCfg.enable` alone (a swarm-wide fact, not "enabled
|
||||
# HERE"): the collector is reachable by name wherever it runs, so a
|
||||
# controller not co-located with it now exports over https instead of
|
||||
# exporting nothing — the graceful-absence case left is "no swarm-otel
|
||||
# anywhere in this swarm at all," which `forgeEnv` already models the
|
||||
# same way.
|
||||
otelSwarmCfg = config.services.hyperhive.swarm.otel;
|
||||
otelEnv = lib.optionalAttrs otelSwarmCfg.enable {
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT = "http://${otelSwarmCfg.domain}:${toString otelSwarmCfg.producerPort}";
|
||||
};
|
||||
|
||||
# Only when THIS host also runs `swarm-otel` — same reasoning and same
|
||||
# shape as `hive-forge/default.nix`'s `ssoLocal`-gated entry: a raw host
|
||||
# systemd unit does not get the bridge's dnsmasq resolution containers
|
||||
# get, so the name that reaches a co-located collector over `otelEnv`
|
||||
# above needs an explicit loopback alias here, or it resolves however
|
||||
# (or however it fails to) off-host DNS says on this host.
|
||||
otelHostsEntry = lib.optionalAttrs otelSwarmCfg.enable {
|
||||
"127.0.0.1" = [ otelSwarmCfg.domain ];
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT = "https://${otelSwarmCfg.domain}/${otelSwarmCfg.producerName}";
|
||||
# Checked by `swarm-otel.nix`'s `oidc/${producerName}` authenticator
|
||||
# against exactly this controller's own registered audience (see the
|
||||
# `audience = [ queueClientId ]` client entry below) — the two have
|
||||
# to name the same value or the exporter mints a token the receiver
|
||||
# was never told to accept.
|
||||
SWARM_CONTROLLER_OTEL_AUDIENCE = queueClientId;
|
||||
};
|
||||
|
||||
# Wrapped rather than documented: every one of these values is derived
|
||||
|
|
@ -479,10 +491,6 @@ in
|
|||
"swarm-controller-credential"
|
||||
];
|
||||
|
||||
# See `otelHostsEntry`'s own comment: only present, and only ever
|
||||
# `{ "127.0.0.1" = [ ... ]; }`, when this host also runs `swarm-otel`.
|
||||
networking.hosts = otelHostsEntry;
|
||||
|
||||
users.users.swarm-controller = {
|
||||
isSystemUser = true;
|
||||
group = "swarm-controller";
|
||||
|
|
@ -509,6 +517,17 @@ in
|
|||
# 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 — same "client's own id
|
||||
# is the value it may ask for" shape `swarm-authelia.nix`'s
|
||||
# `hiveClients` uses, just self-referential instead of prefixed:
|
||||
# this controller is not a hive (see `queueClientId`'s own doc
|
||||
# comment), so it has no `hiveClientPrefix` name to reuse. This is
|
||||
# what lets `vcs_metrics::authenticated_http_client()` mint a token
|
||||
# for `SWARM_CONTROLLER_OTEL_AUDIENCE` and have `swarm-otel.nix`'s
|
||||
# `oidc/swarm` authenticator (which checks for this same id) accept
|
||||
# it — registering here without requesting there, or the reverse,
|
||||
# both fail as a healthy-looking 401 several layers from this line.
|
||||
audience = [ queueClientId ];
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue