vuls: init at 0.27.0
[NixPkgs.git] / nixos / tests / openssh.nix
blobd420c482ca7f28c6267db50d2a1f5422b83f912d
1 import ./make-test-python.nix ({ pkgs, ... }:
3 let inherit (import ./ssh-keys.nix pkgs)
4       snakeOilPrivateKey snakeOilPublicKey snakeOilEd25519PrivateKey snakeOilEd25519PublicKey;
5 in {
6   name = "openssh";
7   meta = with pkgs.lib.maintainers; {
8     maintainers = [ aszlig ];
9   };
11   nodes = {
13     server =
14       { ... }:
16       {
17         services.openssh.enable = true;
18         security.pam.services.sshd.limits =
19           [ { domain = "*"; item = "memlock"; type = "-"; value = 1024; } ];
20         users.users.root.openssh.authorizedKeys.keys = [
21           snakeOilPublicKey
22         ];
23       };
25     server-allowed-users =
26       { ... }:
28       {
29         services.openssh = { enable = true; settings.AllowUsers = [ "alice" "bob" ]; };
30         users.groups = { alice = { }; bob = { }; carol = { }; };
31         users.users = {
32           alice = { isNormalUser = true; group = "alice"; openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; };
33           bob = { isNormalUser = true; group = "bob"; openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; };
34           carol = { isNormalUser = true; group = "carol"; openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; };
35         };
36       };
38     server-lazy =
39       { ... }:
41       {
42         services.openssh = { enable = true; startWhenNeeded = true; };
43         security.pam.services.sshd.limits =
44           [ { domain = "*"; item = "memlock"; type = "-"; value = 1024; } ];
45         users.users.root.openssh.authorizedKeys.keys = [
46           snakeOilPublicKey
47         ];
48       };
50     server-lazy-socket = {
51       virtualisation.vlans = [ 1 2 ];
52       services.openssh = {
53         enable = true;
54         startWhenNeeded = true;
55         ports = [ 2222 ];
56         listenAddresses = [ { addr = "0.0.0.0"; } ];
57       };
58       users.users.root.openssh.authorizedKeys.keys = [
59         snakeOilPublicKey
60       ];
61     };
63     server-localhost-only =
64       { ... }:
66       {
67         services.openssh = {
68           enable = true; listenAddresses = [ { addr = "127.0.0.1"; port = 22; } ];
69         };
70       };
72     server-localhost-only-lazy =
73       { ... }:
75       {
76         services.openssh = {
77           enable = true; startWhenNeeded = true; listenAddresses = [ { addr = "127.0.0.1"; port = 22; } ];
78         };
79       };
81     server-match-rule =
82       { ... }:
84       {
85         services.openssh = {
86           enable = true; listenAddresses = [ { addr = "127.0.0.1"; port = 22; } { addr = "[::]"; port = 22; } ];
87           extraConfig = ''
88             # Combined test for two (predictable) Match criterias
89             Match LocalAddress 127.0.0.1 LocalPort 22
90               PermitRootLogin yes
92             # Separate tests for Match criterias
93             Match User root
94               PermitRootLogin yes
95             Match Group root
96               PermitRootLogin yes
97             Match Host nohost.example
98               PermitRootLogin yes
99             Match LocalAddress 127.0.0.1
100               PermitRootLogin yes
101             Match LocalPort 22
102               PermitRootLogin yes
103             Match RDomain nohost.example
104               PermitRootLogin yes
105             Match Address 127.0.0.1
106               PermitRootLogin yes
107           '';
108         };
109       };
111     server-no-openssl =
112       { ... }:
113       {
114         services.openssh = {
115           enable = true;
116           package = pkgs.opensshPackages.openssh.override {
117             linkOpenssl = false;
118           };
119           hostKeys = [
120             { type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
121           ];
122           settings = {
123             # Since this test is against an OpenSSH-without-OpenSSL,
124             # we have to override NixOS's defaults ciphers (which require OpenSSL)
125             # and instead set these to null, which will mean OpenSSH uses its defaults.
126             # Expectedly, OpenSSH's defaults don't require OpenSSL when it's compiled
127             # without OpenSSL.
128             Ciphers = null;
129             KexAlgorithms = null;
130             Macs = null;
131           };
132         };
133         users.users.root.openssh.authorizedKeys.keys = [
134           snakeOilEd25519PublicKey
135         ];
136       };
138     server-no-pam =
139       { pkgs, ... }:
140       {
141         services.openssh = {
142           enable = true;
143           package = pkgs.opensshPackages.openssh.override {
144             withPAM = false;
145           };
146           settings = {
147             UsePAM = false;
148           };
149         };
150         users.users.root.openssh.authorizedKeys.keys = [
151           snakeOilPublicKey
152         ];
153       };
155     client =
156       { ... }: {
157         virtualisation.vlans = [ 1 2 ];
158       };
160   };
162   testScript = ''
163     start_all()
165     server.wait_for_unit("sshd", timeout=30)
166     server_allowed_users.wait_for_unit("sshd", timeout=30)
167     server_localhost_only.wait_for_unit("sshd", timeout=30)
168     server_match_rule.wait_for_unit("sshd", timeout=30)
169     server_no_openssl.wait_for_unit("sshd", timeout=30)
170     server_no_pam.wait_for_unit("sshd", timeout=30)
172     server_lazy.wait_for_unit("sshd.socket", timeout=30)
173     server_localhost_only_lazy.wait_for_unit("sshd.socket", timeout=30)
174     server_lazy_socket.wait_for_unit("sshd.socket", timeout=30)
176     with subtest("manual-authkey"):
177         client.succeed("mkdir -m 700 /root/.ssh")
178         client.succeed(
179             '${pkgs.openssh}/bin/ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N ""'
180         )
181         public_key = client.succeed(
182             "${pkgs.openssh}/bin/ssh-keygen -y -f /root/.ssh/id_ed25519"
183         )
184         public_key = public_key.strip()
185         client.succeed("chmod 600 /root/.ssh/id_ed25519")
187         server.succeed("mkdir -m 700 /root/.ssh")
188         server.succeed("echo '{}' > /root/.ssh/authorized_keys".format(public_key))
189         server_lazy.succeed("mkdir -m 700 /root/.ssh")
190         server_lazy.succeed("echo '{}' > /root/.ssh/authorized_keys".format(public_key))
192         client.wait_for_unit("network.target")
193         client.succeed(
194             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server 'echo hello world' >&2",
195             timeout=30
196         )
197         client.succeed(
198             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server 'ulimit -l' | grep 1024",
199             timeout=30
200         )
202         client.succeed(
203             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server-lazy 'echo hello world' >&2",
204             timeout=30
205         )
206         client.succeed(
207             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server-lazy 'ulimit -l' | grep 1024",
208             timeout=30
209         )
211     with subtest("socket activation on a non-standard port"):
212         client.succeed(
213             "cat ${snakeOilPrivateKey} > privkey.snakeoil"
214         )
215         client.succeed("chmod 600 privkey.snakeoil")
216         # The final segment in this IP is allocated according to the alphabetical order of machines in this test.
217         client.succeed(
218             "ssh -p 2222 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil root@192.168.2.5 true",
219             timeout=30
220         )
222     with subtest("configured-authkey"):
223         client.succeed(
224             "cat ${snakeOilPrivateKey} > privkey.snakeoil"
225         )
226         client.succeed("chmod 600 privkey.snakeoil")
227         client.succeed(
228             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil server true",
229             timeout=30
230         )
231         client.succeed(
232             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil server-lazy true",
233             timeout=30
234         )
236     with subtest("localhost-only"):
237         server_localhost_only.succeed("ss -nlt | grep '127.0.0.1:22'")
238         server_localhost_only_lazy.succeed("ss -nlt | grep '127.0.0.1:22'")
240     with subtest("match-rules"):
241         server_match_rule.succeed("ss -nlt | grep '127.0.0.1:22'")
243     with subtest("allowed-users"):
244         client.succeed(
245             "cat ${snakeOilPrivateKey} > privkey.snakeoil"
246         )
247         client.succeed("chmod 600 privkey.snakeoil")
248         client.succeed(
249             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil alice@server-allowed-users true",
250             timeout=30
251         )
252         client.succeed(
253             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil bob@server-allowed-users true",
254             timeout=30
255         )
256         client.fail(
257             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil carol@server-allowed-users true",
258             timeout=30
259         )
261     with subtest("no-openssl"):
262         client.succeed(
263             "cat ${snakeOilEd25519PrivateKey} > privkey.snakeoil"
264         )
265         client.succeed("chmod 600 privkey.snakeoil")
266         client.succeed(
267             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil server-no-openssl true",
268             timeout=30
269         )
271     with subtest("no-pam"):
272         client.succeed(
273             "cat ${snakeOilPrivateKey} > privkey.snakeoil"
274         )
275         client.succeed("chmod 600 privkey.snakeoil")
276         client.succeed(
277             "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil server-no-pam true",
278             timeout=30
279         )
280   '';