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