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