summary refs log tree commit diff
diff options
context:
space:
mode:
authorpennae <82953136+pennae@users.noreply.github.com>2022-05-23 10:53:08 +0000
committerGitHub <noreply@github.com>2022-05-23 10:53:08 +0000
commit023e25264cb8022f93ecdff5f28c4a8762cb34ec (patch)
tree76d5ee4b005686f5e7bbae5f4e97167800ea25bf
parente9bdd5fa74bcbae7d0b587bc4c12d2353fd92611 (diff)
parentc1115d37ffd4f947dd110c1bfc8f1593eaa07928 (diff)
Merge pull request #172983 from pennae/mosquitto-bind-interface
nixos/mosquitto: add bind_interface listener option, fix assertion messages
-rw-r--r--nixos/modules/services/networking/mosquitto.nix10
-rw-r--r--nixos/tests/mosquitto.nix28
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"))