1let
2 password1 = "foobar";
3 password2 = "helloworld";
4 password3 = "bazqux";
5 password4 = "asdf123";
6in import ./make-test-python.nix ({ pkgs, ... }: {
7 name = "shadow";
8 meta = with pkgs.lib.maintainers; { maintainers = [ nequissimus ]; };
9
10 nodes.shadow = { pkgs, ... }: {
11 environment.systemPackages = [ pkgs.shadow ];
12
13 users = {
14 mutableUsers = true;
15 users.emma = {
16 isNormalUser = true;
17 password = password1;
18 shell = pkgs.bash;
19 };
20 users.layla = {
21 isNormalUser = true;
22 password = password2;
23 shell = pkgs.shadow;
24 };
25 users.ash = {
26 isNormalUser = true;
27 password = password4;
28 shell = pkgs.bash;
29 };
30 };
31 };
32
33 testScript = ''
34 shadow.wait_for_unit("multi-user.target")
35 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
36
37 with subtest("Normal login"):
38 shadow.send_key("alt-f2")
39 shadow.wait_until_succeeds("[ $(fgconsole) = 2 ]")
40 shadow.wait_for_unit("getty@tty2.service")
41 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty2'")
42 shadow.wait_until_tty_matches(2, "login: ")
43 shadow.send_chars("emma\n")
44 shadow.wait_until_tty_matches(2, "login: emma")
45 shadow.wait_until_succeeds("pgrep login")
46 shadow.sleep(2)
47 shadow.send_chars("${password1}\n")
48 shadow.send_chars("whoami > /tmp/1\n")
49 shadow.wait_for_file("/tmp/1")
50 assert "emma" in shadow.succeed("cat /tmp/1")
51
52 with subtest("Switch user"):
53 shadow.send_chars("su - ash\n")
54 shadow.sleep(2)
55 shadow.send_chars("${password4}\n")
56 shadow.sleep(2)
57 shadow.send_chars("whoami > /tmp/3\n")
58 shadow.wait_for_file("/tmp/3")
59 assert "ash" in shadow.succeed("cat /tmp/3")
60
61 with subtest("Change password"):
62 shadow.send_key("alt-f3")
63 shadow.wait_until_succeeds("[ $(fgconsole) = 3 ]")
64 shadow.wait_for_unit("getty@tty3.service")
65 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty3'")
66 shadow.wait_until_tty_matches(3, "login: ")
67 shadow.send_chars("emma\n")
68 shadow.wait_until_tty_matches(3, "login: emma")
69 shadow.wait_until_succeeds("pgrep login")
70 shadow.sleep(2)
71 shadow.send_chars("${password1}\n")
72 shadow.send_chars("passwd\n")
73 shadow.sleep(2)
74 shadow.send_chars("${password1}\n")
75 shadow.sleep(2)
76 shadow.send_chars("${password3}\n")
77 shadow.sleep(2)
78 shadow.send_chars("${password3}\n")
79 shadow.sleep(2)
80 shadow.send_key("alt-f4")
81 shadow.wait_until_succeeds("[ $(fgconsole) = 4 ]")
82 shadow.wait_for_unit("getty@tty4.service")
83 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty4'")
84 shadow.wait_until_tty_matches(4, "login: ")
85 shadow.send_chars("emma\n")
86 shadow.wait_until_tty_matches(4, "login: emma")
87 shadow.wait_until_succeeds("pgrep login")
88 shadow.sleep(2)
89 shadow.send_chars("${password1}\n")
90 shadow.wait_until_tty_matches(4, "Login incorrect")
91 shadow.wait_until_tty_matches(4, "login:")
92 shadow.send_chars("emma\n")
93 shadow.wait_until_tty_matches(4, "login: emma")
94 shadow.wait_until_succeeds("pgrep login")
95 shadow.sleep(2)
96 shadow.send_chars("${password3}\n")
97 shadow.send_chars("whoami > /tmp/2\n")
98 shadow.wait_for_file("/tmp/2")
99 assert "emma" in shadow.succeed("cat /tmp/2")
100
101 with subtest("Groups"):
102 assert "foobar" not in shadow.succeed("groups emma")
103 shadow.succeed("groupadd foobar")
104 shadow.succeed("usermod -a -G foobar emma")
105 assert "foobar" in shadow.succeed("groups emma")
106
107 with subtest("nologin shell"):
108 shadow.send_key("alt-f5")
109 shadow.wait_until_succeeds("[ $(fgconsole) = 5 ]")
110 shadow.wait_for_unit("getty@tty5.service")
111 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty5'")
112 shadow.wait_until_tty_matches(5, "login: ")
113 shadow.send_chars("layla\n")
114 shadow.wait_until_tty_matches(5, "login: layla")
115 shadow.wait_until_succeeds("pgrep login")
116 shadow.send_chars("${password2}\n")
117 shadow.wait_until_tty_matches(5, "login:")
118 '';
119})