swarm-otel: let the collector write its socket dir, and probe every route through nginx
This commit is contained in:
parent
1325f44707
commit
41bea3c6d9
3 changed files with 104 additions and 6 deletions
|
|
@ -920,6 +920,77 @@ let
|
|||
&& lib.elem "container@swarm-otel.service" u.partOf
|
||||
&& lib.elem "multi-user.target" u.wantedBy;
|
||||
}
|
||||
{
|
||||
# `DynamicUser` forces `ProtectSystem=strict`, which leaves `/run`
|
||||
# read-only unless the path is in `ReadWritePaths`. The controls: the
|
||||
# unit really is DynamicUser, and a copy without the path, or with some
|
||||
# other path, is read-only.
|
||||
name = "the collector unit can write the directory its receiver sockets are created in";
|
||||
ok =
|
||||
let
|
||||
host = serviceContainersWithCi;
|
||||
sc = host.containers.swarm-otel.config.systemd.services.opentelemetry-collector.serviceConfig;
|
||||
s = host.containers.swarm-otel.config.services.opentelemetry-collector.settings;
|
||||
socks = map (r: r.protocols.http.endpoint) (
|
||||
lib.filter (r: (r.protocols.http.transport or null) == "unix") (lib.attrValues s.receivers)
|
||||
);
|
||||
writes =
|
||||
c: sock:
|
||||
let
|
||||
strict = (c.DynamicUser or false) || (c.ProtectSystem or "no") == "strict";
|
||||
dir = dirOf sock;
|
||||
under = p: p == dir || lib.hasPrefix "${p}/" dir;
|
||||
in
|
||||
!strict || lib.any under (c.ReadWritePaths or [ ]);
|
||||
in
|
||||
socks != [ ]
|
||||
&& sc.DynamicUser
|
||||
&& lib.all (writes sc) socks
|
||||
&& !(lib.any (writes (sc // { ReadWritePaths = [ ]; })) socks)
|
||||
&& !(lib.any (writes (sc // { ReadWritePaths = [ "/var/lib/opentelemetry-collector" ]; })) socks);
|
||||
}
|
||||
{
|
||||
# The probe loop names each gateway route, and the routes are read from
|
||||
# the vhost, not from the receivers the probe is built from. A script
|
||||
# missing one route, or treating 502 as a pass, is rejected.
|
||||
name = "the readiness unit probes every collector route through the gateway";
|
||||
ok =
|
||||
let
|
||||
host = serviceContainersWithCi;
|
||||
otel = host.services.hyperhive.swarm.otel;
|
||||
locs = host.services.nginx.virtualHosts.${otel.domain}.locations;
|
||||
routes = lib.sort lib.lessThan (
|
||||
map (l: lib.removeSuffix "/" (lib.removePrefix "/" l)) (
|
||||
lib.filter (l: (locs.${l}.proxyPass or null) != null) (lib.attrNames locs)
|
||||
)
|
||||
);
|
||||
lines = script: map (lib.removePrefix " ") (lib.splitString "\n" script);
|
||||
probed =
|
||||
script:
|
||||
let
|
||||
loop = lib.findFirst (l: lib.hasPrefix "for route in " l) "" (lines script);
|
||||
in
|
||||
lib.sort lib.lessThan (
|
||||
lib.filter (w: w != "") (
|
||||
lib.splitString " " (lib.removeSuffix "; do" (lib.removePrefix "for route in " loop))
|
||||
)
|
||||
);
|
||||
verdict =
|
||||
script:
|
||||
probed script == routes
|
||||
&& lib.hasInfix "--resolve ${otel.domain}:443:127.0.0.1" script
|
||||
&& lib.hasInfix "https://${otel.domain}/$route/" script
|
||||
&& lib.hasInfix "case $code in 000 | 502 | 504) ;;" script;
|
||||
script = host.systemd.services.swarm-otel-sockets.script;
|
||||
in
|
||||
lib.length routes > 2
|
||||
&& lib.elem "h1" routes
|
||||
&& lib.elem "swarm-grafana" routes
|
||||
&& verdict script
|
||||
&& !verdict (lib.replaceStrings [ " swarm-grafana" ] [ "" ] script)
|
||||
&& !verdict (lib.replaceStrings [ "000 | 502 | 504" ] [ "000 | 504" ] script)
|
||||
&& !verdict (lib.replaceStrings [ "--resolve" ] [ "--noresolve" ] script);
|
||||
}
|
||||
{
|
||||
# The DynamicUser layout keeps the history under /var/lib/private; the
|
||||
# static user's StateDirectory is the plain path. The move runs as its
|
||||
|
|
|
|||
Loading…
Reference in a new issue