about summary refs log tree commit diff
path: root/nixos/tests
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/tests')
-rw-r--r--nixos/tests/unbound.nix50
1 files changed, 35 insertions, 15 deletions
diff --git a/nixos/tests/unbound.nix b/nixos/tests/unbound.nix
index 9a7a652b4052f..dc8e5a9d3ed8c 100644
--- a/nixos/tests/unbound.nix
+++ b/nixos/tests/unbound.nix
@@ -8,8 +8,13 @@
    * running a recursive DNS resolver on a machine in the network awaiting input from clients over TCP/53 & UDP/53
    * running a recursive DNS resolver on a machine in the network awaiting input from clients over TCP/853 (DoT)
 
-  In the below test setup we are trying to implement all of those use cases
-  without creating a bazillion machines.
+ In the below test setup we are trying to implement all of those use cases.
+
+ Another aspect that we cover is access to the local control UNIX socket. It
+ can optionally be enabled and users can optionally be in a group to gain
+ access. Users that are not in the group (except for root) should not have
+ access to that socket. Also, when there is no socket configured, users
+ shouldn't be able to access the control socket at all. Not even root.
 */
 import ./make-test-python.nix ({ pkgs, lib, ... }:
   let
@@ -96,7 +101,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
       };
 
       # machine that runs a local unbound that will be reconfigured during test execution
-      local_resolver = { lib, nodes, ... }: {
+      local_resolver = { lib, nodes, config, ... }: {
         imports = [ common ];
         networking.interfaces.eth1.ipv4.addresses = lib.mkForce [
           { address = "192.168.0.3"; prefixLength = 24; }
@@ -113,11 +118,22 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
           enable = true;
           allowedAccess = [ "::1" "127.0.0.0/8" ];
           interfaces = [ "::1" "127.0.0.1" ];
+          localControlSocketPath = "/run/unbound/unbound.ctl";
           extraConfig = ''
             include: "/etc/unbound/extra*.conf"
           '';
         };
 
+        users.users = {
+          # user that is permitted to access the unix socket
+          someuser.extraGroups = [
+            config.users.users.unbound.group
+          ];
+
+          # user that is not permitted to access the unix socket
+          unauthorizeduser = {};
+        };
+
         environment.etc = {
           "unbound-extra1.conf".text = ''
             forward-zone:
@@ -132,12 +148,6 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
                 something.local. IN A 3.4.5.6
               ''}
           '';
-          "unbound-extra3.conf".text = ''
-            remote-control:
-              control-enable: yes
-              control-interface: /run/unbound/unbound.ctl
-          '';
-
         };
       };
 
@@ -218,6 +228,10 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
 
       resolver.wait_for_unit("unbound.service")
 
+      with subtest("root is unable to use unbounc-control when the socket is not configured"):
+          resolver.succeed("which unbound-control")  # the binary must exist
+          resolver.fail("unbound-control list_forwards")  # the invocation must fail
+
       # verify that the resolver is able to resolve on all the local protocols
       with subtest("test that the resolver resolves on all protocols and transports"):
           test(resolver, ["::1", "127.0.0.1"], doh=True)
@@ -241,18 +255,24 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
           print(local_resolver.succeed("journalctl -u unbound -n 1000"))
           test(local_resolver, ["::1", "127.0.0.1"], args=["+timeout=60"])
 
+      with subtest("test that we can use the unbound control socket"):
+          out = local_resolver.succeed(
+              "sudo -u someuser -- unbound-control list_forwards"
+          ).strip()
+
+          # Thank you black! Can't really break this line into a readable version.
+          expected = "example.local. IN forward ${(lib.head nodes.resolver.config.networking.interfaces.eth1.ipv6.addresses).address} ${(lib.head nodes.resolver.config.networking.interfaces.eth1.ipv4.addresses).address}"
+          assert out == expected, f"Expected `{expected}` but got `{out}` instead."
+          local_resolver.fail("sudo -u unauthorizeduser -- unbound-control list_forwards")
+
+
       # link a new config file to /etc/unbound/extra.conf
       local_resolver.succeed("ln -sf /etc/unbound-extra2.conf /etc/unbound/extra2.conf")
 
       # reload the server & ensure the new local zone works
       with subtest("test that we can query the new local zone"):
-          local_resolver.succeed("systemctl reload unbound")
+          local_resolver.succeed("unbound-control reload")
           r = [("A", "3.4.5.6")]
           test(local_resolver, ["::1", "127.0.0.1"], zone="something.local.", records=r)
-
-      with subtest("test that we can enable unbound control sockets on the fly"):
-          local_resolver.succeed("ln -sf /etc/unbound-extra3.conf /etc/unbound/extra3.conf")
-          local_resolver.succeed("systemctl reload unbound")
-          local_resolver.succeed("unbound-control list_forwards")
     '';
   })