1import ./make-test-python.nix ({ pkgs, ... }: {
2 name = "ghostunnel";
3 nodes = {
4 backend = { pkgs, ... }: {
5 services.nginx.enable = true;
6 services.nginx.virtualHosts."backend".root = pkgs.runCommand "webroot" {} ''
7 mkdir $out
8 echo hi >$out/hi.txt
9 '';
10 networking.firewall.allowedTCPPorts = [ 80 ];
11 };
12 service = { ... }: {
13 services.ghostunnel.enable = true;
14 services.ghostunnel.servers."plain-old" = {
15 listen = "0.0.0.0:443";
16 cert = "/root/service-cert.pem";
17 key = "/root/service-key.pem";
18 disableAuthentication = true;
19 target = "backend:80";
20 unsafeTarget = true;
21 };
22 services.ghostunnel.servers."client-cert" = {
23 listen = "0.0.0.0:1443";
24 cert = "/root/service-cert.pem";
25 key = "/root/service-key.pem";
26 cacert = "/root/ca.pem";
27 target = "backend:80";
28 allowCN = ["client"];
29 unsafeTarget = true;
30 };
31 networking.firewall.allowedTCPPorts = [ 443 1443 ];
32 };
33 client = { pkgs, ... }: {
34 environment.systemPackages = [
35 pkgs.curl
36 ];
37 };
38 };
39
40 testScript = ''
41
42 # prepare certificates
43
44 def cmd(command):
45 print(f"+{command}")
46 r = os.system(command)
47 if r != 0:
48 raise Exception(f"Command {command} failed with exit code {r}")
49
50 # Create CA
51 cmd("${pkgs.openssl}/bin/openssl genrsa -out ca-key.pem 4096")
52 cmd("${pkgs.openssl}/bin/openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -subj '/C=NL/ST=Zuid-Holland/L=The Hague/O=Stevige Balken en Planken B.V./OU=OpSec/CN=Certificate Authority' -out ca.pem")
53
54 # Create service
55 cmd("${pkgs.openssl}/bin/openssl genrsa -out service-key.pem 4096")
56 cmd("${pkgs.openssl}/bin/openssl req -subj '/CN=service' -sha256 -new -key service-key.pem -out service.csr")
57 cmd("echo subjectAltName = DNS:service,IP:127.0.0.1 >> extfile.cnf")
58 cmd("echo extendedKeyUsage = serverAuth >> extfile.cnf")
59 cmd("${pkgs.openssl}/bin/openssl x509 -req -days 365 -sha256 -in service.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out service-cert.pem -extfile extfile.cnf")
60
61 # Create client
62 cmd("${pkgs.openssl}/bin/openssl genrsa -out client-key.pem 4096")
63 cmd("${pkgs.openssl}/bin/openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr")
64 cmd("echo extendedKeyUsage = clientAuth > extfile-client.cnf")
65 cmd("${pkgs.openssl}/bin/openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile extfile-client.cnf")
66
67 cmd("ls -al")
68
69 start_all()
70
71 # Configuration
72 service.copy_from_host("ca.pem", "/root/ca.pem")
73 service.copy_from_host("service-cert.pem", "/root/service-cert.pem")
74 service.copy_from_host("service-key.pem", "/root/service-key.pem")
75 client.copy_from_host("ca.pem", "/root/ca.pem")
76 client.copy_from_host("service-cert.pem", "/root/service-cert.pem")
77 client.copy_from_host("client-cert.pem", "/root/client-cert.pem")
78 client.copy_from_host("client-key.pem", "/root/client-key.pem")
79
80 backend.wait_for_unit("nginx.service")
81 service.wait_for_unit("multi-user.target")
82 service.wait_for_unit("multi-user.target")
83 client.wait_for_unit("multi-user.target")
84
85 # Check assumptions before the real test
86 client.succeed("bash -c 'diff <(curl -v --no-progress-meter http://backend/hi.txt) <(echo hi)'")
87
88 # Plain old simple TLS can connect, ignoring cert
89 client.succeed("bash -c 'diff <(curl -v --no-progress-meter --insecure https://service/hi.txt) <(echo hi)'")
90
91 # Plain old simple TLS provides correct signature with its cert
92 client.succeed("bash -c 'diff <(curl -v --no-progress-meter --cacert /root/ca.pem https://service/hi.txt) <(echo hi)'")
93
94 # Client can authenticate with certificate
95 client.succeed("bash -c 'diff <(curl -v --no-progress-meter --cert /root/client-cert.pem --key /root/client-key.pem --cacert /root/ca.pem https://service:1443/hi.txt) <(echo hi)'")
96
97 # Client must authenticate with certificate
98 client.fail("bash -c 'diff <(curl -v --no-progress-meter --cacert /root/ca.pem https://service:1443/hi.txt) <(echo hi)'")
99 '';
100
101 meta.maintainers = with pkgs.lib.maintainers; [
102 roberth
103 ];
104})