Watch
0
0
Fork
You've already forked hyperhive
0

squid blocks a runtime deny list from the controller in every egress mode, ahead of the allow list

This commit is contained in:
atlas 2026-11-04 22:00:42 +01:00 • committed by mara
commit dd5fde848f

View file

@ -636,6 +636,58 @@ let
&& builtins.elem ''acl unrestricted proxy_auth "${list}"'' lines
&& list == "/var/lib/hive-squid/unrestricted";
}
{
# The swarm's deny list is an include that precedes every allow and the
# credential check, so a denied name is refused in every mode and for a
# client that sent no credential. Control: the include and the allows are
# found, so a position compared below is not a lookup of nothing.
name = "squid includes the swarm's deny list after the destination denies and before the credential check and every allow";
ok =
let
sq = hiveOtel.services.hyperhive.deploy.hive-controller.squid;
lines = lib.splitString "\n" hiveOtel.services.squid.configText;
at = l: lib.lists.findFirstIndex (x: x == l) null lines;
deny = at "include ${sq.denyFile}";
allows = map at [
"http_access allow base_dst"
"include ${sq.agentAllowFile}"
"http_access allow unrestricted"
"http_access allow allowed_dst"
];
in
deny != null
&& sq.denyFile == "/var/lib/hive-squid/deny.conf"
&& !(lib.elem null allows)
&& lib.all (a: deny < a) allows
&& at "http_access deny to_private" < deny
&& at "http_access deny ip_v4_host" < deny
&& deny < at "http_access deny !authed"
# Two includes: this one and the per-agent allow rules.
&& lib.length (lib.filter (l: lib.hasPrefix "include " l) lines) == 2;
}
{
# What the deny list adds to the configuration is the include and the
# lines that log a hit; with the file empty, which tmpfiles creates, squid
# has no rule it did not have. Control: the lines are found, so the
# equality below is not against an empty filter.
name = "squid's deny list adds one include and the log lines, and its file exists empty before squid starts";
ok =
let
sq = hiveOtel.services.hyperhive.deploy.hive-controller.squid;
conf = hiveOtel.services.squid.configText;
mentions = lib.filter (
l: !(lib.hasPrefix "#" l) && (lib.hasInfix "egress_den" l || lib.hasInfix sq.denyFile l)
) (lib.splitString "\n" conf);
in
mentions == [
"logformat egress_denied egress_denied user=%[un method=%rm host=%>rd port=%>rP result=%Ss/%03>Hs"
"acl egress_denied_hit note egress_deny 1"
"access_log syslog:daemon.info logformat=egress_denied egress_denied_hit"
"include ${sq.denyFile}"
]
&& builtins.elem "f ${sq.denyFile} 0640 hive-core squid - -" hiveOtel.systemd.tmpfiles.rules
&& hiveOtelAllLocal.systemd.services.hive-c0re.environment.HIVE_SQUID_DENY_FILE == sq.denyFile;
}
{
# The list is read when squid parses its configuration, so a change to
# the file reloads squid. Control: the watched path is the list's own.
@ -651,6 +703,7 @@ let
list
hiveOtel.services.hyperhive.deploy.hive-controller.squid.allowedFile
hiveOtel.services.hyperhive.deploy.hive-controller.squid.agentAllowFile
hiveOtel.services.hyperhive.deploy.hive-controller.squid.denyFile
]
&& hiveOtel.systemd.services.squid-unrestricted-reload.startLimitIntervalSec == 0
&& builtins.elem "paths.target" path.wantedBy