otel: a hive always authenticates — drop the unauthenticated mode
mara, reviewing this PR: "hives always require an identity, swarm controller
and auth is not optional."
So `requireHiveIdentity` is gone rather than defaulted, and with it every
branch that had to describe an unauthenticated collector. The swarm tier now
serves per-hive receivers only, and `/` answers 404 because there is no
swarm-wide inbox to route to. A hive with no credential is a build error, not
a quieter mode.
`hivePortBase` goes too: with per-hive receivers unconditional, `port` IS the
base of the range. That keeps one documented knob instead of adding a second,
and its advice ("move it if something else claims that range") still holds.
Two assertions replace the toggle — an empty hive roster, and a null
`authelia.url`. The second matters because a guessed issuer URL evaluates
cleanly, deploys cleanly, and then refuses every hive at runtime.
⚠️ `cfg.port` is deliberately no longer compared against the derived range in
the collision assertion: it is now the range's first element, so listing it
would make that assertion fire on every config.
This also retires the asymmetry guard added earlier in review — the state it
protected against (auth off on one side, credential still set on the other)
is no longer representable.
This commit is contained in:
parent
7da7915150
commit
9bd2b9e9e6
3 changed files with 107 additions and 192 deletions
|
|
@ -255,7 +255,11 @@ in
|
|||
swarmName = "otlphttp/swarm";
|
||||
authName = "oauth2client/swarm";
|
||||
|
||||
# Holding a credential IS the condition — see `clientSecretFile`.
|
||||
# A hive always authenticates to the swarm's collector as itself, so
|
||||
# this is not a mode — it is a precondition, and the assertion below
|
||||
# is what enforces it. Kept as a name because several places have to
|
||||
# read "do we have what it takes", and an eval error from a null path
|
||||
# names this file rather than the option an operator has to set.
|
||||
senderAuth = otel.clientSecretFile != null && hiveName != null;
|
||||
|
||||
# This hive's client id, and also the audience it must ASK for. Both
|
||||
|
|
@ -382,60 +386,28 @@ in
|
|||
|
||||
assertions = [
|
||||
{
|
||||
# Only checkable on a host that runs BOTH tiers — which is the
|
||||
# deployment where it can actually go wrong silently. A remote
|
||||
# hive cannot see the swarm tier's config at all, so its operator
|
||||
# sets the path explicitly and this says nothing.
|
||||
assertion = !(swarmOtelCfg.enable && swarmOtelCfg.requireHiveIdentity) || senderAuth;
|
||||
# A hive authenticates to the swarm's collector as itself — there
|
||||
# is no unauthenticated path to fall back to, so a missing
|
||||
# credential is a broken deployment rather than a quieter mode.
|
||||
# Caught here because the alternative is a collector that starts
|
||||
# cleanly, retries forever, and reports nothing to anyone.
|
||||
assertion = senderAuth;
|
||||
message = ''
|
||||
This host runs the swarm's telemetry collector with
|
||||
services.hyperhive.swarm.otel.requireHiveIdentity = true, so
|
||||
ingest is authenticated per hive — but this hive's own
|
||||
collector has no credential to present:
|
||||
services.hyperhive.otel.enable is true but this hive has no
|
||||
identity to present to the swarm's collector:
|
||||
|
||||
services.hyperhive.otel.clientSecretFile = ${
|
||||
if otel.clientSecretFile == null then "null" else otel.clientSecretFile
|
||||
}
|
||||
services.hyperhive.hiveName = ${if hiveName == null then "null" else hiveName}
|
||||
|
||||
Its samples would be refused with a 401 by the collector
|
||||
running beside it. Set both, or set requireHiveIdentity =
|
||||
false to accept unauthenticated ingest.
|
||||
'';
|
||||
}
|
||||
{
|
||||
# The mirror of the assertion above, and the reason it exists is
|
||||
# that the failure is SILENT rather than loud. With ingest
|
||||
# unauthenticated the swarm tier serves one catch-all location
|
||||
# and passes the URI through unchanged — but this tier still
|
||||
# appends `/<hive>` whenever it holds a credential, so the
|
||||
# receiver is asked for `/<hive>/v1/metrics`, a path it does not
|
||||
# serve. The result is 404s and retries: no 401, no assertion, no
|
||||
# log anywhere saying telemetry stopped.
|
||||
#
|
||||
# Only reachable by overriding one side without the other, since
|
||||
# both defaults derive from `swarm.authelia.enable` and move
|
||||
# together. That is exactly why it is worth a build error — an
|
||||
# operator who flips the escape hatch has no reason to suspect
|
||||
# the sending half.
|
||||
assertion = !(swarmOtelCfg.enable && !swarmOtelCfg.requireHiveIdentity && senderAuth);
|
||||
message = ''
|
||||
This host accepts unauthenticated telemetry ingest
|
||||
(services.hyperhive.swarm.otel.requireHiveIdentity = false),
|
||||
but its own collector still holds a credential:
|
||||
Every hive authenticates as itself — that is what makes the
|
||||
`hive` label on its metrics mean anything — so both are
|
||||
required.
|
||||
|
||||
services.hyperhive.otel.clientSecretFile = ${
|
||||
if otel.clientSecretFile == null then "null" else otel.clientSecretFile
|
||||
}
|
||||
|
||||
A collector that authenticates also addresses its hive's own
|
||||
path, and an unauthenticated swarm tier serves no per-hive
|
||||
paths — so this hive's samples would 404 rather than be
|
||||
refused, which no log names as an auth problem.
|
||||
|
||||
Set services.hyperhive.otel.clientSecretFile = null to send
|
||||
unauthenticated too, or drop the requireHiveIdentity
|
||||
override.
|
||||
On a host that runs the swarm's identity provider, the default
|
||||
already points at the secret authelia minted. On a hive that
|
||||
does not, copy that hive's secret across and name it here.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in a new issue