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