at 23.11-beta 5.5 kB view raw
1{ system ? builtins.currentSystem, config ? { } 2, pkgs ? import ../.. { inherit system config; } }: 3 4with import ../lib/testing-python.nix { inherit system pkgs; }; 5with pkgs.lib; 6 7let 8 stunnelCommon = { 9 services.stunnel = { 10 enable = true; 11 user = "stunnel"; 12 }; 13 users.groups.stunnel = { }; 14 users.users.stunnel = { 15 isSystemUser = true; 16 group = "stunnel"; 17 }; 18 }; 19 makeCert = { config, pkgs, ... }: { 20 systemd.services.create-test-cert = { 21 wantedBy = [ "sysinit.target" ]; 22 before = [ "sysinit.target" ]; 23 unitConfig.DefaultDependencies = false; 24 script = '' 25 ${pkgs.openssl}/bin/openssl req -batch -x509 -newkey rsa -nodes -out /test-cert.pem -keyout /test-key.pem -subj /CN=${config.networking.hostName} 26 ( umask 077; cat /test-key.pem /test-cert.pem > /test-key-and-cert.pem ) 27 chown stunnel /test-key.pem /test-key-and-cert.pem 28 ''; 29 }; 30 }; 31 serverCommon = { pkgs, ... }: { 32 networking.firewall.allowedTCPPorts = [ 443 ]; 33 services.stunnel.servers.https = { 34 accept = "443"; 35 connect = 80; 36 cert = "/test-key-and-cert.pem"; 37 }; 38 systemd.services.simple-webserver = { 39 wantedBy = [ "multi-user.target" ]; 40 script = '' 41 cd /etc/webroot 42 ${pkgs.python3}/bin/python -m http.server 80 43 ''; 44 }; 45 }; 46 copyCert = src: dest: filename: '' 47 from shlex import quote 48 ${src}.wait_for_file("/test-key-and-cert.pem") 49 server_cert = ${src}.succeed("cat /test-cert.pem") 50 ${dest}.succeed("echo %s > ${filename}" % quote(server_cert)) 51 ''; 52 53in { 54 basicServer = makeTest { 55 name = "basicServer"; 56 57 nodes = { 58 client = { }; 59 server = { 60 imports = [ makeCert serverCommon stunnelCommon ]; 61 environment.etc."webroot/index.html".text = "well met"; 62 }; 63 }; 64 65 testScript = '' 66 start_all() 67 68 ${copyCert "server" "client" "/authorized-server-cert.crt"} 69 70 server.wait_for_unit("simple-webserver") 71 server.wait_for_unit("stunnel") 72 73 client.succeed("curl --fail --cacert /authorized-server-cert.crt https://server/ > out") 74 client.succeed('[[ "$(< out)" == "well met" ]]') 75 ''; 76 }; 77 78 serverAndClient = makeTest { 79 name = "serverAndClient"; 80 81 nodes = { 82 client = { 83 imports = [ stunnelCommon ]; 84 services.stunnel.clients = { 85 httpsClient = { 86 accept = "80"; 87 connect = "server:443"; 88 CAFile = "/authorized-server-cert.crt"; 89 }; 90 httpsClientWithHostVerify = { 91 accept = "81"; 92 connect = "server:443"; 93 CAFile = "/authorized-server-cert.crt"; 94 verifyHostname = "server"; 95 }; 96 httpsClientWithHostVerifyFail = { 97 accept = "82"; 98 connect = "server:443"; 99 CAFile = "/authorized-server-cert.crt"; 100 verifyHostname = "wronghostname"; 101 }; 102 }; 103 }; 104 server = { 105 imports = [ makeCert serverCommon stunnelCommon ]; 106 environment.etc."webroot/index.html".text = "hello there"; 107 }; 108 }; 109 110 testScript = '' 111 start_all() 112 113 ${copyCert "server" "client" "/authorized-server-cert.crt"} 114 115 server.wait_for_unit("simple-webserver") 116 server.wait_for_unit("stunnel") 117 118 # In case stunnel came up before we got the server's cert copied over 119 client.succeed("systemctl reload-or-restart stunnel") 120 121 client.succeed("curl --fail http://localhost/ > out") 122 client.succeed('[[ "$(< out)" == "hello there" ]]') 123 124 client.succeed("curl --fail http://localhost:81/ > out") 125 client.succeed('[[ "$(< out)" == "hello there" ]]') 126 127 client.fail("curl --fail http://localhost:82/ > out") 128 client.succeed('[[ "$(< out)" == "" ]]') 129 ''; 130 }; 131 132 mutualAuth = makeTest { 133 name = "mutualAuth"; 134 135 nodes = rec { 136 client = { 137 imports = [ makeCert stunnelCommon ]; 138 services.stunnel.clients.authenticated-https = { 139 accept = "80"; 140 connect = "server:443"; 141 verifyPeer = true; 142 CAFile = "/authorized-server-cert.crt"; 143 cert = "/test-cert.pem"; 144 key = "/test-key.pem"; 145 }; 146 }; 147 wrongclient = client; 148 server = { 149 imports = [ makeCert serverCommon stunnelCommon ]; 150 services.stunnel.servers.https = { 151 CAFile = "/authorized-client-certs.crt"; 152 verifyPeer = true; 153 }; 154 environment.etc."webroot/index.html".text = "secret handshake"; 155 }; 156 }; 157 158 testScript = '' 159 start_all() 160 161 ${copyCert "server" "client" "/authorized-server-cert.crt"} 162 ${copyCert "client" "server" "/authorized-client-certs.crt"} 163 ${copyCert "server" "wrongclient" "/authorized-server-cert.crt"} 164 165 # In case stunnel came up before we got the cross-certs in place 166 client.succeed("systemctl reload-or-restart stunnel") 167 server.succeed("systemctl reload-or-restart stunnel") 168 wrongclient.succeed("systemctl reload-or-restart stunnel") 169 170 server.wait_for_unit("simple-webserver") 171 client.fail("curl --fail --insecure https://server/ > out") 172 client.succeed('[[ "$(< out)" == "" ]]') 173 client.succeed("curl --fail http://localhost/ > out") 174 client.succeed('[[ "$(< out)" == "secret handshake" ]]') 175 wrongclient.fail("curl --fail http://localhost/ > out") 176 wrongclient.succeed('[[ "$(< out)" == "" ]]') 177 ''; 178 }; 179}