1import ./make-test-python.nix ({ pkgs, lib, ...}:
2{
3 name = "wpa_supplicant";
4 meta = with lib.maintainers; {
5 maintainers = [ rnhmjoj ];
6 };
7
8 machine = { ... }: {
9 imports = [ ../modules/profiles/minimal.nix ];
10
11 # add a virtual wlan interface
12 boot.kernelModules = [ "mac80211_hwsim" ];
13
14 # wireless access point
15 services.hostapd = {
16 enable = true;
17 wpa = true;
18 interface = "wlan0";
19 ssid = "nixos-test";
20 wpaPassphrase = "reproducibility";
21 };
22
23 # wireless client
24 networking.wireless = {
25 # the override is needed because the wifi is
26 # disabled with mkVMOverride in qemu-vm.nix.
27 enable = lib.mkOverride 0 true;
28 userControlled.enable = true;
29 interfaces = [ "wlan1" ];
30
31 networks = {
32 # test network
33 nixos-test.psk = "@PSK_NIXOS_TEST@";
34
35 # secrets substitution test cases
36 test1.psk = "@PSK_VALID@"; # should be replaced
37 test2.psk = "@PSK_SPECIAL@"; # should be replaced
38 test3.psk = "@PSK_MISSING@"; # should not be replaced
39 test4.psk = "P@ssowrdWithSome@tSymbol"; # should not be replaced
40 };
41
42 # secrets
43 environmentFile = pkgs.writeText "wpa-secrets" ''
44 PSK_NIXOS_TEST="reproducibility"
45 PSK_VALID="S0m3BadP4ssw0rd";
46 # taken from https://github.com/minimaxir/big-list-of-naughty-strings
47 PSK_SPECIAL=",./;'[]\-= <>?:\"{}|_+ !@#$%^\&*()`~";
48 '';
49 };
50
51 };
52
53 testScript =
54 ''
55 config_file = "/run/wpa_supplicant/wpa_supplicant.conf"
56
57 with subtest("Configuration file is inaccessible to other users"):
58 machine.wait_for_file(config_file)
59 machine.fail(f"sudo -u nobody ls {config_file}")
60
61 with subtest("Secrets variables have been substituted"):
62 machine.fail(f"grep -q @PSK_VALID@ {config_file}")
63 machine.fail(f"grep -q @PSK_SPECIAL@ {config_file}")
64 machine.succeed(f"grep -q @PSK_MISSING@ {config_file}")
65 machine.succeed(f"grep -q P@ssowrdWithSome@tSymbol {config_file}")
66
67 # save file for manual inspection
68 machine.copy_from_vm(config_file)
69
70 with subtest("Daemon is running and accepting connections"):
71 machine.wait_for_unit("wpa_supplicant-wlan1.service")
72 status = machine.succeed("wpa_cli -i wlan1 status")
73 assert "Failed to connect" not in status, \
74 "Failed to connect to the daemon"
75
76 with subtest("Daemon can connect to the access point"):
77 machine.wait_until_succeeds(
78 "wpa_cli -i wlan1 status | grep -q wpa_state=COMPLETED"
79 )
80 '';
81})