send agent traffic through squid once its hive announces it
This commit is contained in:
parent
86e9f49fe6
commit
b551eb02ff
1 changed files with 885 additions and 27 deletions
|
|
@ -1,5 +1,7 @@
|
|||
# `checks.vm-hive-squid`: runs ../host-modules/hive-squid.nix in a VM, which
|
||||
# the module-eval suite can only read. Three nodes on two networks:
|
||||
# the module-eval suite can only read, and checks that an agent with the proxy
|
||||
# variables of nix/agent-modules/egress-proxy.nix reaches squid and skips it
|
||||
# where it should. Three nodes on two networks:
|
||||
#
|
||||
# agent (vlan 1) --> proxy (vlan 1 = the stand-in bridge, vlan 2 = uplink) --> web (vlan 2)
|
||||
#
|
||||
|
|
@ -170,6 +172,8 @@ pkgs.testers.runNixOSTest {
|
|||
value = [ p.name ];
|
||||
}) privateNets
|
||||
);
|
||||
# The gateway: nginx answers on the bridge, which agents reach directly.
|
||||
networking.firewall.interfaces.eth1.allowedTCPPorts = [ 443 ];
|
||||
# Renders the users file the way hive-c0re does.
|
||||
environment.systemPackages = [ pkgs.mkpasswd ];
|
||||
services.hyperhive.squid.selfcheck.unrestrictedCanary = "other.t.local";
|
||||
|
|
@ -211,6 +215,8 @@ pkgs.testers.runNixOSTest {
|
|||
{ lib, ... }:
|
||||
{
|
||||
virtualisation.vlans = [ 1 ];
|
||||
# The bridge listener, by the name the proxy resolves to the same address.
|
||||
networking.hosts.${bridgeIp} = [ "bridge.t.local" ];
|
||||
networking.interfaces.eth1.ipv4.addresses = lib.mkForce [
|
||||
{
|
||||
address = "192.168.1.3";
|
||||
|
|
@ -357,6 +363,45 @@ pkgs.testers.runNixOSTest {
|
|||
"http://${bridgeIp}:3128/squid-internal-mgr/counters) = 403"
|
||||
)
|
||||
|
||||
# The variables an agent's `proxy.env` carries (nix/agent-modules/egress-proxy.nix),
|
||||
# as a curl on the agent reads them.
|
||||
def agent_env(cred, no_proxy):
|
||||
url = f"http://{cred}@${bridgeIp}:3128"
|
||||
pairs = {
|
||||
"HTTPS_PROXY": url, "HTTP_PROXY": url, "https_proxy": url, "http_proxy": url,
|
||||
"NO_PROXY": no_proxy, "no_proxy": no_proxy,
|
||||
}
|
||||
return " ".join(f"{k}='{v}'" for k, v in pairs.items())
|
||||
|
||||
def agent_get(cred, no_proxy, url):
|
||||
# The status of the answer, whoever gave it; 000 when none came.
|
||||
return agent.succeed(
|
||||
f"env {agent_env(cred, no_proxy)} curl -sS -m 15 -o /dev/null -w '%{{http_code}}' {url} 2>/dev/null || true"
|
||||
).strip()
|
||||
|
||||
def squid_saw(pattern):
|
||||
return re.search(pattern, proxy.succeed("journalctl -u squid.service -o cat"))
|
||||
|
||||
with subtest("an agent with the proxy variables reaches an allowed name through squid and a swarm-internal name directly"):
|
||||
NO_PROXY = "localhost,127.0.0.1,::1,bridge.t.local,${bridgeIp}"
|
||||
# Plain HTTP to the listeners' port 443, so the answer carries a status.
|
||||
assert agent_get(ATLAS, NO_PROXY, "http://forge.t.local:443/") not in ("000", "403", "407")
|
||||
assert squid_saw(r"192\.168\.1\.3 TCP_\w+/\d+ .* GET http://forge\.t\.local:443/ atlas "), "through squid, as atlas"
|
||||
assert agent_get(ATLAS, NO_PROXY, "http://bridge.t.local:443/") not in ("000", "403", "407")
|
||||
assert not squid_saw(r"GET http://bridge\.t\.local:443/ "), "a swarm-internal name never reached squid"
|
||||
# Control: without the exemption the same request goes to squid, which refuses the bridge.
|
||||
assert agent_get(ATLAS, "localhost", "http://bridge.t.local:443/") == "403"
|
||||
assert squid_saw(r"192\.168\.1\.3 TCP_DENIED/403 .* GET http://bridge\.t\.local:443/ "), "control: squid refuses it"
|
||||
# CONNECT takes the same path: HTTPS_PROXY names the proxy for https URLs.
|
||||
assert agent.succeed(
|
||||
f"env {agent_env(ATLAS, NO_PROXY)} curl -sS -m 15 -o /dev/null -w '%{{http_connect}}' https://forge.t.local/ 2>/dev/null || true"
|
||||
).strip() == "200"
|
||||
|
||||
with subtest("an agent without the proxy variables goes direct"):
|
||||
assert agent.succeed(
|
||||
"curl -sS -m 15 -o /dev/null -w '%{http_code}' http://bridge.t.local:443/ 2>/dev/null || true"
|
||||
).strip() not in ("000", "403", "407")
|
||||
|
||||
with subtest("the self-check passes with its credential"):
|
||||
proxy.succeed("install -d -m 0700 /run/credstore")
|
||||
proxy.succeed(f"printf '%s\\n' {PW['selfcheck.squid']} > /run/credstore/hive-squid.selfcheck")
|
||||
|
|
|
|||
Loading…
Reference in a new issue