1{
2 system ? builtins.currentSystem,
3 config ? { },
4 pkgs ? import ../.. { inherit system config; },
5}:
6
7with import ../lib/testing-python.nix { inherit system pkgs; };
8let
9 mkSpec =
10 {
11 host,
12 service ? null,
13 action,
14 }:
15 {
16 inherit action;
17 authority = {
18 file = {
19 group = "nginx";
20 owner = "nginx";
21 path = "/var/ssl/${host}-ca.pem";
22 };
23 label = "www_ca";
24 profile = "three-month";
25 remote = "localhost:8888";
26 };
27 certificate = {
28 group = "nginx";
29 owner = "nginx";
30 path = "/var/ssl/${host}-cert.pem";
31 };
32 private_key = {
33 group = "nginx";
34 mode = "0600";
35 owner = "nginx";
36 path = "/var/ssl/${host}-key.pem";
37 };
38 request = {
39 CN = host;
40 hosts = [
41 host
42 "www.${host}"
43 ];
44 key = {
45 algo = "rsa";
46 size = 2048;
47 };
48 names = [
49 {
50 C = "US";
51 L = "San Francisco";
52 O = "Example, LLC";
53 ST = "CA";
54 }
55 ];
56 };
57 inherit service;
58 };
59
60 mkCertmgrTest =
61 {
62 svcManager,
63 specs,
64 testScript,
65 }:
66 makeTest {
67 name = "certmgr-" + svcManager;
68 nodes = {
69 machine =
70 {
71 config,
72 lib,
73 pkgs,
74 ...
75 }:
76 {
77 networking.firewall.allowedTCPPorts = with config.services; [
78 cfssl.port
79 certmgr.metricsPort
80 ];
81 networking.extraHosts = "127.0.0.1 imp.example.org decl.example.org";
82
83 services.cfssl.enable = true;
84 systemd.services.cfssl.after = [
85 "cfssl-init.service"
86 "networking.target"
87 ];
88
89 systemd.tmpfiles.rules = [ "d /var/ssl 777 root root" ];
90
91 systemd.services.cfssl-init = {
92 description = "Initialize the cfssl CA";
93 wantedBy = [ "multi-user.target" ];
94 serviceConfig = {
95 User = "cfssl";
96 Type = "oneshot";
97 WorkingDirectory = config.services.cfssl.dataDir;
98 };
99 script = ''
100 ${pkgs.cfssl}/bin/cfssl genkey -initca ${
101 pkgs.writeText "ca.json" (
102 builtins.toJSON {
103 hosts = [ "ca.example.com" ];
104 key = {
105 algo = "rsa";
106 size = 4096;
107 };
108 names = [
109 {
110 C = "US";
111 L = "San Francisco";
112 O = "Internet Widgets, LLC";
113 OU = "Certificate Authority";
114 ST = "California";
115 }
116 ];
117 }
118 )
119 } | ${pkgs.cfssl}/bin/cfssljson -bare ca
120 '';
121 };
122
123 services.nginx = {
124 enable = true;
125 virtualHosts = lib.mkMerge (
126 map
127 (host: {
128 ${host} = {
129 sslCertificate = "/var/ssl/${host}-cert.pem";
130 sslCertificateKey = "/var/ssl/${host}-key.pem";
131 extraConfig = ''
132 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
133 '';
134 onlySSL = true;
135 serverName = host;
136 root = pkgs.writeTextDir "index.html" "It works!";
137 };
138 })
139 [
140 "imp.example.org"
141 "decl.example.org"
142 ]
143 );
144 };
145
146 systemd.services.nginx.wantedBy = lib.mkForce [ ];
147
148 systemd.services.certmgr.after = [ "cfssl.service" ];
149 services.certmgr = {
150 enable = true;
151 inherit svcManager;
152 inherit specs;
153 };
154
155 };
156 };
157 inherit testScript;
158 };
159in
160{
161 systemd = mkCertmgrTest {
162 svcManager = "systemd";
163 specs = {
164 decl = mkSpec {
165 host = "decl.example.org";
166 service = "nginx";
167 action = "restart";
168 };
169 imp = toString (
170 pkgs.writeText "test.json" (
171 builtins.toJSON (mkSpec {
172 host = "imp.example.org";
173 service = "nginx";
174 action = "restart";
175 })
176 )
177 );
178 };
179 testScript = ''
180 machine.wait_for_unit("cfssl.service")
181 machine.wait_until_succeeds("ls /var/ssl/decl.example.org-ca.pem")
182 machine.wait_until_succeeds("ls /var/ssl/decl.example.org-key.pem")
183 machine.wait_until_succeeds("ls /var/ssl/decl.example.org-cert.pem")
184 machine.wait_until_succeeds("ls /var/ssl/imp.example.org-ca.pem")
185 machine.wait_until_succeeds("ls /var/ssl/imp.example.org-key.pem")
186 machine.wait_until_succeeds("ls /var/ssl/imp.example.org-cert.pem")
187 machine.wait_for_unit("nginx.service")
188 assert 1 < int(machine.succeed('journalctl -u nginx | grep "Starting Nginx" | wc -l'))
189 machine.succeed("curl --cacert /var/ssl/imp.example.org-ca.pem https://imp.example.org")
190 machine.succeed(
191 "curl --cacert /var/ssl/decl.example.org-ca.pem https://decl.example.org"
192 )
193 '';
194 };
195
196 command = mkCertmgrTest {
197 svcManager = "command";
198 specs = {
199 test = mkSpec {
200 host = "command.example.org";
201 action = "touch /tmp/command.executed";
202 };
203 };
204 testScript = ''
205 machine.wait_for_unit("cfssl.service")
206 machine.wait_until_succeeds("stat /tmp/command.executed")
207 '';
208 };
209
210}