nix: follow-ups from the service/deploy split
- swarm.victoriametrics.port: the description states why the listener is loopback-only instead of pointing "below" at text in another file. - authelia: the deploy half derives its unit and instance names from swarm.authelia.unit, so the instance is spelled once, in swarm-authelia-service.nix. - authelia: the tokenEndpointAuthMethod and bearerAuthz descriptions name the obligations the authelia host asserts instead of "below"; the swarm-authelia.nix header describes that file only. - module-eval-swarm-otel-core: swarm.otel.audience must contain both store push URLs the collector's exporters use and request tokens for. Refs #3742
This commit is contained in:
parent
960cf9ce30
commit
dc5c2d8d83
4 changed files with 50 additions and 28 deletions
|
|
@ -12,8 +12,8 @@ let
|
|||
swarmDomain = config.services.hyperhive.swarm.domain;
|
||||
|
||||
# The unit name upstream's `services.authelia.instances.<name>` derives,
|
||||
# which `unit` publishes. ./swarm-authelia.nix binds the same two names for
|
||||
# the instance it declares, and the two must agree.
|
||||
# which `unit` publishes. ./swarm-authelia.nix reads its instance name back
|
||||
# from `unit`, so this is the one place the instance is spelled.
|
||||
instance = "swarm";
|
||||
unitName = "authelia-${instance}";
|
||||
in
|
||||
|
|
@ -240,9 +240,10 @@ in
|
|||
method must be *stated*: omitting it is refused with
|
||||
`must be configured as 'client_secret_basic', … but it's
|
||||
configured as` an empty string. The sentence above is
|
||||
true of an ordinary client and false of that one, which
|
||||
is exactly how a reviewer reads this option and concludes
|
||||
the assertion below is wrong.
|
||||
true of an ordinary client and false of that one: the
|
||||
host that runs authelia asserts at evaluation that a
|
||||
`bearerAuthz` client states `client_secret_basic`,
|
||||
`client_secret_jwt` or `private_key_jwt`.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -290,12 +291,14 @@ in
|
|||
one value that is legal here and nothing else.
|
||||
|
||||
::: {.note}
|
||||
Setting this obliges two other options, and the assertions
|
||||
below enforce it. Authelia checks the same thing, but only
|
||||
Setting this obliges two other options: a non-empty
|
||||
`audience`, and a `tokenEndpointAuthMethod` of
|
||||
`client_secret_basic`, `client_secret_jwt` or
|
||||
`private_key_jwt`. Authelia checks the same thing, but only
|
||||
in its `preStart` validator — which means a violation
|
||||
builds and deploys cleanly and then fails to restart,
|
||||
taking swarm SSO down. The assertions move that to
|
||||
evaluation, where a wrong value costs nothing.
|
||||
taking swarm SSO down. The host that runs authelia asserts
|
||||
both at evaluation, where a wrong value costs nothing.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
# The swarm's SSO provider: one authelia for the whole swarm, in a
|
||||
# `swarm-authelia` nixos-container.
|
||||
#
|
||||
# Two halves, and only one of them is conditional:
|
||||
#
|
||||
# - the CLIENT pointer (`url`) exists on every hive, because a hive
|
||||
# that doesn't run authelia still has to know where to send people.
|
||||
# - the CONTAINER only exists where the swarm's shared services live.
|
||||
# `deploy.allSwarmServices` asserts this module's `enable`
|
||||
# (see ./swarm-required-services.nix); a hive is a client by default.
|
||||
# `swarm-authelia` nixos-container on the host with `deploy.authelia.enable`
|
||||
# (`deploy.allSwarmServices` defaults it on, see
|
||||
# ./swarm-required-services.nix). What every hive sees of it, `url` and the
|
||||
# OIDC client register included, is in ./swarm-authelia-service.nix.
|
||||
#
|
||||
# The file backend is the right shape, not a placeholder for LDAP: what
|
||||
# makes a directory necessary is the size of the subject set, and this
|
||||
|
|
@ -91,12 +86,10 @@ let
|
|||
|
||||
# Upstream's `services.authelia.instances.<name>` derives the unit,
|
||||
# user, group and StateDirectory from the instance name
|
||||
# (`authelia` + `-<name>`). Naming them here rather than repeating the
|
||||
# literal keeps the generator unit below and the module in step.
|
||||
# ./swarm-authelia-service.nix binds the same two names for `unit`;
|
||||
# the two must agree.
|
||||
instance = "swarm";
|
||||
unitName = "authelia-${instance}";
|
||||
# (`authelia` + `-<name>`). Both are read back from `swarm.authelia.unit`,
|
||||
# so the instance declared below is the one that option names.
|
||||
unitName = lib.removeSuffix ".service" cfg.unit;
|
||||
instance = lib.removePrefix "authelia-" unitName;
|
||||
stateDir = "/var/lib/${unitName}";
|
||||
|
||||
caTrust = import ./lib/hive-ca-trust.nix {
|
||||
|
|
@ -790,7 +783,7 @@ in
|
|||
../container-modules/swarm-container.nix
|
||||
(import ../container-modules/swarm-container-resolver.nix {
|
||||
inherit (networkCfg) bridgeIp;
|
||||
dnsConsumers = [ "authelia-${instance}.service" ];
|
||||
dnsConsumers = [ cfg.unit ];
|
||||
})
|
||||
caBundleModule
|
||||
];
|
||||
|
|
|
|||
|
|
@ -47,9 +47,11 @@ in
|
|||
type = lib.types.port;
|
||||
default = 8428;
|
||||
description = ''
|
||||
Port VictoriaMetrics listens on, bound to loopback only (see
|
||||
below). Upstream's own default, kept so an operator reading
|
||||
VictoriaMetrics documentation finds what they expect.
|
||||
Port VictoriaMetrics listens on, bound to loopback only on the
|
||||
host that runs it: its write endpoint is unauthenticated, so the
|
||||
gateway's vhost there is the only route to it. Upstream's own
|
||||
default, kept so an operator reading VictoriaMetrics
|
||||
documentation finds what they expect.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,30 @@ let
|
|||
&& lib.hasInfix "metrics.t.local" m
|
||||
&& lib.hasInfix "logs.t.local" l;
|
||||
}
|
||||
{
|
||||
# `swarm.otel.audience` is built in ../host-modules/swarm-otel-service.nix,
|
||||
# the push URLs the exporters use in ../host-modules/swarm-otel.nix. A URL
|
||||
# the registration lacks is refused at the token endpoint with
|
||||
# `invalid_target`, so every push fails while the collector reports
|
||||
# healthy.
|
||||
name = "the collector's registered audiences include both store push URLs it requests";
|
||||
ok =
|
||||
let
|
||||
s = otelSettings otelBaoWithAuthelia;
|
||||
registered = otelBaoWithAuthelia.services.hyperhive.swarm.otel.audience;
|
||||
withoutQuery = url: lib.head (lib.splitString "?" url);
|
||||
pushUrls = [
|
||||
s.exporters."otlphttp/victoriametrics".metrics_endpoint
|
||||
(withoutQuery s.exporters."otlphttp/victorialogs".logs_endpoint)
|
||||
];
|
||||
requested = map (n: s.extensions."oauth2client/${n}".endpoint_params.audience) [
|
||||
"victoriametrics"
|
||||
"victorialogs"
|
||||
];
|
||||
in
|
||||
lib.all (u: builtins.elem u registered) pushUrls
|
||||
&& lib.sort lib.lessThan requested == lib.sort lib.lessThan pushUrls;
|
||||
}
|
||||
{
|
||||
# `_HOSTNAME` cannot separate machines on its own: a hostname is a
|
||||
# config value two of them can share, and then every stream for a unit
|
||||
|
|
|
|||
Loading…
Reference in a new issue