diff options
Diffstat (limited to 'nixpkgs/nixos/tests')
27 files changed, 755 insertions, 132 deletions
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix index 3b4a39f5ff96..6f17bd2cdd3b 100644 --- a/nixpkgs/nixos/tests/all-tests.nix +++ b/nixpkgs/nixos/tests/all-tests.nix @@ -21,7 +21,7 @@ let if isAttrs val then if hasAttr "test" val then callTest val - else mapAttrs (n: s: discoverTests s) val + else mapAttrs (n: s: if n == "passthru" then s else discoverTests s) val else if isFunction val then # Tests based on make-test-python.nix will return the second lambda @@ -167,6 +167,7 @@ in { cgit = handleTest ./cgit.nix {}; charliecloud = handleTest ./charliecloud.nix {}; chromium = (handleTestOn ["aarch64-linux" "x86_64-linux"] ./chromium.nix {}).stable or {}; + chrony = handleTestOn ["aarch64-linux" "x86_64-linux"] ./chrony.nix {}; chrony-ptp = handleTestOn ["aarch64-linux" "x86_64-linux"] ./chrony-ptp.nix {}; cinnamon = handleTest ./cinnamon.nix {}; cjdns = handleTest ./cjdns.nix {}; @@ -217,7 +218,7 @@ in { disable-installer-tools = handleTest ./disable-installer-tools.nix {}; discourse = handleTest ./discourse.nix {}; dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {}; - dnscrypt-wrapper = handleTestOn ["x86_64-linux"] ./dnscrypt-wrapper {}; + dnscrypt-wrapper = runTestOn ["x86_64-linux"] ./dnscrypt-wrapper; dnsdist = handleTest ./dnsdist.nix {}; doas = handleTest ./doas.nix {}; docker = handleTestOn ["aarch64-linux" "x86_64-linux"] ./docker.nix {}; @@ -252,6 +253,7 @@ in { envoy = handleTest ./envoy.nix {}; ergo = handleTest ./ergo.nix {}; ergochat = handleTest ./ergochat.nix {}; + eris-server = handleTest ./eris-server.nix {}; esphome = handleTest ./esphome.nix {}; etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; }; activation = pkgs.callPackage ../modules/system/activation/test.nix { }; @@ -365,6 +367,7 @@ in { iftop = handleTest ./iftop.nix {}; incron = handleTest ./incron.nix {}; influxdb = handleTest ./influxdb.nix {}; + influxdb2 = handleTest ./influxdb2.nix {}; initrd-network-openvpn = handleTest ./initrd-network-openvpn {}; initrd-network-ssh = handleTest ./initrd-network-ssh {}; initrd-luks-empty-passphrase = handleTest ./initrd-luks-empty-passphrase.nix {}; @@ -388,6 +391,7 @@ in { jibri = handleTest ./jibri.nix {}; jirafeau = handleTest ./jirafeau.nix {}; jitsi-meet = handleTest ./jitsi-meet.nix {}; + jool = handleTest ./jool.nix {}; k3s = handleTest ./k3s {}; kafka = handleTest ./kafka.nix {}; kanidm = handleTest ./kanidm.nix {}; @@ -461,6 +465,7 @@ in { matrix-conduit = handleTest ./matrix/conduit.nix {}; matrix-synapse = handleTest ./matrix/synapse.nix {}; mattermost = handleTest ./mattermost.nix {}; + mediamtx = handleTest ./mediamtx.nix {}; mediatomb = handleTest ./mediatomb.nix {}; mediawiki = handleTest ./mediawiki.nix {}; meilisearch = handleTest ./meilisearch.nix {}; @@ -569,6 +574,7 @@ in { openresty-lua = handleTest ./openresty-lua.nix {}; opensmtpd = handleTest ./opensmtpd.nix {}; opensmtpd-rspamd = handleTest ./opensmtpd-rspamd.nix {}; + opensnitch = handleTest ./opensnitch.nix {}; openssh = handleTest ./openssh.nix {}; octoprint = handleTest ./octoprint.nix {}; openstack-image-metadata = (handleTestOn ["x86_64-linux"] ./openstack-image.nix {}).metadata or {}; diff --git a/nixpkgs/nixos/tests/budgie.nix b/nixpkgs/nixos/tests/budgie.nix index 34ee1e303de9..19d9b2bd0bed 100644 --- a/nixpkgs/nixos/tests/budgie.nix +++ b/nixpkgs/nixos/tests/budgie.nix @@ -52,10 +52,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { machine.wait_for_window("budgie-daemon") machine.wait_until_succeeds("pgrep budgie-panel") machine.wait_for_window("budgie-panel") + # We don't check xwininfo for this one. + # See https://github.com/NixOS/nixpkgs/pull/216737#discussion_r1155312754 + machine.wait_until_succeeds("pgrep budgie-wm") with subtest("Open MATE terminal"): machine.succeed("su - ${user.name} -c 'DISPLAY=:0 mate-terminal >&2 &'") machine.wait_for_window("Terminal") + + with subtest("Check if budgie-wm has ever coredumped"): + machine.fail("coredumpctl --json=short | grep budgie-wm") machine.sleep(20) machine.screenshot("screen") ''; diff --git a/nixpkgs/nixos/tests/caddy.nix b/nixpkgs/nixos/tests/caddy.nix index ed88f08739e8..238091ec606f 100644 --- a/nixpkgs/nixos/tests/caddy.nix +++ b/nixpkgs/nixos/tests/caddy.nix @@ -22,22 +22,6 @@ import ./make-test-python.nix ({ pkgs, ... }: { ''; services.caddy.enableReload = true; - specialisation.etag.configuration = { - services.caddy.extraConfig = lib.mkForce '' - http://localhost { - encode gzip - - file_server - root * ${ - pkgs.runCommand "testdir2" {} '' - mkdir "$out" - echo changed > "$out/example.html" - '' - } - } - ''; - }; - specialisation.config-reload.configuration = { services.caddy.extraConfig = '' http://localhost:8080 { @@ -55,7 +39,6 @@ import ./make-test-python.nix ({ pkgs, ... }: { testScript = { nodes, ... }: let - etagSystem = "${nodes.webserver.system.build.toplevel}/specialisation/etag"; justReloadSystem = "${nodes.webserver.system.build.toplevel}/specialisation/config-reload"; multipleConfigs = "${nodes.webserver.system.build.toplevel}/specialisation/multiple-configs"; in @@ -65,33 +48,6 @@ import ./make-test-python.nix ({ pkgs, ... }: { webserver.wait_for_open_port(80) - def check_etag(url): - etag = webserver.succeed( - "curl --fail -v '{}' 2>&1 | sed -n -e \"s/^< [Ee][Tt][Aa][Gg]: *//p\"".format( - url - ) - ) - etag = etag.replace("\r\n", " ") - http_code = webserver.succeed( - "curl --fail --silent --show-error -o /dev/null -w \"%{{http_code}}\" --head -H 'If-None-Match: {}' {}".format( - etag, url - ) - ) - assert int(http_code) == 304, "HTTP code is {}, expected 304".format(http_code) - return etag - - - with subtest("check ETag if serving Nix store paths"): - old_etag = check_etag(url) - webserver.succeed( - "${etagSystem}/bin/switch-to-configuration test >&2" - ) - webserver.sleep(1) - new_etag = check_etag(url) - assert old_etag != new_etag, "Old ETag {} is the same as {}".format( - old_etag, new_etag - ) - with subtest("config is reloaded on nixos-rebuild switch"): webserver.succeed( "${justReloadSystem}/bin/switch-to-configuration test >&2" diff --git a/nixpkgs/nixos/tests/chrony.nix b/nixpkgs/nixos/tests/chrony.nix new file mode 100644 index 000000000000..578b1e32d50c --- /dev/null +++ b/nixpkgs/nixos/tests/chrony.nix @@ -0,0 +1,31 @@ +import ./make-test-python.nix ({ lib, ... }: +{ + name = "chrony"; + + meta = { + maintainers = with lib.maintainers; [ fpletz ]; + }; + + nodes = { + default = { + services.chrony.enable = true; + }; + graphene-hardened = { + services.chrony.enable = true; + services.chrony.enableMemoryLocking = true; + environment.memoryAllocator.provider = "graphene-hardened"; + # dhcpcd privsep is incompatible with graphene-hardened + networking.useNetworkd = true; + }; + }; + + testScript = {nodes, ...} : let + graphene-hardened = nodes.graphene-hardened.system.build.toplevel; + in '' + default.start() + default.wait_for_unit('multi-user.target') + default.succeed('systemctl is-active chronyd.service') + default.succeed('${graphene-hardened}/bin/switch-to-configuration test') + default.succeed('systemctl is-active chronyd.service') + ''; +}) diff --git a/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix b/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix index 1bdd064e1130..1c05376e097b 100644 --- a/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix +++ b/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix @@ -1,4 +1,6 @@ -import ../make-test-python.nix ({ pkgs, ... }: { +{ lib, pkgs, ... }: + +{ name = "dnscrypt-wrapper"; meta = with pkgs.lib.maintainers; { maintainers = [ rnhmjoj ]; @@ -50,23 +52,23 @@ import ../make-test-python.nix ({ pkgs, ... }: { server.wait_for_unit("dnscrypt-wrapper") server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.key") server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.crt") + almost_expiration = server.succeed("date --date '4days 23 hours 56min'").strip() with subtest("The client can connect to the server"): server.wait_for_unit("tinydns") client.wait_for_unit("dnscrypt-proxy2") - assert "1.2.3.4" in client.succeed( + assert "1.2.3.4" in client.wait_until_succeeds( "host it.works" ), "The IP address of 'it.works' does not match 1.2.3.4" with subtest("The server rotates the ephemeral keys"): # advance time by a little less than 5 days - server.succeed("date -s \"$(date --date '4 days 6 hours')\"") - client.succeed("date -s \"$(date --date '4 days 6 hours')\"") + server.succeed(f"date -s '{almost_expiration}'") + client.succeed(f"date -s '{almost_expiration}'") server.wait_for_file("/var/lib/dnscrypt-wrapper/oldkeys") with subtest("The client can still connect to the server"): server.wait_for_unit("dnscrypt-wrapper") client.succeed("host it.works") ''; -}) - +} diff --git a/nixpkgs/nixos/tests/eris-server.nix b/nixpkgs/nixos/tests/eris-server.nix new file mode 100644 index 000000000000..a50db3afebf5 --- /dev/null +++ b/nixpkgs/nixos/tests/eris-server.nix @@ -0,0 +1,23 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "eris-server"; + meta.maintainers = with lib.maintainers; [ ehmry ]; + + nodes.server = { + environment.systemPackages = [ pkgs.eris-go pkgs.nim.pkgs.eris ]; + services.eris-server = { + enable = true; + decode = true; + listenHttp = "[::1]:80"; + backends = [ "badger+file:///var/cache/eris.badger?get&put" ]; + mountpoint = "/eris"; + }; + }; + + testScript = '' + start_all() + server.wait_for_unit("eris-server.service") + server.wait_for_open_port(5683) + server.wait_for_open_port(80) + server.succeed("eriscmd get http://[::1] $(echo 'Hail ERIS!' | eriscmd put coap+tcp://[::1]:5683)") + ''; +}) diff --git a/nixpkgs/nixos/tests/fcitx5/config b/nixpkgs/nixos/tests/fcitx5/config deleted file mode 100644 index cf4334639f1c..000000000000 --- a/nixpkgs/nixos/tests/fcitx5/config +++ /dev/null @@ -1,11 +0,0 @@ -[Hotkey] -EnumerateSkipFirst=False - -[Hotkey/TriggerKeys] -0=Control+space - -[Hotkey/EnumerateForwardKeys] -0=Alt+Shift_L - -[Hotkey/EnumerateBackwardKeys] -0=Alt+Shift_R diff --git a/nixpkgs/nixos/tests/fcitx5/default.nix b/nixpkgs/nixos/tests/fcitx5/default.nix index 9b000da48eaf..c113f2e2c052 100644 --- a/nixpkgs/nixos/tests/fcitx5/default.nix +++ b/nixpkgs/nixos/tests/fcitx5/default.nix @@ -36,6 +36,43 @@ rec { pkgs.fcitx5-m17n pkgs.fcitx5-mozc ]; + fcitx5.settings = { + globalOptions = { + "Hotkey"."EnumerateSkipFirst" = "False"; + "Hotkey/TriggerKeys"."0" = "Control+space"; + "Hotkey/EnumerateForwardKeys"."0" = "Alt+Shift_L"; + "Hotkey/EnumerateBackwardKeys"."0" = "Alt+Shift_R"; + }; + inputMethod = { + "GroupOrder" = { + "0" = "NixOS_test"; + }; + "Groups/0" = { + "Default Layout" = "us"; + "DefaultIM" = "wbx"; + "Name" = "NixOS_test"; + }; + "Groups/0/Items/0" = { + "Name" = "keyboard-us"; + }; + "Groups/0/Items/1" = { + "Layout" = "us"; + "Name" = "wbx"; + }; + "Groups/0/Items/2" = { + "Layout" = "us"; + "Name" = "hangul"; + }; + "Groups/0/Items/3" = { + "Layout" = "us"; + "Name" = "m17n_sa_harvard-kyoto"; + }; + "Groups/0/Items/4" = { + "Layout" = "us"; + "Name" = "mozc"; + }; + }; + }; }; }; @@ -43,7 +80,6 @@ rec { let user = nodes.machine.users.users.alice; xauth = "${user.home}/.Xauthority"; - fcitx_confdir = "${user.home}/.config/fcitx5"; in '' start_all() @@ -56,15 +92,6 @@ rec { machine.succeed("su - ${user.name} -c 'kill $(pgrep fcitx5)'") machine.sleep(1) - machine.copy_from_host( - "${./profile}", - "${fcitx_confdir}/profile", - ) - machine.copy_from_host( - "${./config}", - "${fcitx_confdir}/config", - ) - machine.succeed("su - ${user.name} -c 'alacritty >&2 &'") machine.succeed("su - ${user.name} -c 'fcitx5 >&2 &'") machine.sleep(10) diff --git a/nixpkgs/nixos/tests/fcitx5/profile b/nixpkgs/nixos/tests/fcitx5/profile deleted file mode 100644 index 1b48c634e0eb..000000000000 --- a/nixpkgs/nixos/tests/fcitx5/profile +++ /dev/null @@ -1,27 +0,0 @@ -[Groups/0] -Name=NixOS_test -Default Layout=us -DefaultIM=wbx - -[Groups/0/Items/0] -Name=keyboard-us -Layout= - -[Groups/0/Items/1] -Name=wbx -Layout=us - -[Groups/0/Items/2] -Name=hangul -Layout=us - -[Groups/0/Items/3] -Name=m17n_sa_harvard-kyoto -Layout=us - -[Groups/0/Items/4] -Name=mozc -Layout=us - -[GroupOrder] -0=NixOS_test diff --git a/nixpkgs/nixos/tests/influxdb2.nix b/nixpkgs/nixos/tests/influxdb2.nix new file mode 100644 index 000000000000..c9c54b788cc0 --- /dev/null +++ b/nixpkgs/nixos/tests/influxdb2.nix @@ -0,0 +1,36 @@ +import ./make-test-python.nix ({ pkgs, ...} : { + name = "influxdb2"; + meta = with pkgs.lib.maintainers; { + maintainers = [ offline ]; + }; + + nodes.machine = { lib, ... }: { + environment.systemPackages = [ pkgs.influxdb2-cli ]; + services.influxdb2.enable = true; + services.influxdb2.provision = { + enable = true; + initialSetup = { + organization = "default"; + bucket = "default"; + passwordFile = pkgs.writeText "admin-pw" "ExAmPl3PA55W0rD"; + tokenFile = pkgs.writeText "admin-token" "verysecureadmintoken"; + }; + }; + }; + + testScript = { nodes, ... }: + let + tokenArg = "--token verysecureadmintoken"; + in '' + machine.wait_for_unit("influxdb2.service") + + machine.fail("curl --fail -X POST 'http://localhost:8086/api/v2/signin' -u admin:wrongpassword") + machine.succeed("curl --fail -X POST 'http://localhost:8086/api/v2/signin' -u admin:ExAmPl3PA55W0rD") + + out = machine.succeed("influx org list ${tokenArg}") + assert "default" in out + + out = machine.succeed("influx bucket list ${tokenArg} --org default") + assert "default" in out + ''; +}) diff --git a/nixpkgs/nixos/tests/jool.nix b/nixpkgs/nixos/tests/jool.nix new file mode 100644 index 000000000000..6d5ded9b18e0 --- /dev/null +++ b/nixpkgs/nixos/tests/jool.nix @@ -0,0 +1,250 @@ +{ system ? builtins.currentSystem, + config ? {}, + pkgs ? import ../.. { inherit system config; } +}: + +with import ../lib/testing-python.nix { inherit system pkgs; }; + +let + inherit (pkgs) lib; + + ipv6Only = { + networking.useDHCP = false; + networking.interfaces.eth1.ipv4.addresses = lib.mkVMOverride [ ]; + }; + + ipv4Only = { + networking.useDHCP = false; + networking.interfaces.eth1.ipv6.addresses = lib.mkVMOverride [ ]; + }; + + webserver = ip: msg: { + systemd.services.webserver = { + description = "Mock webserver"; + wants = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig.Restart = "always"; + script = '' + while true; do + { + printf 'HTTP/1.0 200 OK\n' + printf 'Content-Length: ${toString (1 + builtins.stringLength msg)}\n' + printf '\n${msg}\n\n' + } | ${pkgs.libressl.nc}/bin/nc -${toString ip}nvl 80 + done + ''; + }; + networking.firewall.allowedTCPPorts = [ 80 ]; + }; + +in + +{ + siit = makeTest { + # This test simulates the setup described in [1] with two IPv6 and + # IPv4-only devices on different subnets communicating through a border + # relay running Jool in SIIT mode. + # [1]: https://nicmx.github.io/Jool/en/run-vanilla.html + name = "jool-siit"; + meta.maintainers = with lib.maintainers; [ rnhmjoj ]; + + # Border relay + nodes.relay = { ... }: { + imports = [ ../modules/profiles/minimal.nix ]; + virtualisation.vlans = [ 1 2 ]; + + # Enable packet routing + boot.kernel.sysctl = { + "net.ipv6.conf.all.forwarding" = 1; + "net.ipv4.conf.all.forwarding" = 1; + }; + + networking.useDHCP = false; + networking.interfaces = lib.mkVMOverride { + eth1.ipv6.addresses = [ { address = "fd::198.51.100.1"; prefixLength = 120; } ]; + eth2.ipv4.addresses = [ { address = "192.0.2.1"; prefixLength = 24; } ]; + }; + + networking.jool = { + enable = true; + siit.enable = true; + siit.config.global.pool6 = "fd::/96"; + }; + }; + + # IPv6 only node + nodes.alice = { ... }: { + imports = [ + ../modules/profiles/minimal.nix + ipv6Only + (webserver 6 "Hello, Bob!") + ]; + + virtualisation.vlans = [ 1 ]; + networking.interfaces.eth1.ipv6 = { + addresses = [ { address = "fd::198.51.100.8"; prefixLength = 120; } ]; + routes = [ { address = "fd::192.0.2.0"; prefixLength = 120; + via = "fd::198.51.100.1"; } ]; + }; + }; + + # IPv4 only node + nodes.bob = { ... }: { + imports = [ + ../modules/profiles/minimal.nix + ipv4Only + (webserver 4 "Hello, Alice!") + ]; + + virtualisation.vlans = [ 2 ]; + networking.interfaces.eth1.ipv4 = { + addresses = [ { address = "192.0.2.16"; prefixLength = 24; } ]; + routes = [ { address = "198.51.100.0"; prefixLength = 24; + via = "192.0.2.1"; } ]; + }; + }; + + testScript = '' + start_all() + + relay.wait_for_unit("jool-siit.service") + alice.wait_for_unit("network-addresses-eth1.service") + bob.wait_for_unit("network-addresses-eth1.service") + + with subtest("Alice and Bob can't ping each other"): + relay.systemctl("stop jool-siit.service") + alice.fail("ping -c1 fd::192.0.2.16") + bob.fail("ping -c1 198.51.100.8") + + with subtest("Alice and Bob can ping using the relay"): + relay.systemctl("start jool-siit.service") + alice.wait_until_succeeds("ping -c1 fd::192.0.2.16") + bob.wait_until_succeeds("ping -c1 198.51.100.8") + + with subtest("Alice can connect to Bob's webserver"): + bob.wait_for_open_port(80) + alice.succeed("curl -vvv http://[fd::192.0.2.16] >&2") + alice.succeed("curl --fail -s http://[fd::192.0.2.16] | grep -q Alice") + + with subtest("Bob can connect to Alices's webserver"): + alice.wait_for_open_port(80) + bob.succeed("curl --fail -s http://198.51.100.8 | grep -q Bob") + ''; + }; + + nat64 = makeTest { + # This test simulates the setup described in [1] with two IPv6-only nodes + # (a client and a homeserver) on the LAN subnet and an IPv4 node on the WAN. + # The router runs Jool in stateful NAT64 mode, masquarading the LAN and + # forwarding ports using static BIB entries. + # [1]: https://nicmx.github.io/Jool/en/run-nat64.html + name = "jool-nat64"; + meta.maintainers = with lib.maintainers; [ rnhmjoj ]; + + # Router + nodes.router = { ... }: { + imports = [ ../modules/profiles/minimal.nix ]; + virtualisation.vlans = [ 1 2 ]; + + # Enable packet routing + boot.kernel.sysctl = { + "net.ipv6.conf.all.forwarding" = 1; + "net.ipv4.conf.all.forwarding" = 1; + }; + + networking.useDHCP = false; + networking.interfaces = lib.mkVMOverride { + eth1.ipv6.addresses = [ { address = "2001:db8::1"; prefixLength = 96; } ]; + eth2.ipv4.addresses = [ { address = "203.0.113.1"; prefixLength = 24; } ]; + }; + + networking.jool = { + enable = true; + nat64.enable = true; + nat64.config = { + bib = [ + { # forward HTTP 203.0.113.1 (router) → 2001:db8::9 (homeserver) + "protocol" = "TCP"; + "ipv4 address" = "203.0.113.1#80"; + "ipv6 address" = "2001:db8::9#80"; + } + ]; + pool4 = [ + # Ports for dynamic translation + { protocol = "TCP"; prefix = "203.0.113.1/32"; "port range" = "40001-65535"; } + { protocol = "UDP"; prefix = "203.0.113.1/32"; "port range" = "40001-65535"; } + { protocol = "ICMP"; prefix = "203.0.113.1/32"; "port range" = "40001-65535"; } + # Ports for static BIB entries + { protocol = "TCP"; prefix = "203.0.113.1/32"; "port range" = "80"; } + ]; + }; + }; + }; + + # LAN client (IPv6 only) + nodes.client = { ... }: { + imports = [ ../modules/profiles/minimal.nix ipv6Only ]; + virtualisation.vlans = [ 1 ]; + + networking.interfaces.eth1.ipv6 = { + addresses = [ { address = "2001:db8::8"; prefixLength = 96; } ]; + routes = [ { address = "64:ff9b::"; prefixLength = 96; + via = "2001:db8::1"; } ]; + }; + }; + + # LAN server (IPv6 only) + nodes.homeserver = { ... }: { + imports = [ + ../modules/profiles/minimal.nix + ipv6Only + (webserver 6 "Hello from IPv6!") + ]; + + virtualisation.vlans = [ 1 ]; + networking.interfaces.eth1.ipv6 = { + addresses = [ { address = "2001:db8::9"; prefixLength = 96; } ]; + routes = [ { address = "64:ff9b::"; prefixLength = 96; + via = "2001:db8::1"; } ]; + }; + }; + + # WAN server (IPv4 only) + nodes.server = { ... }: { + imports = [ + ../modules/profiles/minimal.nix + ipv4Only + (webserver 4 "Hello from IPv4!") + ]; + + virtualisation.vlans = [ 2 ]; + networking.interfaces.eth1.ipv4.addresses = + [ { address = "203.0.113.16"; prefixLength = 24; } ]; + }; + + testScript = '' + start_all() + + for node in [client, homeserver, server]: + node.wait_for_unit("network-addresses-eth1.service") + + with subtest("Client can ping the WAN server"): + router.wait_for_unit("jool-nat64.service") + client.succeed("ping -c1 64:ff9b::203.0.113.16") + + with subtest("Client can connect to the WAN webserver"): + server.wait_for_open_port(80) + client.succeed("curl --fail -s http://[64:ff9b::203.0.113.16] | grep -q IPv4!") + + with subtest("Router BIB entries are correctly populated"): + router.succeed("jool bib display | grep -q 'Dynamic TCP.*2001:db8::8'") + router.succeed("jool bib display | grep -q 'Static TCP.*2001:db8::9'") + + with subtest("WAN server can reach the LAN server"): + homeserver.wait_for_open_port(80) + server.succeed("curl --fail -s http://203.0.113.1 | grep -q IPv6!") + ''; + + }; + +} diff --git a/nixpkgs/nixos/tests/kernel-generic.nix b/nixpkgs/nixos/tests/kernel-generic.nix index e4a8e06df1ef..e69dd550289c 100644 --- a/nixpkgs/nixos/tests/kernel-generic.nix +++ b/nixpkgs/nixos/tests/kernel-generic.nix @@ -42,7 +42,9 @@ let }; in mapAttrs (_: lP: testsForLinuxPackages lP) kernels // { - inherit testsForLinuxPackages; + passthru = { + inherit testsForLinuxPackages; - testsForKernel = kernel: testsForLinuxPackages (pkgs.linuxPackagesFor kernel); + testsForKernel = kernel: testsForLinuxPackages (pkgs.linuxPackagesFor kernel); + }; } diff --git a/nixpkgs/nixos/tests/libvirtd.nix b/nixpkgs/nixos/tests/libvirtd.nix index b6e604075997..41d06cc9643f 100644 --- a/nixpkgs/nixos/tests/libvirtd.nix +++ b/nixpkgs/nixos/tests/libvirtd.nix @@ -11,6 +11,9 @@ import ./make-test-python.nix ({ pkgs, ... }: { memorySize = 2048; libvirtd.enable = true; + libvirtd.hooks.qemu.is_working = "${pkgs.writeShellScript "testHook.sh" '' + touch /tmp/qemu_hook_is_working + ''}"; }; boot.supportedFilesystems = [ "zfs" ]; networking.hostId = "deadbeef"; # needed for zfs @@ -57,5 +60,9 @@ import ./make-test-python.nix ({ pkgs, ... }: { virthost.shutdown() virthost.wait_for_unit("multi-user.target") virthost.wait_until_succeeds("ping -c 1 nixos") + + with subtest("test if hooks are linked and run"): + virthost.succeed("ls /var/lib/libvirt/hooks/qemu.d/is_working") + virthost.succeed("ls /tmp/qemu_hook_is_working") ''; }) diff --git a/nixpkgs/nixos/tests/matrix/synapse.nix b/nixpkgs/nixos/tests/matrix/synapse.nix index 698d67c793e3..98b077469192 100644 --- a/nixpkgs/nixos/tests/matrix/synapse.nix +++ b/nixpkgs/nixos/tests/matrix/synapse.nix @@ -65,7 +65,7 @@ in { nodes = { # Since 0.33.0, matrix-synapse doesn't allow underscores in server names - serverpostgres = { pkgs, nodes, ... }: let + serverpostgres = { pkgs, nodes, config, ... }: let mailserverIP = nodes.mailserver.config.networking.primaryIPAddress; in { @@ -77,6 +77,11 @@ in { name = "psycopg2"; args.password = "synapse"; }; + redis = { + enabled = true; + host = "localhost"; + port = config.services.redis.servers.matrix-synapse.port; + }; tls_certificate_path = "${cert}"; tls_private_key_path = "${key}"; registration_shared_secret = registrationSharedSecret; @@ -107,6 +112,11 @@ in { ''; }; + services.redis.servers.matrix-synapse = { + enable = true; + port = 6380; + }; + networking.extraHosts = '' ${mailserverIP} ${mailerDomain} ''; @@ -208,6 +218,9 @@ in { serverpostgres.wait_until_succeeds( "curl --fail -L --cacert ${ca_pem} https://localhost:8448/" ) + serverpostgres.wait_until_succeeds( + "journalctl -u matrix-synapse.service | grep -q 'Connected to redis'" + ) serverpostgres.require_unit_state("postgresql.service") serverpostgres.succeed("register_new_matrix_user -u ${testUser} -p ${testPassword} -a -k ${registrationSharedSecret} https://localhost:8448/") serverpostgres.succeed("obtain-token-and-register-email") diff --git a/nixpkgs/nixos/tests/mediamtx.nix b/nixpkgs/nixos/tests/mediamtx.nix new file mode 100644 index 000000000000..8cacd02631d9 --- /dev/null +++ b/nixpkgs/nixos/tests/mediamtx.nix @@ -0,0 +1,57 @@ +import ./make-test-python.nix ({ pkgs, lib, ...} : + +{ + name = "mediamtx"; + meta.maintainers = with lib.maintainers; [ fpletz ]; + + nodes = { + machine = { config, ... }: { + services.mediamtx = { + enable = true; + settings = { + metrics = true; + paths.all.source = "publisher"; + }; + }; + + systemd.services.rtmp-publish = { + description = "Publish an RTMP stream to mediamtx"; + after = [ "mediamtx.service" ]; + bindsTo = [ "mediamtx.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + DynamicUser = true; + Restart = "on-failure"; + RestartSec = "1s"; + TimeoutStartSec = "10s"; + ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -re -f lavfi -i smptebars=size=800x600:rate=10 -c libx264 -f flv rtmp://localhost:1935/test"; + }; + }; + + systemd.services.rtmp-receive = { + description = "Receive an RTMP stream from mediamtx"; + after = [ "rtmp-publish.service" ]; + bindsTo = [ "rtmp-publish.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + DynamicUser = true; + Restart = "on-failure"; + RestartSec = "1s"; + TimeoutStartSec = "10s"; + ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -y -re -i rtmp://localhost:1935/test -f flv /dev/null"; + }; + }; + }; + }; + + testScript = '' + start_all() + + machine.wait_for_unit("mediamtx.service") + machine.wait_for_unit("rtmp-publish.service") + machine.wait_for_unit("rtmp-receive.service") + machine.wait_for_open_port(9998) + machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"publish\".*1$'") + machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"read\".*1$'") + ''; +}) diff --git a/nixpkgs/nixos/tests/netdata.nix b/nixpkgs/nixos/tests/netdata.nix index aea67c29d0d4..c5f7294f79ab 100644 --- a/nixpkgs/nixos/tests/netdata.nix +++ b/nixpkgs/nixos/tests/netdata.nix @@ -10,7 +10,7 @@ import ./make-test-python.nix ({ pkgs, ...} : { netdata = { pkgs, ... }: { - environment.systemPackages = with pkgs; [ curl jq ]; + environment.systemPackages = with pkgs; [ curl jq netdata ]; services.netdata.enable = true; }; }; @@ -34,5 +34,8 @@ import ./make-test-python.nix ({ pkgs, ...} : { filter = '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0' cmd = f"curl -s {url} | jq -e '{filter}'" netdata.wait_until_succeeds(cmd) + + # check if the control socket is available + netdata.succeed("sudo netdatacli ping") ''; }) diff --git a/nixpkgs/nixos/tests/nextcloud/basic.nix b/nixpkgs/nixos/tests/nextcloud/basic.nix index db5cee9f6584..b7af6d6d7364 100644 --- a/nixpkgs/nixos/tests/nextcloud/basic.nix +++ b/nixpkgs/nixos/tests/nextcloud/basic.nix @@ -90,8 +90,8 @@ in { test -e graph grep "$what" graph >$out || true ''; - nextcloudUsesImagick = findInClosure "imagick" nodes.nextcloud.config.system.build.vm; - nextcloudWithoutDoesntUseIt = findInClosure "imagick" nodes.nextcloudWithoutMagick.config.system.build.vm; + nextcloudUsesImagick = findInClosure "imagick" nodes.nextcloud.system.build.vm; + nextcloudWithoutDoesntUseIt = findInClosure "imagick" nodes.nextcloudWithoutMagick.system.build.vm; in '' assert open("${nextcloudUsesImagick}").read() != "" assert open("${nextcloudWithoutDoesntUseIt}").read() == "" diff --git a/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix b/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix index 92beb869eb03..d6ea39c6155a 100644 --- a/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix +++ b/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix @@ -49,8 +49,8 @@ in { #!${pkgs.runtimeShell} echo 'bye' | ${withRcloneEnv3} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file2 ''; - openssl1-node = nodes.nextcloudwithopenssl1.config.system.build.toplevel; - openssl3-node = nodes.nextcloudwithopenssl3.config.system.build.toplevel; + openssl1-node = nodes.nextcloudwithopenssl1.system.build.toplevel; + openssl3-node = nodes.nextcloudwithopenssl3.system.build.toplevel; in '' nextcloudwithopenssl1.start() nextcloudwithopenssl1.wait_for_unit("multi-user.target") diff --git a/nixpkgs/nixos/tests/nixops/default.nix b/nixpkgs/nixos/tests/nixops/default.nix index bd00e6143639..b8f747b2a19f 100644 --- a/nixpkgs/nixos/tests/nixops/default.nix +++ b/nixpkgs/nixos/tests/nixops/default.nix @@ -14,11 +14,12 @@ let # inherit testsForPackage; }; - testsForPackage = lib.makeOverridable (args: lib.recurseIntoAttrs { + testsForPackage = args: lib.recurseIntoAttrs { legacyNetwork = testLegacyNetwork args; - }); + passthru.override = args': testsForPackage (args // args'); + }; - testLegacyNetwork = { nixopsPkg }: pkgs.nixosTest ({ + testLegacyNetwork = { nixopsPkg, ... }: pkgs.nixosTest ({ name = "nixops-legacy-network"; nodes = { deployer = { config, lib, nodes, pkgs, ... }: { @@ -52,7 +53,7 @@ let chmod 0400 ~/.ssh/id_ed25519 ''; serverNetworkJSON = pkgs.writeText "server-network.json" - (builtins.toJSON nodes.server.config.system.build.networkConfig); + (builtins.toJSON nodes.server.system.build.networkConfig); in '' import shlex diff --git a/nixpkgs/nixos/tests/opensnitch.nix b/nixpkgs/nixos/tests/opensnitch.nix new file mode 100644 index 000000000000..d84e4e0a935b --- /dev/null +++ b/nixpkgs/nixos/tests/opensnitch.nix @@ -0,0 +1,62 @@ +import ./make-test-python.nix ({ pkgs, ... }: { + name = "opensnitch"; + + meta = with pkgs.lib.maintainers; { + maintainers = [ onny ]; + }; + + nodes = { + server = + { ... }: { + networking.firewall.allowedTCPPorts = [ 80 ]; + services.caddy = { + enable = true; + virtualHosts."localhost".extraConfig = '' + respond "Hello, world!" + ''; + }; + }; + + clientBlocked = + { ... }: { + services.opensnitch = { + enable = true; + settings.DefaultAction = "deny"; + }; + }; + + clientAllowed = + { ... }: { + services.opensnitch = { + enable = true; + settings.DefaultAction = "deny"; + rules = { + opensnitch = { + name = "curl"; + enabled = true; + action = "allow"; + duration = "always"; + operator = { + type ="simple"; + sensitive = false; + operand = "process.path"; + data = "${pkgs.curl}/bin/curl"; + }; + }; + }; + }; + }; + }; + + testScript = '' + start_all() + server.wait_for_unit("caddy.service") + server.wait_for_open_port(80) + + clientBlocked.wait_for_unit("opensnitchd.service") + clientBlocked.fail("curl http://server") + + clientAllowed.wait_for_unit("opensnitchd.service") + clientAllowed.succeed("curl http://server") + ''; +}) diff --git a/nixpkgs/nixos/tests/pantheon.nix b/nixpkgs/nixos/tests/pantheon.nix index 653fcc6edad1..dee6964644c5 100644 --- a/nixpkgs/nixos/tests/pantheon.nix +++ b/nixpkgs/nixos/tests/pantheon.nix @@ -60,6 +60,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with subtest("Open elementary terminal"): machine.execute("su - ${user.name} -c 'DISPLAY=:0 io.elementary.terminal >&2 &'") machine.wait_for_window("io.elementary.terminal") + + with subtest("Check if gala has ever coredumped"): + machine.fail("coredumpctl --json=short | grep gala") machine.sleep(20) machine.screenshot("screen") ''; diff --git a/nixpkgs/nixos/tests/prometheus-exporters.nix b/nixpkgs/nixos/tests/prometheus-exporters.nix index 23740dd98e3d..d86f8ac634e8 100644 --- a/nixpkgs/nixos/tests/prometheus-exporters.nix +++ b/nixpkgs/nixos/tests/prometheus-exporters.nix @@ -307,6 +307,23 @@ let ''; }; + idrac = { + exporterConfig = { + enable = true; + port = 9348; + configuration = { + hosts = { + default = { username = "username"; password = "password"; }; + }; + }; + }; + exporterTest = '' + wait_for_unit("prometheus-idrac-exporter.service") + wait_for_open_port(9348) + wait_until_succeeds("curl localhost:9348") + ''; + }; + influxdb = { exporterConfig = { enable = true; @@ -1183,7 +1200,7 @@ let }; exporterTest = '' wait_until_succeeds( - 'journalctl -eu prometheus-smartctl-exporter.service -o cat | grep "Device unavailable"' + 'journalctl -eu prometheus-smartctl-exporter.service -o cat | grep "Unable to detect device type"' ) ''; }; diff --git a/nixpkgs/nixos/tests/switch-test.nix b/nixpkgs/nixos/tests/switch-test.nix index f44dede7fef4..53595ae7d3e2 100644 --- a/nixpkgs/nixos/tests/switch-test.nix +++ b/nixpkgs/nixos/tests/switch-test.nix @@ -1,6 +1,6 @@ # Test configuration switching. -import ./make-test-python.nix ({ pkgs, ...} : let +import ./make-test-python.nix ({ lib, pkgs, ...} : let # Simple service that can either be socket-activated or that will # listen on port 1234 if not socket-activated. @@ -279,6 +279,28 @@ in { systemd.services.test-service.unitConfig.RefuseManualStart = true; }; + unitWithTemplate.configuration = { + systemd.services."instantiated@".serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.coreutils}/bin/true"; + ExecReload = "${pkgs.coreutils}/bin/true"; + }; + systemd.services."instantiated@one" = { + wantedBy = [ "multi-user.target" ]; + overrideStrategy = "asDropin"; + }; + systemd.services."instantiated@two" = { + wantedBy = [ "multi-user.target" ]; + overrideStrategy = "asDropin"; + }; + }; + + unitWithTemplateModified.configuration = { + imports = [ unitWithTemplate.configuration ]; + systemd.services."instantiated@".serviceConfig.X-Test = "test"; + }; + restart-and-reload-by-activation-script.configuration = { systemd.services = rec { simple-service = { @@ -290,29 +312,50 @@ in { ExecReload = "${pkgs.coreutils}/bin/true"; }; }; + "templated-simple-service@" = simple-service; + "templated-simple-service@instance".overrideStrategy = "asDropin"; simple-restart-service = simple-service // { stopIfChanged = false; }; + "templated-simple-restart-service@" = simple-restart-service; + "templated-simple-restart-service@instance".overrideStrategy = "asDropin"; simple-reload-service = simple-service // { reloadIfChanged = true; }; + "templated-simple-reload-service@" = simple-reload-service; + "templated-simple-reload-service@instance".overrideStrategy = "asDropin"; no-restart-service = simple-service // { restartIfChanged = false; }; + "templated-no-restart-service@" = no-restart-service; + "templated-no-restart-service@instance".overrideStrategy = "asDropin"; reload-triggers = simple-service // { wantedBy = [ "multi-user.target" ]; }; + "templated-reload-triggers@" = simple-service; + "templated-reload-triggers@instance" = { + overrideStrategy = "asDropin"; + wantedBy = [ "multi-user.target" ]; + }; reload-triggers-and-restart-by-as = simple-service; + "templated-reload-triggers-and-restart-by-as@" = reload-triggers-and-restart-by-as; + "templated-reload-triggers-and-restart-by-as@instance".overrideStrategy = "asDropin"; reload-triggers-and-restart = simple-service // { stopIfChanged = false; # easier to check for this wantedBy = [ "multi-user.target" ]; }; + "templated-reload-triggers-and-restart@" = simple-service; + "templated-reload-triggers-and-restart@instance" = { + overrideStrategy = "asDropin"; + stopIfChanged = false; # easier to check for this + wantedBy = [ "multi-user.target" ]; + }; }; system.activationScripts.restart-and-reload-test = { @@ -332,12 +375,20 @@ in { simple-reload-service.service no-restart-service.service reload-triggers-and-restart-by-as.service + templated-simple-service@instance.service + templated-simple-restart-service@instance.service + templated-simple-reload-service@instance.service + templated-no-restart-service@instance.service + templated-reload-triggers-and-restart-by-as@instance.service EOF cat <<EOF >> "$g" reload-triggers.service reload-triggers-and-restart-by-as.service reload-triggers-and-restart.service + templated-reload-triggers@instance.service + templated-reload-triggers-and-restart-by-as@instance.service + templated-reload-triggers-and-restart@instance.service EOF ''; }; @@ -346,6 +397,10 @@ in { restart-and-reload-by-activation-script-modified.configuration = { imports = [ restart-and-reload-by-activation-script.configuration ]; systemd.services.reload-triggers-and-restart.serviceConfig.X-Modified = "test"; + systemd.services."templated-reload-triggers-and-restart@instance" = { + overrideStrategy = "asDropin"; + serviceConfig.X-Modified = "test"; + }; }; simple-socket.configuration = { @@ -507,6 +562,10 @@ in { set -o pipefail exec env -i "$@" | tee /dev/stderr ''; + + # Returns a comma separated representation of the given list in sorted + # order, that matches the output format of switch-to-configuration.pl + sortedUnits = xs: lib.concatStringsSep ", " (builtins.sort builtins.lessThan xs); in /* python */ '' def switch_to_specialisation(system, name, action="test", fail=False): if name == "": @@ -733,6 +792,16 @@ in { assert_contains(out, "\nstarting the following units: required-service.service\n") assert_lacks(out, "the following new units were started:") + # Ensure templated units are restarted when the base unit changes + switch_to_specialisation("${machine}", "unitWithTemplate") + out = switch_to_specialisation("${machine}", "unitWithTemplateModified") + assert_contains(out, "stopping the following units: instantiated@one.service, instantiated@two.service\n") + assert_lacks(out, "NOT restarting the following changed units:") + assert_lacks(out, "reloading the following units:") + assert_lacks(out, "\nrestarting the following units:") + assert_contains(out, "\nstarting the following units: instantiated@one.service, instantiated@two.service\n") + assert_lacks(out, "the following new units were started:") + with subtest("failing units"): # Let the simple service fail switch_to_specialisation("${machine}", "simpleServiceModified") @@ -896,15 +965,62 @@ in { assert_lacks(out, "NOT restarting the following changed units:") assert_lacks(out, "reloading the following units:") assert_lacks(out, "restarting the following units:") - assert_contains(out, "\nstarting the following units: no-restart-service.service, reload-triggers-and-restart-by-as.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n") - assert_contains(out, "the following new units were started: no-restart-service.service, reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, reload-triggers.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n") + assert_contains(out, "\nstarting the following units: ${sortedUnits [ + "no-restart-service.service" + "reload-triggers-and-restart-by-as.service" + "simple-reload-service.service" + "simple-restart-service.service" + "simple-service.service" + "templated-no-restart-service@instance.service" + "templated-reload-triggers-and-restart-by-as@instance.service" + "templated-simple-reload-service@instance.service" + "templated-simple-restart-service@instance.service" + "templated-simple-service@instance.service" + ]}\n") + assert_contains(out, "the following new units were started: ${sortedUnits [ + "no-restart-service.service" + "reload-triggers-and-restart-by-as.service" + "reload-triggers-and-restart.service" + "reload-triggers.service" + "simple-reload-service.service" + "simple-restart-service.service" + "simple-service.service" + "system-templated\\\\x2dno\\\\x2drestart\\\\x2dservice.slice" + "system-templated\\\\x2dreload\\\\x2dtriggers.slice" + "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart.slice" + "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart\\\\x2dby\\\\x2das.slice" + "system-templated\\\\x2dsimple\\\\x2dreload\\\\x2dservice.slice" + "system-templated\\\\x2dsimple\\\\x2drestart\\\\x2dservice.slice" + "system-templated\\\\x2dsimple\\\\x2dservice.slice" + "templated-no-restart-service@instance.service" + "templated-reload-triggers-and-restart-by-as@instance.service" + "templated-reload-triggers-and-restart@instance.service" + "templated-reload-triggers@instance.service" + "templated-simple-reload-service@instance.service" + "templated-simple-restart-service@instance.service" + "templated-simple-service@instance.service" + ]}\n") # Switch to the same system where the example services get restarted # and reloaded by the activation script out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") - assert_contains(out, "reloading the following units: reload-triggers-and-restart.service, reload-triggers.service, simple-reload-service.service\n") - assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, simple-restart-service.service, simple-service.service\n") + assert_contains(out, "reloading the following units: ${sortedUnits [ + "reload-triggers-and-restart.service" + "reload-triggers.service" + "simple-reload-service.service" + "templated-reload-triggers-and-restart@instance.service" + "templated-reload-triggers@instance.service" + "templated-simple-reload-service@instance.service" + ]}\n") + assert_contains(out, "restarting the following units: ${sortedUnits [ + "reload-triggers-and-restart-by-as.service" + "simple-restart-service.service" + "simple-service.service" + "templated-reload-triggers-and-restart-by-as@instance.service" + "templated-simple-restart-service@instance.service" + "templated-simple-service@instance.service" + ]}\n") assert_lacks(out, "\nstarting the following units:") assert_lacks(out, "the following new units were started:") # Switch to the same system and see if the service gets restarted when it's modified @@ -912,16 +1028,44 @@ in { out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") - assert_contains(out, "reloading the following units: reload-triggers.service, simple-reload-service.service\n") - assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n") + assert_contains(out, "reloading the following units: ${sortedUnits [ + "reload-triggers.service" + "simple-reload-service.service" + "templated-reload-triggers@instance.service" + "templated-simple-reload-service@instance.service" + ]}\n") + assert_contains(out, "restarting the following units: ${sortedUnits [ + "reload-triggers-and-restart-by-as.service" + "reload-triggers-and-restart.service" + "simple-restart-service.service" + "simple-service.service" + "templated-reload-triggers-and-restart-by-as@instance.service" + "templated-reload-triggers-and-restart@instance.service" + "templated-simple-restart-service@instance.service" + "templated-simple-service@instance.service" + ]}\n") assert_lacks(out, "\nstarting the following units:") assert_lacks(out, "the following new units were started:") # The same, but in dry mode out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate") assert_lacks(out, "would stop the following units:") assert_lacks(out, "would NOT stop the following changed units:") - assert_contains(out, "would reload the following units: reload-triggers.service, simple-reload-service.service\n") - assert_contains(out, "would restart the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n") + assert_contains(out, "would reload the following units: ${sortedUnits [ + "reload-triggers.service" + "simple-reload-service.service" + "templated-reload-triggers@instance.service" + "templated-simple-reload-service@instance.service" + ]}\n") + assert_contains(out, "would restart the following units: ${sortedUnits [ + "reload-triggers-and-restart-by-as.service" + "reload-triggers-and-restart.service" + "simple-restart-service.service" + "simple-service.service" + "templated-reload-triggers-and-restart-by-as@instance.service" + "templated-reload-triggers-and-restart@instance.service" + "templated-simple-restart-service@instance.service" + "templated-simple-service@instance.service" + ]}\n") assert_lacks(out, "\nwould start the following units:") with subtest("socket-activated services"): diff --git a/nixpkgs/nixos/tests/systemd-boot.nix b/nixpkgs/nixos/tests/systemd-boot.nix index 84a4da5aa6ec..c1f8637989e3 100644 --- a/nixpkgs/nixos/tests/systemd-boot.nix +++ b/nixpkgs/nixos/tests/systemd-boot.nix @@ -118,14 +118,11 @@ in nodes.machine = { pkgs, lib, ... }: { imports = [ common ]; boot.loader.systemd-boot.memtest86.enable = true; - nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ - "memtest86-efi" - ]; }; testScript = '' machine.succeed("test -e /boot/loader/entries/memtest86.conf") - machine.succeed("test -e /boot/efi/memtest86/BOOTX64.efi") + machine.succeed("test -e /boot/efi/memtest86/memtest.efi") ''; }; @@ -152,15 +149,12 @@ in imports = [ common ]; boot.loader.systemd-boot.memtest86.enable = true; boot.loader.systemd-boot.memtest86.entryFilename = "apple.conf"; - nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ - "memtest86-efi" - ]; }; testScript = '' machine.fail("test -e /boot/loader/entries/memtest86.conf") machine.succeed("test -e /boot/loader/entries/apple.conf") - machine.succeed("test -e /boot/efi/memtest86/BOOTX64.efi") + machine.succeed("test -e /boot/efi/memtest86/memtest.efi") ''; }; diff --git a/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix b/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix index 2fd3983e13ec..715477191bfb 100644 --- a/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix +++ b/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix @@ -13,7 +13,7 @@ let in { name = "mastodon-remote-postgresql"; - meta.maintainers = with pkgs.lib.maintainers; [ erictapen izorkin turion ]; + meta.maintainers = with pkgs.lib.maintainers; [ erictapen izorkin ]; nodes = { database = { diff --git a/nixpkgs/nixos/tests/web-servers/agate.nix b/nixpkgs/nixos/tests/web-servers/agate.nix index e8d789a9ca44..0de27b6f7d8d 100644 --- a/nixpkgs/nixos/tests/web-servers/agate.nix +++ b/nixpkgs/nixos/tests/web-servers/agate.nix @@ -20,7 +20,7 @@ geminiserver.wait_for_open_port(1965) with subtest("check is serving over gemini"): - response = geminiserver.succeed("${pkgs.gmni}/bin/gmni -j once -i -N gemini://localhost:1965") + response = geminiserver.succeed("${pkgs.gemget}/bin/gemget --header -o - gemini://localhost:1965") print(response) assert "Hello NixOS!" in response ''; diff --git a/nixpkgs/nixos/tests/wrappers.nix b/nixpkgs/nixos/tests/wrappers.nix index 08c1ad0b6b99..391e9b42b45b 100644 --- a/nixpkgs/nixos/tests/wrappers.nix +++ b/nixpkgs/nixos/tests/wrappers.nix @@ -55,6 +55,10 @@ in out = machine.succeed(cmd_as_regular(cmd)).strip() assert out == expected, "Expected {0} to output {1}, but got {2}".format(cmd, expected, out) + def test_as_regular_in_userns_mapped_as_root(cmd, expected): + out = machine.succeed(f"su -l regular -c '${pkgs.util-linux}/bin/unshare -rm {cmd}'").strip() + assert out == expected, "Expected {0} to output {1}, but got {2}".format(cmd, expected, out) + test_as_regular('${busybox pkgs}/bin/busybox id -u', '${toString userUid}') test_as_regular('${busybox pkgs}/bin/busybox id -ru', '${toString userUid}') test_as_regular('${busybox pkgs}/bin/busybox id -g', '${toString usersGid}') @@ -70,10 +74,27 @@ in test_as_regular('/run/wrappers/bin/sgid_root_busybox id -g', '0') test_as_regular('/run/wrappers/bin/sgid_root_busybox id -rg', '${toString usersGid}') + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -u', '0') + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -ru', '0') + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -g', '0') + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -rg', '0') + + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -u', '0') + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -ru', '0') + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -g', '0') + test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -rg', '0') + # We are only testing the permitted set, because it's easiest to look at with capsh. machine.fail(cmd_as_regular('${pkgs.libcap}/bin/capsh --has-p=CAP_CHOWN')) machine.fail(cmd_as_regular('${pkgs.libcap}/bin/capsh --has-p=CAP_SYS_ADMIN')) machine.succeed(cmd_as_regular('/run/wrappers/bin/capsh_with_chown --has-p=CAP_CHOWN')) machine.fail(cmd_as_regular('/run/wrappers/bin/capsh_with_chown --has-p=CAP_SYS_ADMIN')) + + # test a few "attacks" against which the wrapper protects itself + machine.succeed("cp /run/wrappers/bin/suid_root_busybox{,.real} /tmp/") + machine.fail(cmd_as_regular("/tmp/suid_root_busybox id -u")) + + machine.succeed("chmod u+s,a+w /run/wrappers/bin/suid_root_busybox") + machine.fail(cmd_as_regular("/run/wrappers/bin/suid_root_busybox id -u")) ''; }) |