diff options
-rw-r--r-- | nixos/modules/services/networking/mosquitto.nix | 10 | ||||
-rw-r--r-- | nixos/tests/mosquitto.nix | 28 |
2 files changed, 34 insertions, 4 deletions
diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix index b41a2fd27be2f..256d9457d3960 100644 --- a/nixos/modules/services/networking/mosquitto.nix +++ b/nixos/modules/services/networking/mosquitto.nix @@ -199,6 +199,7 @@ let allow_anonymous = 1; allow_zero_length_clientid = 1; auto_id_prefix = 1; + bind_interface = 1; cafile = 1; capath = 1; certfile = 1; @@ -295,7 +296,7 @@ let }; listenerAsserts = prefix: listener: - assertKeysValid prefix freeformListenerKeys listener.settings + assertKeysValid "${prefix}.settings" freeformListenerKeys listener.settings ++ userAsserts prefix listener.users ++ imap0 (i: v: authAsserts "${prefix}.authPlugins.${toString i}" v) @@ -397,7 +398,7 @@ let }; bridgeAsserts = prefix: bridge: - assertKeysValid prefix freeformBridgeKeys bridge.settings + assertKeysValid "${prefix}.settings" freeformBridgeKeys bridge.settings ++ [ { assertion = length bridge.addresses > 0; message = "Bridge ${prefix} needs remote broker addresses"; @@ -526,7 +527,7 @@ let globalAsserts = prefix: cfg: flatten [ - (assertKeysValid prefix freeformGlobalKeys cfg.settings) + (assertKeysValid "${prefix}.settings" freeformGlobalKeys cfg.settings) (imap0 (n: l: listenerAsserts "${prefix}.listener.${toString n}" l) cfg.listeners) (mapAttrsToList (n: b: bridgeAsserts "${prefix}.bridge.${n}" b) cfg.bridges) ]; @@ -629,9 +630,10 @@ in ])); RemoveIPC = true; RestrictAddressFamilies = [ - "AF_UNIX" # for sd_notify() call + "AF_UNIX" "AF_INET" "AF_INET6" + "AF_NETLINK" ]; RestrictNamespaces = true; RestrictRealtime = true; diff --git a/nixos/tests/mosquitto.nix b/nixos/tests/mosquitto.nix index 36cc8e3e3d9bd..d516d3373d9f6 100644 --- a/nixos/tests/mosquitto.nix +++ b/nixos/tests/mosquitto.nix @@ -4,6 +4,7 @@ let port = 1888; tlsPort = 1889; anonPort = 1890; + bindTestPort = 1891; password = "VERY_secret"; hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw=="; topic = "test/foo"; @@ -125,6 +126,10 @@ in { }; }; } + { + settings.bind_interface = "eth0"; + port = bindTestPort; + } ]; }; }; @@ -134,6 +139,8 @@ in { }; testScript = '' + import json + def mosquitto_cmd(binary, user, topic, port): return ( "mosquitto_{} " @@ -162,6 +169,27 @@ in { start_all() 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"): client1.succeed(publish("-m test", "password_store")) client1.succeed(publish("-m test", "password_file")) |