swarm-logs-auth: run as a static user so nginx reaches its socket
With DynamicUser=true and RuntimeDirectoryPreserve=yes, systemd creates the unit's runtime directory under /run/private/ (0700 root:root) and symlinks /run/swarm-logs-auth to it (systemd.exec(5), RuntimeDirectoryPreserve=). nginx runs as the unprivileged nginx user, so its connect() to /run/swarm-logs-auth/auth.sock failed with EACCES, the auth subrequest ended in a 502, and auth_request answered every agent bearer on /select/logsql/ with a 500. The unit now runs as a static swarm-logs-auth system user and group, the shape swarm-controller already uses for its 0751 + Preserve socket dir. RestrictSUIDSGID and RemoveIPC, which DynamicUser implied and the unit did not set itself, are set explicitly. module-eval-core-toggle gains a case that fails when any unit creating the runtime directory of a unix: upstream of nginx combines DynamicUser with RuntimeDirectoryPreserve. docs/process/gotchas.md records the trap. Fixes #5235
This commit is contained in:
parent
41404598f5
commit
b807189692
3 changed files with 66 additions and 1 deletions
|
|
@ -578,6 +578,47 @@ let
|
|||
&& lib.hasInfix "--socket /run/swarm-logs-auth/auth.sock" unit.serviceConfig.ExecStart
|
||||
&& l ? "= /__hive_authelia";
|
||||
}
|
||||
{
|
||||
# A `DynamicUser` unit's preserved runtime directory lives under
|
||||
# `/run/private/` (0700 root:root), which nginx cannot traverse, so a
|
||||
# socket there answers every proxied request with a 502. Each `unix:`
|
||||
# upstream under `/run/<dir>/` is matched to the units creating `<dir>`.
|
||||
# The first clause is the control: the match finds swarm-logs-auth's.
|
||||
name = "no unix socket nginx proxies to sits in a DynamicUser's preserved runtime directory";
|
||||
ok =
|
||||
let
|
||||
prefix = "http://unix:/run/";
|
||||
upstreamDirs = lib.unique (
|
||||
map (p: lib.head (lib.splitString "/" (lib.removePrefix prefix p))) (
|
||||
lib.filter (p: p != null && lib.hasPrefix prefix p) (
|
||||
lib.concatMap (vh: lib.mapAttrsToList (_: loc: loc.proxyPass) vh.locations) (
|
||||
lib.attrValues allLocal.services.nginx.virtualHosts
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
runtimeDirs =
|
||||
sc:
|
||||
let
|
||||
r = sc.RuntimeDirectory or [ ];
|
||||
in
|
||||
if lib.isList r then r else lib.splitString " " r;
|
||||
owners = lib.filterAttrs (
|
||||
_: u: lib.any (d: lib.elem d upstreamDirs) (runtimeDirs u.serviceConfig)
|
||||
) allLocal.systemd.services;
|
||||
hidden =
|
||||
sc:
|
||||
lib.elem (sc.DynamicUser or false) [
|
||||
true
|
||||
"yes"
|
||||
]
|
||||
&& !(lib.elem (sc.RuntimeDirectoryPreserve or "no") [
|
||||
false
|
||||
"no"
|
||||
]);
|
||||
in
|
||||
owners ? swarm-logs-auth && !(lib.any (u: hidden u.serviceConfig) (lib.attrValues owners));
|
||||
}
|
||||
{
|
||||
# Every agent bearer the responder has not recently granted costs a
|
||||
# store login and read, so its location carries the per-address limit.
|
||||
|
|
|
|||
Loading…
Reference in a new issue