diff options
Diffstat (limited to 'nixos/modules/services/security/cfssl.nix')
-rw-r--r-- | nixos/modules/services/security/cfssl.nix | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/nixos/modules/services/security/cfssl.nix b/nixos/modules/services/security/cfssl.nix new file mode 100644 index 00000000000..6df2343b84d --- /dev/null +++ b/nixos/modules/services/security/cfssl.nix @@ -0,0 +1,222 @@ +{ config, options, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.cfssl; +in { + options.services.cfssl = { + enable = mkEnableOption "the CFSSL CA api-server"; + + dataDir = mkOption { + default = "/var/lib/cfssl"; + type = types.path; + description = '' + The work directory for CFSSL. + + <note><para> + If left as the default value this directory will automatically be + created before the CFSSL server starts, otherwise you are + responsible for ensuring the directory exists with appropriate + ownership and permissions. + </para></note> + ''; + }; + + address = mkOption { + default = "127.0.0.1"; + type = types.str; + description = "Address to bind."; + }; + + port = mkOption { + default = 8888; + type = types.port; + description = "Port to bind."; + }; + + ca = mkOption { + defaultText = literalExpression ''"''${cfg.dataDir}/ca.pem"''; + type = types.str; + description = "CA used to sign the new certificate -- accepts '[file:]fname' or 'env:varname'."; + }; + + caKey = mkOption { + defaultText = literalExpression ''"file:''${cfg.dataDir}/ca-key.pem"''; + type = types.str; + description = "CA private key -- accepts '[file:]fname' or 'env:varname'."; + }; + + caBundle = mkOption { + default = null; + type = types.nullOr types.path; + description = "Path to root certificate store."; + }; + + intBundle = mkOption { + default = null; + type = types.nullOr types.path; + description = "Path to intermediate certificate store."; + }; + + intDir = mkOption { + default = null; + type = types.nullOr types.path; + description = "Intermediates directory."; + }; + + metadata = mkOption { + default = null; + type = types.nullOr types.path; + description = '' + Metadata file for root certificate presence. + The content of the file is a json dictionary (k,v): each key k is + a SHA-1 digest of a root certificate while value v is a list of key + store filenames. + ''; + }; + + remote = mkOption { + default = null; + type = types.nullOr types.str; + description = "Remote CFSSL server."; + }; + + configFile = mkOption { + default = null; + type = types.nullOr types.str; + description = "Path to configuration file. Do not put this in nix-store as it might contain secrets."; + }; + + responder = mkOption { + default = null; + type = types.nullOr types.path; + description = "Certificate for OCSP responder."; + }; + + responderKey = mkOption { + default = null; + type = types.nullOr types.str; + description = "Private key for OCSP responder certificate. Do not put this in nix-store."; + }; + + tlsKey = mkOption { + default = null; + type = types.nullOr types.str; + description = "Other endpoint's CA private key. Do not put this in nix-store."; + }; + + tlsCert = mkOption { + default = null; + type = types.nullOr types.path; + description = "Other endpoint's CA to set up TLS protocol."; + }; + + mutualTlsCa = mkOption { + default = null; + type = types.nullOr types.path; + description = "Mutual TLS - require clients be signed by this CA."; + }; + + mutualTlsCn = mkOption { + default = null; + type = types.nullOr types.str; + description = "Mutual TLS - regex for whitelist of allowed client CNs."; + }; + + tlsRemoteCa = mkOption { + default = null; + type = types.nullOr types.path; + description = "CAs to trust for remote TLS requests."; + }; + + mutualTlsClientCert = mkOption { + default = null; + type = types.nullOr types.path; + description = "Mutual TLS - client certificate to call remote instance requiring client certs."; + }; + + mutualTlsClientKey = mkOption { + default = null; + type = types.nullOr types.path; + description = "Mutual TLS - client key to call remote instance requiring client certs. Do not put this in nix-store."; + }; + + dbConfig = mkOption { + default = null; + type = types.nullOr types.path; + description = "Certificate db configuration file. Path must be writeable."; + }; + + logLevel = mkOption { + default = 1; + type = types.enum [ 0 1 2 3 4 5 ]; + description = "Log level (0 = DEBUG, 5 = FATAL)."; + }; + }; + + config = mkIf cfg.enable { + users.groups.cfssl = { + gid = config.ids.gids.cfssl; + }; + + users.users.cfssl = { + description = "cfssl user"; + home = cfg.dataDir; + group = "cfssl"; + uid = config.ids.uids.cfssl; + }; + + systemd.services.cfssl = { + description = "CFSSL CA API server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = lib.mkMerge [ + { + WorkingDirectory = cfg.dataDir; + Restart = "always"; + User = "cfssl"; + Group = "cfssl"; + + ExecStart = with cfg; let + opt = n: v: optionalString (v != null) ''-${n}="${v}"''; + in + lib.concatStringsSep " \\\n" [ + "${pkgs.cfssl}/bin/cfssl serve" + (opt "address" address) + (opt "port" (toString port)) + (opt "ca" ca) + (opt "ca-key" caKey) + (opt "ca-bundle" caBundle) + (opt "int-bundle" intBundle) + (opt "int-dir" intDir) + (opt "metadata" metadata) + (opt "remote" remote) + (opt "config" configFile) + (opt "responder" responder) + (opt "responder-key" responderKey) + (opt "tls-key" tlsKey) + (opt "tls-cert" tlsCert) + (opt "mutual-tls-ca" mutualTlsCa) + (opt "mutual-tls-cn" mutualTlsCn) + (opt "mutual-tls-client-key" mutualTlsClientKey) + (opt "mutual-tls-client-cert" mutualTlsClientCert) + (opt "tls-remote-ca" tlsRemoteCa) + (opt "db-config" dbConfig) + (opt "loglevel" (toString logLevel)) + ]; + } + (mkIf (cfg.dataDir == options.services.cfssl.dataDir.default) { + StateDirectory = baseNameOf cfg.dataDir; + StateDirectoryMode = 700; + }) + ]; + }; + + services.cfssl = { + ca = mkDefault "${cfg.dataDir}/ca.pem"; + caKey = mkDefault "${cfg.dataDir}/ca-key.pem"; + }; + }; +} |