Merge pull request #172983 from pennae/mosquitto-bind-interface

nixos/mosquitto: add bind_interface listener option, fix assertion messages
main
pennae 2 years ago committed by GitHub
commit 023e25264c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      nixos/modules/services/networking/mosquitto.nix
  2. 28
      nixos/tests/mosquitto.nix

@ -199,6 +199,7 @@ let
allow_anonymous = 1; allow_anonymous = 1;
allow_zero_length_clientid = 1; allow_zero_length_clientid = 1;
auto_id_prefix = 1; auto_id_prefix = 1;
bind_interface = 1;
cafile = 1; cafile = 1;
capath = 1; capath = 1;
certfile = 1; certfile = 1;
@ -295,7 +296,7 @@ let
}; };
listenerAsserts = prefix: listener: listenerAsserts = prefix: listener:
assertKeysValid prefix freeformListenerKeys listener.settings assertKeysValid "${prefix}.settings" freeformListenerKeys listener.settings
++ userAsserts prefix listener.users ++ userAsserts prefix listener.users
++ imap0 ++ imap0
(i: v: authAsserts "${prefix}.authPlugins.${toString i}" v) (i: v: authAsserts "${prefix}.authPlugins.${toString i}" v)
@ -397,7 +398,7 @@ let
}; };
bridgeAsserts = prefix: bridge: bridgeAsserts = prefix: bridge:
assertKeysValid prefix freeformBridgeKeys bridge.settings assertKeysValid "${prefix}.settings" freeformBridgeKeys bridge.settings
++ [ { ++ [ {
assertion = length bridge.addresses > 0; assertion = length bridge.addresses > 0;
message = "Bridge ${prefix} needs remote broker addresses"; message = "Bridge ${prefix} needs remote broker addresses";
@ -526,7 +527,7 @@ let
globalAsserts = prefix: cfg: globalAsserts = prefix: cfg:
flatten [ flatten [
(assertKeysValid prefix freeformGlobalKeys cfg.settings) (assertKeysValid "${prefix}.settings" freeformGlobalKeys cfg.settings)
(imap0 (n: l: listenerAsserts "${prefix}.listener.${toString n}" l) cfg.listeners) (imap0 (n: l: listenerAsserts "${prefix}.listener.${toString n}" l) cfg.listeners)
(mapAttrsToList (n: b: bridgeAsserts "${prefix}.bridge.${n}" b) cfg.bridges) (mapAttrsToList (n: b: bridgeAsserts "${prefix}.bridge.${n}" b) cfg.bridges)
]; ];
@ -629,9 +630,10 @@ in
])); ]));
RemoveIPC = true; RemoveIPC = true;
RestrictAddressFamilies = [ RestrictAddressFamilies = [
"AF_UNIX" # for sd_notify() call "AF_UNIX"
"AF_INET" "AF_INET"
"AF_INET6" "AF_INET6"
"AF_NETLINK"
]; ];
RestrictNamespaces = true; RestrictNamespaces = true;
RestrictRealtime = true; RestrictRealtime = true;

@ -4,6 +4,7 @@ let
port = 1888; port = 1888;
tlsPort = 1889; tlsPort = 1889;
anonPort = 1890; anonPort = 1890;
bindTestPort = 1891;
password = "VERY_secret"; password = "VERY_secret";
hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw=="; hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw==";
topic = "test/foo"; topic = "test/foo";
@ -125,6 +126,10 @@ in {
}; };
}; };
} }
{
settings.bind_interface = "eth0";
port = bindTestPort;
}
]; ];
}; };
}; };
@ -134,6 +139,8 @@ in {
}; };
testScript = '' testScript = ''
import json
def mosquitto_cmd(binary, user, topic, port): def mosquitto_cmd(binary, user, topic, port):
return ( return (
"mosquitto_{} " "mosquitto_{} "
@ -162,6 +169,27 @@ in {
start_all() start_all()
server.wait_for_unit("mosquitto.service") server.wait_for_unit("mosquitto.service")
with subtest("bind_interface"):
addrs = dict()
for iface in json.loads(server.succeed("ip -json address show")):
for addr in iface['addr_info']:
# don't want to deal with multihoming here
assert addr['local'] not in addrs
addrs[addr['local']] = (iface['ifname'], addr['family'])
# mosquitto grabs *one* random address per type for bind_interface
(has4, has6) = (False, False)
for line in server.succeed("ss -HlptnO sport = ${toString bindTestPort}").splitlines():
items = line.split()
if "mosquitto" not in items[5]: continue
listener = items[3].rsplit(':', maxsplit=1)[0].strip('[]')
assert listener in addrs
assert addrs[listener][0] == "eth0"
has4 |= addrs[listener][1] == 'inet'
has6 |= addrs[listener][1] == 'inet6'
assert has4
assert has6
with subtest("check passwords"): with subtest("check passwords"):
client1.succeed(publish("-m test", "password_store")) client1.succeed(publish("-m test", "password_store"))
client1.succeed(publish("-m test", "password_file")) client1.succeed(publish("-m test", "password_file"))

Loading…
Cancel
Save