at 23.11-pre 6.7 kB view raw
1{ config, options, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.cfssl; 7in { 8 options.services.cfssl = { 9 enable = mkEnableOption (lib.mdDoc "the CFSSL CA api-server"); 10 11 dataDir = mkOption { 12 default = "/var/lib/cfssl"; 13 type = types.path; 14 description = lib.mdDoc '' 15 The work directory for CFSSL. 16 17 ::: {.note} 18 If left as the default value this directory will automatically be 19 created before the CFSSL server starts, otherwise you are 20 responsible for ensuring the directory exists with appropriate 21 ownership and permissions. 22 ::: 23 ''; 24 }; 25 26 address = mkOption { 27 default = "127.0.0.1"; 28 type = types.str; 29 description = lib.mdDoc "Address to bind."; 30 }; 31 32 port = mkOption { 33 default = 8888; 34 type = types.port; 35 description = lib.mdDoc "Port to bind."; 36 }; 37 38 ca = mkOption { 39 defaultText = literalExpression ''"''${cfg.dataDir}/ca.pem"''; 40 type = types.str; 41 description = lib.mdDoc "CA used to sign the new certificate -- accepts '[file:]fname' or 'env:varname'."; 42 }; 43 44 caKey = mkOption { 45 defaultText = literalExpression ''"file:''${cfg.dataDir}/ca-key.pem"''; 46 type = types.str; 47 description = lib.mdDoc "CA private key -- accepts '[file:]fname' or 'env:varname'."; 48 }; 49 50 caBundle = mkOption { 51 default = null; 52 type = types.nullOr types.path; 53 description = lib.mdDoc "Path to root certificate store."; 54 }; 55 56 intBundle = mkOption { 57 default = null; 58 type = types.nullOr types.path; 59 description = lib.mdDoc "Path to intermediate certificate store."; 60 }; 61 62 intDir = mkOption { 63 default = null; 64 type = types.nullOr types.path; 65 description = lib.mdDoc "Intermediates directory."; 66 }; 67 68 metadata = mkOption { 69 default = null; 70 type = types.nullOr types.path; 71 description = lib.mdDoc '' 72 Metadata file for root certificate presence. 73 The content of the file is a json dictionary (k,v): each key k is 74 a SHA-1 digest of a root certificate while value v is a list of key 75 store filenames. 76 ''; 77 }; 78 79 remote = mkOption { 80 default = null; 81 type = types.nullOr types.str; 82 description = lib.mdDoc "Remote CFSSL server."; 83 }; 84 85 configFile = mkOption { 86 default = null; 87 type = types.nullOr types.str; 88 description = lib.mdDoc "Path to configuration file. Do not put this in nix-store as it might contain secrets."; 89 }; 90 91 responder = mkOption { 92 default = null; 93 type = types.nullOr types.path; 94 description = lib.mdDoc "Certificate for OCSP responder."; 95 }; 96 97 responderKey = mkOption { 98 default = null; 99 type = types.nullOr types.str; 100 description = lib.mdDoc "Private key for OCSP responder certificate. Do not put this in nix-store."; 101 }; 102 103 tlsKey = mkOption { 104 default = null; 105 type = types.nullOr types.str; 106 description = lib.mdDoc "Other endpoint's CA private key. Do not put this in nix-store."; 107 }; 108 109 tlsCert = mkOption { 110 default = null; 111 type = types.nullOr types.path; 112 description = lib.mdDoc "Other endpoint's CA to set up TLS protocol."; 113 }; 114 115 mutualTlsCa = mkOption { 116 default = null; 117 type = types.nullOr types.path; 118 description = lib.mdDoc "Mutual TLS - require clients be signed by this CA."; 119 }; 120 121 mutualTlsCn = mkOption { 122 default = null; 123 type = types.nullOr types.str; 124 description = lib.mdDoc "Mutual TLS - regex for whitelist of allowed client CNs."; 125 }; 126 127 tlsRemoteCa = mkOption { 128 default = null; 129 type = types.nullOr types.path; 130 description = lib.mdDoc "CAs to trust for remote TLS requests."; 131 }; 132 133 mutualTlsClientCert = mkOption { 134 default = null; 135 type = types.nullOr types.path; 136 description = lib.mdDoc "Mutual TLS - client certificate to call remote instance requiring client certs."; 137 }; 138 139 mutualTlsClientKey = mkOption { 140 default = null; 141 type = types.nullOr types.path; 142 description = lib.mdDoc "Mutual TLS - client key to call remote instance requiring client certs. Do not put this in nix-store."; 143 }; 144 145 dbConfig = mkOption { 146 default = null; 147 type = types.nullOr types.path; 148 description = lib.mdDoc "Certificate db configuration file. Path must be writeable."; 149 }; 150 151 logLevel = mkOption { 152 default = 1; 153 type = types.enum [ 0 1 2 3 4 5 ]; 154 description = lib.mdDoc "Log level (0 = DEBUG, 5 = FATAL)."; 155 }; 156 }; 157 158 config = mkIf cfg.enable { 159 users.groups.cfssl = { 160 gid = config.ids.gids.cfssl; 161 }; 162 163 users.users.cfssl = { 164 description = "cfssl user"; 165 home = cfg.dataDir; 166 group = "cfssl"; 167 uid = config.ids.uids.cfssl; 168 }; 169 170 systemd.services.cfssl = { 171 description = "CFSSL CA API server"; 172 wantedBy = [ "multi-user.target" ]; 173 after = [ "network.target" ]; 174 175 serviceConfig = lib.mkMerge [ 176 { 177 WorkingDirectory = cfg.dataDir; 178 Restart = "always"; 179 User = "cfssl"; 180 Group = "cfssl"; 181 182 ExecStart = with cfg; let 183 opt = n: v: optionalString (v != null) ''-${n}="${v}"''; 184 in 185 lib.concatStringsSep " \\\n" [ 186 "${pkgs.cfssl}/bin/cfssl serve" 187 (opt "address" address) 188 (opt "port" (toString port)) 189 (opt "ca" ca) 190 (opt "ca-key" caKey) 191 (opt "ca-bundle" caBundle) 192 (opt "int-bundle" intBundle) 193 (opt "int-dir" intDir) 194 (opt "metadata" metadata) 195 (opt "remote" remote) 196 (opt "config" configFile) 197 (opt "responder" responder) 198 (opt "responder-key" responderKey) 199 (opt "tls-key" tlsKey) 200 (opt "tls-cert" tlsCert) 201 (opt "mutual-tls-ca" mutualTlsCa) 202 (opt "mutual-tls-cn" mutualTlsCn) 203 (opt "mutual-tls-client-key" mutualTlsClientKey) 204 (opt "mutual-tls-client-cert" mutualTlsClientCert) 205 (opt "tls-remote-ca" tlsRemoteCa) 206 (opt "db-config" dbConfig) 207 (opt "loglevel" (toString logLevel)) 208 ]; 209 } 210 (mkIf (cfg.dataDir == options.services.cfssl.dataDir.default) { 211 StateDirectory = baseNameOf cfg.dataDir; 212 StateDirectoryMode = 700; 213 }) 214 ]; 215 }; 216 217 services.cfssl = { 218 ca = mkDefault "${cfg.dataDir}/ca.pem"; 219 caKey = mkDefault "${cfg.dataDir}/ca-key.pem"; 220 }; 221 }; 222}