1{ lib, ... }:
2
3let
4 # All passwords are "test"
5 rootHashedPasswordFile = "$y$j9T$6ueoTO5y7vvFsGvpQJEEa.$vubxgBiMnkTCtRtPD3hNiZHa7Nm1WsJeE9QomYqSRXB";
6 updatedRootHashedPassword = "$y$j9T$pBCO9N1FRF1rSl6V15n9n/$1JmRLEYPO7TRCx43cvLO19u59WA/oqTEhmSR4wrhzr.";
7
8 normaloPassword = "test";
9 updatedNormaloHashedPassword = "$y$j9T$IEWqhKtWg.r.8fVkSEF56.$iKNxdMC6hOAQRp6eBtYvBk4c7BGpONXeZMqc8I/LM46";
10
11 sysuserInitialHashedPassword = "$y$j9T$Kb6jGrk41hudTZpNjazf11$iw7fZXrewC6JxRaGPz7/gPXDZ.Z1VWsupvy81Hi1XiD";
12 updatedSysuserInitialHashedPassword = "$y$j9T$kUBVhgOdSjymSfwfRVja70$eqCwWzVsz0fI0Uc6JsdD2CYMCpfJcErqnIqva2JCi1D";
13
14 newNormaloHashedPassword = "$y$j9T$UFBMWbGjjVola0YE9YCcV/$jRSi5S6lzkcifbuqjMcyXLTwgOGm9BTQk/G/jYaxroC";
15in
16
17{
18
19 name = "userborn";
20
21 meta.maintainers = with lib.maintainers; [ nikstur ];
22
23 nodes.machine = {
24 services.userborn.enable = true;
25
26 # Read this password file at runtime from outside the Nix store.
27 environment.etc."rootpw.secret".text = rootHashedPasswordFile;
28
29 users = {
30 users = {
31 root = {
32 # Override the empty root password set by the test instrumentation.
33 hashedPasswordFile = lib.mkForce "/etc/rootpw.secret";
34 };
35 normalo = {
36 isNormalUser = true;
37 password = normaloPassword;
38 };
39 sysuser = {
40 isSystemUser = true;
41 group = "sysusers";
42 initialHashedPassword = sysuserInitialHashedPassword;
43 };
44 };
45 groups = {
46 sysusers = { };
47 };
48 };
49
50 specialisation.new-generation.configuration = {
51 users = {
52 users = {
53 root = {
54 # Forcing this to null simulates removing the config value in a new
55 # generation.
56 hashedPasswordFile = lib.mkOverride 9 null;
57 hashedPassword = updatedRootHashedPassword;
58 };
59 normalo = {
60 hashedPassword = updatedNormaloHashedPassword;
61 };
62 sysuser = {
63 initialHashedPassword = lib.mkForce updatedSysuserInitialHashedPassword;
64 };
65 new-normalo = {
66 isNormalUser = true;
67 hashedPassword = newNormaloHashedPassword;
68 };
69 normalo-disabled = {
70 enable = false;
71 isNormalUser = true;
72 };
73 };
74 groups = {
75 new-group = { };
76 };
77 };
78 };
79 };
80
81 testScript = ''
82 machine.wait_for_unit("userborn.service")
83
84 with subtest("Correct mode on the password files"):
85 assert machine.succeed("stat -c '%a' /etc/passwd") == "644\n"
86 assert machine.succeed("stat -c '%a' /etc/group") == "644\n"
87 assert machine.succeed("stat -c '%a' /etc/shadow") == "0\n"
88
89 with subtest("root user has correct password"):
90 print(machine.succeed("getent passwd root"))
91 assert "${rootHashedPasswordFile}" in machine.succeed("getent shadow root"), "root user password is not correct"
92
93 with subtest("normalo user is created"):
94 print(machine.succeed("getent passwd normalo"))
95 assert 1000 <= int(machine.succeed("id --user normalo")), "normalo user doesn't have a normal UID"
96 assert machine.succeed("stat -c '%U' /home/normalo") == "normalo\n"
97
98 with subtest("system user is created with correct password"):
99 print(machine.succeed("getent passwd sysuser"))
100 assert 1000 > int(machine.succeed("id --user sysuser")), "sysuser user doesn't have a system UID"
101 assert "${sysuserInitialHashedPassword}" in machine.succeed("getent shadow sysuser"), "system user password is not correct"
102
103 with subtest("normalo-disabled is NOT created"):
104 machine.fail("id normalo-disabled")
105 # Check if user's home has been created
106 machine.fail("[ -d '/home/normalo-disabled' ]")
107
108 with subtest("sysusers group is created"):
109 print(machine.succeed("getent group sysusers"))
110
111 with subtest("Check files"):
112 print(machine.succeed("grpck -r"))
113 print(machine.succeed("pwck -r"))
114
115
116 machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
117
118
119 with subtest("root user password is updated"):
120 print(machine.succeed("getent passwd root"))
121 assert "${updatedRootHashedPassword}" in machine.succeed("getent shadow root"), "root user password is not updated"
122
123 with subtest("normalo user password is updated"):
124 print(machine.succeed("getent passwd normalo"))
125 assert "${updatedNormaloHashedPassword}" in machine.succeed("getent shadow normalo"), "normalo user password is not updated"
126
127 with subtest("system user password is NOT updated"):
128 print(machine.succeed("getent passwd sysuser"))
129 assert "${sysuserInitialHashedPassword}" in machine.succeed("getent shadow sysuser"), "sysuser user password is not updated"
130
131 with subtest("new-normalo user is created after switching to new generation"):
132 print(machine.succeed("getent passwd new-normalo"))
133 assert 1000 <= int(machine.succeed("id --user new-normalo")), "new-normalo user doesn't have a normal UID"
134 assert machine.succeed("stat -c '%U' /home/new-normalo") == "new-normalo\n"
135 assert "${newNormaloHashedPassword}" in machine.succeed("getent shadow new-normalo"), "new-normalo user password is not correct"
136
137 with subtest("new-group group is created after switching to new generation"):
138 print(machine.succeed("getent group new-group"))
139
140 with subtest("Check files"):
141 print(machine.succeed("grpck -r"))
142 print(machine.succeed("pwck -r"))
143 '';
144}