1# Some tests to ensure sudo is working properly.
2
3let
4 password = "helloworld";
5in
6{ lib, pkgs, ... }:
7{
8 name = "sudo";
9 meta.maintainers = pkgs.sudo.meta.maintainers;
10
11 nodes.machine =
12 { lib, ... }:
13 {
14 users.groups = {
15 foobar = { };
16 barfoo = { };
17 baz = {
18 gid = 1337;
19 };
20 };
21 users.users = {
22 test0 = {
23 isNormalUser = true;
24 extraGroups = [ "wheel" ];
25 };
26 test1 = {
27 isNormalUser = true;
28 password = password;
29 };
30 test2 = {
31 isNormalUser = true;
32 extraGroups = [ "foobar" ];
33 password = password;
34 };
35 test3 = {
36 isNormalUser = true;
37 extraGroups = [ "barfoo" ];
38 };
39 test4 = {
40 isNormalUser = true;
41 extraGroups = [ "baz" ];
42 };
43 test5 = {
44 isNormalUser = true;
45 };
46 };
47
48 security.sudo = {
49 # Explicitly _not_ defining 'enable = true;' here, to check that sudo is enabled by default
50
51 wheelNeedsPassword = false;
52
53 extraConfig = ''
54 Defaults lecture="never"
55 '';
56
57 extraRules = [
58 # SUDOERS SYNTAX CHECK (Test whether the module produces a valid output;
59 # errors being detected by the visudo checks.
60
61 # These should not create any entries
62 {
63 users = [ "notest1" ];
64 commands = [ ];
65 }
66 {
67 commands = [
68 {
69 command = "ALL";
70 options = [ ];
71 }
72 ];
73 }
74
75 # Test defining commands with the options syntax, though not setting any options
76 {
77 users = [ "notest2" ];
78 commands = [
79 {
80 command = "ALL";
81 options = [ ];
82 }
83 ];
84 }
85
86 # CONFIGURATION FOR TEST CASES
87 {
88 users = [ "test1" ];
89 groups = [ "foobar" ];
90 commands = [ "ALL" ];
91 }
92 {
93 groups = [
94 "barfoo"
95 1337
96 ];
97 commands = [
98 {
99 command = "ALL";
100 options = [
101 "NOPASSWD"
102 "NOSETENV"
103 ];
104 }
105 ];
106 }
107 {
108 users = [ "test5" ];
109 commands = [
110 {
111 command = "ALL";
112 options = [
113 "NOPASSWD"
114 "SETENV"
115 ];
116 }
117 ];
118 runAs = "test1:barfoo";
119 }
120 ];
121 };
122 };
123
124 nodes.strict =
125 { ... }:
126 {
127 users.users = {
128 admin = {
129 isNormalUser = true;
130 extraGroups = [ "wheel" ];
131 };
132 noadmin = {
133 isNormalUser = true;
134 };
135 };
136
137 security.sudo = {
138 enable = true;
139 wheelNeedsPassword = false;
140 execWheelOnly = true;
141 };
142 };
143
144 testScript = ''
145 with subtest("users in wheel group should have passwordless sudo"):
146 machine.succeed('su - test0 -c "sudo -u root true"')
147
148 with subtest("test1 user should have sudo with password"):
149 machine.succeed('su - test1 -c "echo ${password} | sudo -S -u root true"')
150
151 with subtest("test1 user should not be able to use sudo without password"):
152 machine.fail('su - test1 -c "sudo -n -u root true"')
153
154 with subtest("users in group 'foobar' should be able to use sudo with password"):
155 machine.succeed('su - test2 -c "echo ${password} | sudo -S -u root true"')
156
157 with subtest("users in group 'barfoo' should be able to use sudo without password"):
158 machine.succeed("sudo -u test3 sudo -n -u root true")
159
160 with subtest("users in group 'baz' (GID 1337)"):
161 machine.succeed("sudo -u test4 sudo -n -u root echo true")
162
163 with subtest("test5 user should be able to run commands under test1"):
164 machine.succeed("sudo -u test5 sudo -n -u test1 true")
165
166 with subtest("test5 user should not be able to run commands under root"):
167 machine.fail("sudo -u test5 sudo -n -u root true")
168
169 with subtest("test5 user should be able to keep their environment"):
170 machine.succeed("sudo -u test5 sudo -n -E -u test1 true")
171
172 with subtest("users in group 'barfoo' should not be able to keep their environment"):
173 machine.fail("sudo -u test3 sudo -n -E -u root true")
174
175 with subtest("users in wheel should be able to run sudo despite execWheelOnly"):
176 strict.succeed('su - admin -c "sudo -u root true"')
177
178 with subtest("non-wheel users should be unable to run sudo thanks to execWheelOnly"):
179 strict.fail('su - noadmin -c "sudo --help"')
180 '';
181}