diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 7a7b01238b6e..18599437c825 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -589,7 +589,7 @@ in { keymap = handleTest ./keymap.nix {}; kimai = handleTest ./kimai.nix {}; kmonad = runTest ./kmonad.nix; - knot = handleTest ./knot.nix {}; + knot = runTest ./knot.nix; komga = handleTest ./komga.nix {}; krb5 = discoverTests (import ./krb5); ksm = handleTest ./ksm.nix {}; diff --git a/nixos/tests/knot.nix b/nixos/tests/knot.nix index 10ab1390696f..651fccc21949 100644 --- a/nixos/tests/knot.nix +++ b/nixos/tests/knot.nix @@ -1,254 +1,256 @@ -import ./make-test-python.nix ( - { pkgs, lib, ... }: - let - common = { - networking.firewall.enable = false; - networking.useDHCP = false; - }; - exampleZone = pkgs.writeTextDir "example.com.zone" '' - @ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800 - @ NS ns1 - @ NS ns2 - ns1 A 192.168.0.1 - ns1 AAAA fd00::1 - ns2 A 192.168.0.2 - ns2 AAAA fd00::2 - www A 192.0.2.1 - www AAAA 2001:DB8::1 - sub NS ns.example.com. - ''; - delegatedZone = pkgs.writeTextDir "sub.example.com.zone" '' - @ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800 - @ NS ns1.example.com. - @ NS ns2.example.com. - @ A 192.0.2.2 - @ AAAA 2001:DB8::2 - ''; +{ + pkgs, + lib, + ... +}: +let + common = { + networking.firewall.enable = false; + networking.useDHCP = false; + }; + exampleZone = pkgs.writeTextDir "example.com.zone" '' + @ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800 + @ NS ns1 + @ NS ns2 + ns1 A 192.168.0.1 + ns1 AAAA fd00::1 + ns2 A 192.168.0.2 + ns2 AAAA fd00::2 + www A 192.0.2.1 + www AAAA 2001:DB8::1 + sub NS ns.example.com. + ''; + delegatedZone = pkgs.writeTextDir "sub.example.com.zone" '' + @ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800 + @ NS ns1.example.com. + @ NS ns2.example.com. + @ A 192.0.2.2 + @ AAAA 2001:DB8::2 + ''; - knotZonesEnv = pkgs.buildEnv { - name = "knot-zones"; - paths = [ - exampleZone - delegatedZone - ]; - }; - # DO NOT USE pkgs.writeText IN PRODUCTION. This put secrets in the nix store! - tsigFile = pkgs.writeText "tsig.conf" '' - key: - - id: xfr_key - algorithm: hmac-sha256 - secret: zOYgOgnzx3TGe5J5I/0kxd7gTcxXhLYMEq3Ek3fY37s= - ''; - in - { - name = "knot"; - meta = with pkgs.lib.maintainers; { - maintainers = [ hexa ]; - }; + knotZonesEnv = pkgs.buildEnv { + name = "knot-zones"; + paths = [ + exampleZone + delegatedZone + ]; + }; + # DO NOT USE pkgs.writeText IN PRODUCTION. This put secrets in the nix store! + tsigFile = pkgs.writeText "tsig.conf" '' + key: + - id: xfr_key + algorithm: hmac-sha256 + secret: zOYgOgnzx3TGe5J5I/0kxd7gTcxXhLYMEq3Ek3fY37s= + ''; +in +{ + name = "knot"; + meta = with pkgs.lib.maintainers; { + maintainers = [ hexa ]; + }; - nodes = { - primary = - { lib, ... }: - { - imports = [ common ]; + nodes = { + primary = + { lib, ... }: + { + imports = [ common ]; - # trigger sched_setaffinity syscall - virtualisation.cores = 2; + # trigger sched_setaffinity syscall + virtualisation.cores = 2; - networking.interfaces.eth1 = { - ipv4.addresses = lib.mkForce [ - { - address = "192.168.0.1"; - prefixLength = 24; - } + networking.interfaces.eth1 = { + ipv4.addresses = lib.mkForce [ + { + address = "192.168.0.1"; + prefixLength = 24; + } + ]; + ipv6.addresses = lib.mkForce [ + { + address = "fd00::1"; + prefixLength = 64; + } + ]; + }; + services.knot.enable = true; + services.knot.extraArgs = [ "-v" ]; + services.knot.keyFiles = [ tsigFile ]; + services.knot.settings = { + server = { + listen = [ + "0.0.0.0@53" + "::@53" ]; - ipv6.addresses = lib.mkForce [ - { - address = "fd00::1"; - prefixLength = 64; - } + listen-quic = [ + "0.0.0.0@853" + "::@853" ]; + automatic-acl = true; }; - services.knot.enable = true; - services.knot.extraArgs = [ "-v" ]; - services.knot.keyFiles = [ tsigFile ]; - services.knot.settings = { - server = { - listen = [ - "0.0.0.0@53" - "::@53" - ]; - listen-quic = [ - "0.0.0.0@853" - "::@853" - ]; - automatic-acl = true; - }; - acl.secondary_acl = { + acl.secondary_acl = { + address = "192.168.0.2"; + key = "xfr_key"; + action = "transfer"; + }; + + remote.secondary.address = "192.168.0.2@53"; + + template.default = { + storage = knotZonesEnv; + notify = [ "secondary" ]; + acl = [ "secondary_acl" ]; + dnssec-signing = true; + # Input-only zone files + # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-3 + # prevents modification of the zonefiles, since the zonefiles are immutable + zonefile-sync = -1; + zonefile-load = "difference"; + journal-content = "changes"; + }; + + zone = { + "example.com".file = "example.com.zone"; + "sub.example.com".file = "sub.example.com.zone"; + }; + + log.syslog.any = "info"; + }; + }; + + secondary = + { lib, ... }: + { + imports = [ common ]; + networking.interfaces.eth1 = { + ipv4.addresses = lib.mkForce [ + { address = "192.168.0.2"; - key = "xfr_key"; - action = "transfer"; - }; - - remote.secondary.address = "192.168.0.2@53"; - - template.default = { - storage = knotZonesEnv; - notify = [ "secondary" ]; - acl = [ "secondary_acl" ]; - dnssec-signing = true; - # Input-only zone files - # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-3 - # prevents modification of the zonefiles, since the zonefiles are immutable - zonefile-sync = -1; - zonefile-load = "difference"; - journal-content = "changes"; - }; - - zone = { - "example.com".file = "example.com.zone"; - "sub.example.com".file = "sub.example.com.zone"; - }; - - log.syslog.any = "info"; - }; + prefixLength = 24; + } + ]; + ipv6.addresses = lib.mkForce [ + { + address = "fd00::2"; + prefixLength = 64; + } + ]; }; - - secondary = - { lib, ... }: - { - imports = [ common ]; - networking.interfaces.eth1 = { - ipv4.addresses = lib.mkForce [ - { - address = "192.168.0.2"; - prefixLength = 24; - } - ]; - ipv6.addresses = lib.mkForce [ - { - address = "fd00::2"; - prefixLength = 64; - } - ]; + services.knot.enable = true; + services.knot.keyFiles = [ tsigFile ]; + services.knot.extraArgs = [ "-v" ]; + services.knot.settings = { + server = { + automatic-acl = true; }; - services.knot.enable = true; - services.knot.keyFiles = [ tsigFile ]; - services.knot.extraArgs = [ "-v" ]; - services.knot.settings = { - server = { - automatic-acl = true; - }; - xdp = { - listen = [ - "eth1" - ]; - tcp = true; - }; - - remote.primary = { - address = "192.168.0.1@53"; - key = "xfr_key"; - }; - - remote.primary-quic = { - address = "192.168.0.1@853"; - key = "xfr_key"; - quic = true; - }; - - template.default = { - # zonefileless setup - # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-2 - zonefile-sync = "-1"; - zonefile-load = "none"; - journal-content = "all"; - }; - - zone = { - "example.com" = { - master = "primary"; - file = "example.com.zone"; - }; - "sub.example.com" = { - master = "primary-quic"; - file = "sub.example.com.zone"; - }; - }; - - log.syslog.any = "debug"; + xdp = { + listen = [ + "eth1" + ]; + tcp = true; }; + + remote.primary = { + address = "192.168.0.1@53"; + key = "xfr_key"; + }; + + remote.primary-quic = { + address = "192.168.0.1@853"; + key = "xfr_key"; + quic = true; + }; + + template.default = { + # zonefileless setup + # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-2 + zonefile-sync = "-1"; + zonefile-load = "none"; + journal-content = "all"; + }; + + zone = { + "example.com" = { + master = "primary"; + file = "example.com.zone"; + }; + "sub.example.com" = { + master = "primary-quic"; + file = "sub.example.com.zone"; + }; + }; + + log.syslog.any = "debug"; }; - client = - { lib, nodes, ... }: - { - imports = [ common ]; - networking.interfaces.eth1 = { - ipv4.addresses = [ - { - address = "192.168.0.3"; - prefixLength = 24; - } - ]; - ipv6.addresses = [ - { - address = "fd00::3"; - prefixLength = 64; - } - ]; - }; - environment.systemPackages = [ pkgs.knot-dns ]; + }; + client = + { lib, nodes, ... }: + { + imports = [ common ]; + networking.interfaces.eth1 = { + ipv4.addresses = [ + { + address = "192.168.0.3"; + prefixLength = 24; + } + ]; + ipv6.addresses = [ + { + address = "fd00::3"; + prefixLength = 64; + } + ]; }; - }; + environment.systemPackages = [ pkgs.knot-dns ]; + }; + }; - testScript = - { nodes, ... }: - let - primary4 = (lib.head nodes.primary.config.networking.interfaces.eth1.ipv4.addresses).address; - primary6 = (lib.head nodes.primary.config.networking.interfaces.eth1.ipv6.addresses).address; + testScript = + { nodes, ... }: + let + primary4 = (lib.head nodes.primary.config.networking.interfaces.eth1.ipv4.addresses).address; + primary6 = (lib.head nodes.primary.config.networking.interfaces.eth1.ipv6.addresses).address; - secondary4 = (lib.head nodes.secondary.config.networking.interfaces.eth1.ipv4.addresses).address; - secondary6 = (lib.head nodes.secondary.config.networking.interfaces.eth1.ipv6.addresses).address; - in - '' - import re + secondary4 = (lib.head nodes.secondary.config.networking.interfaces.eth1.ipv4.addresses).address; + secondary6 = (lib.head nodes.secondary.config.networking.interfaces.eth1.ipv6.addresses).address; + in + '' + import re - start_all() + start_all() - client.wait_for_unit("network.target") - primary.wait_for_unit("knot.service") - secondary.wait_for_unit("knot.service") + client.wait_for_unit("network.target") + primary.wait_for_unit("knot.service") + secondary.wait_for_unit("knot.service") - for zone in ("example.com.", "sub.example.com."): - secondary.wait_until_succeeds( - f"knotc zone-status {zone} | grep -q 'serial: 2019031302'" - ) + for zone in ("example.com.", "sub.example.com."): + secondary.wait_until_succeeds( + f"knotc zone-status {zone} | grep -q 'serial: 2019031302'" + ) - def test(host, query_type, query, pattern): - out = client.succeed(f"khost -t {query_type} {query} {host}").strip() - client.log(f"{host} replied with: {out}") - assert re.search(pattern, out), f'Did not match "{pattern}"' + def test(host, query_type, query, pattern): + out = client.succeed(f"khost -t {query_type} {query} {host}").strip() + client.log(f"{host} replied with: {out}") + assert re.search(pattern, out), f'Did not match "{pattern}"' - for host in ("${primary4}", "${primary6}", "${secondary4}", "${secondary6}"): - with subtest(f"Interrogate {host}"): - test(host, "SOA", "example.com", r"start of authority.*noc\.example\.com\.") - test(host, "A", "example.com", r"has no [^ ]+ record") - test(host, "AAAA", "example.com", r"has no [^ ]+ record") + for host in ("${primary4}", "${primary6}", "${secondary4}", "${secondary6}"): + with subtest(f"Interrogate {host}"): + test(host, "SOA", "example.com", r"start of authority.*noc\.example\.com\.") + test(host, "A", "example.com", r"has no [^ ]+ record") + test(host, "AAAA", "example.com", r"has no [^ ]+ record") - test(host, "A", "www.example.com", r"address 192.0.2.1$") - test(host, "AAAA", "www.example.com", r"address 2001:db8::1$") + test(host, "A", "www.example.com", r"address 192.0.2.1$") + test(host, "AAAA", "www.example.com", r"address 2001:db8::1$") - test(host, "NS", "sub.example.com", r"nameserver is ns\d\.example\.com.$") - test(host, "A", "sub.example.com", r"address 192.0.2.2$") - test(host, "AAAA", "sub.example.com", r"address 2001:db8::2$") + test(host, "NS", "sub.example.com", r"nameserver is ns\d\.example\.com.$") + test(host, "A", "sub.example.com", r"address 192.0.2.2$") + test(host, "AAAA", "sub.example.com", r"address 2001:db8::2$") - test(host, "RRSIG", "www.example.com", r"RR set signature is") - test(host, "DNSKEY", "example.com", r"DNSSEC key is") + test(host, "RRSIG", "www.example.com", r"RR set signature is") + test(host, "DNSKEY", "example.com", r"DNSSEC key is") - primary.log(primary.succeed("systemd-analyze security knot.service | grep -v '✓'")) - ''; - } -) + primary.log(primary.succeed("systemd-analyze security knot.service | grep -v '✓'")) + ''; +}