1import ./make-test-python.nix (
2 { pkgs, ... }:
3 let
4 sshKeys = import (pkgs.path + "/nixos/tests/ssh-keys.nix") pkgs;
5 sshUsername = "any-user";
6 serverName = "server";
7 clientName = "client";
8 sshAuditPort = 2222;
9 in
10 {
11 name = "ssh";
12
13 nodes = {
14 "${serverName}" = {
15 networking.firewall.allowedTCPPorts = [
16 sshAuditPort
17 ];
18 services.openssh.enable = true;
19 users.users."${sshUsername}" = {
20 isNormalUser = true;
21 openssh.authorizedKeys.keys = [
22 sshKeys.snakeOilPublicKey
23 ];
24 };
25 };
26 "${clientName}" = {
27 programs.ssh = {
28 ciphers = [
29 "aes128-ctr"
30 "aes128-gcm@openssh.com"
31 "aes192-ctr"
32 "aes256-ctr"
33 "aes256-gcm@openssh.com"
34 "chacha20-poly1305@openssh.com"
35 ];
36 extraConfig = ''
37 IdentitiesOnly yes
38 '';
39 hostKeyAlgorithms = [
40 "rsa-sha2-256"
41 "rsa-sha2-256-cert-v01@openssh.com"
42 "rsa-sha2-512"
43 "rsa-sha2-512-cert-v01@openssh.com"
44 "sk-ssh-ed25519-cert-v01@openssh.com"
45 "sk-ssh-ed25519@openssh.com"
46 "ssh-ed25519"
47 "ssh-ed25519-cert-v01@openssh.com"
48 ];
49 kexAlgorithms = [
50 "curve25519-sha256"
51 "curve25519-sha256@libssh.org"
52 "diffie-hellman-group-exchange-sha256"
53 "diffie-hellman-group16-sha512"
54 "diffie-hellman-group18-sha512"
55 "sntrup761x25519-sha512@openssh.com"
56 ];
57 macs = [
58 "hmac-sha2-256-etm@openssh.com"
59 "hmac-sha2-512-etm@openssh.com"
60 "umac-128-etm@openssh.com"
61 ];
62 };
63 };
64 };
65
66 testScript = ''
67 start_all()
68
69 ${serverName}.wait_for_open_port(22)
70
71 # Should pass SSH server audit
72 ${serverName}.succeed("${pkgs.ssh-audit}/bin/ssh-audit 127.0.0.1")
73
74 # Wait for client to be able to connect to the server
75 ${clientName}.systemctl("start network-online.target")
76 ${clientName}.wait_for_unit("network-online.target")
77
78 # Set up trusted private key
79 ${clientName}.succeed("cat ${sshKeys.snakeOilPrivateKey} > privkey.snakeoil")
80 ${clientName}.succeed("chmod 600 privkey.snakeoil")
81
82 # Fail fast and disable interactivity
83 ssh_options = "-o BatchMode=yes -o ConnectTimeout=1 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
84
85 # Should deny root user
86 ${clientName}.fail(f"ssh {ssh_options} root@${serverName} true")
87
88 # Should deny non-root user password login
89 ${clientName}.fail(f"ssh {ssh_options} -o PasswordAuthentication=yes ${sshUsername}@${serverName} true")
90
91 # Should allow non-root user certificate login
92 ${clientName}.succeed(f"ssh {ssh_options} -i privkey.snakeoil ${sshUsername}@${serverName} true")
93
94 # Should pass SSH client audit
95 service_name = "ssh-audit.service"
96 ${serverName}.succeed(f"systemd-run --unit={service_name} ${pkgs.ssh-audit}/bin/ssh-audit --client-audit --port=${toString sshAuditPort}")
97 ${clientName}.sleep(5) # We can't use wait_for_open_port because ssh-audit exits as soon as anything talks to it
98 ${clientName}.execute(
99 f"ssh {ssh_options} -i privkey.snakeoil -p ${toString sshAuditPort} ${sshUsername}@${serverName} true",
100 check_return=False,
101 timeout=10
102 )
103 ${serverName}.succeed(f"exit $(systemctl show --property=ExecMainStatus --value {service_name})")
104 '';
105 }
106)