125 lines
4.2 KiB
Nix
125 lines
4.2 KiB
Nix
{ self, inputs, lib, ... }:
|
|
let
|
|
mkSANArgs = sans: builtins.concatLists (map (name: [ "--san" name ]) sans);
|
|
mkOpts = config: let cfg = config.mtls; in {
|
|
certDir = lib.mkOption {
|
|
description = "String path to the directory where the certs will be stored";
|
|
type = lib.types.str;
|
|
default = "/etc/mtls";
|
|
};
|
|
keyFile = lib.mkOption {
|
|
description = "String path for the private key";
|
|
type = lib.types.str;
|
|
default = "${config.certDir}/key.pem";
|
|
};
|
|
certFile = lib.mkOption {
|
|
description = "String path for the public cert";
|
|
type = lib.types.str;
|
|
default = "${config.certDir}/cert.pem";
|
|
};
|
|
bundleFile = lib.mkOption {
|
|
description = "String path for the mTLS key bundle";
|
|
type = lib.types.str;
|
|
default = "${config.certDir}/mtls.pem";
|
|
};
|
|
subject = lib.mkOption {
|
|
description = "Subject for the cert";
|
|
type = lib.types.str;
|
|
};
|
|
provisioner = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
};
|
|
provisionerPasswordFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
};
|
|
overwrite = lib.mkEnableOption "Overwrite existing cert file?";
|
|
SANs = lib.mkOption {
|
|
description = "A list of Subject Alternative Names";
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
};
|
|
};
|
|
in
|
|
{
|
|
flake.wrappers.mtls = {
|
|
generate = inputs.wrappers.lib.wrapModule ({ config, lib, wlib, ... }: {
|
|
options = (mkOpts config);
|
|
config = {
|
|
binName = "mtls-generate";
|
|
package = config.pkgs.step-cli;
|
|
extraPackages = with config.pkgs; [ coreutils step-cli systemd ];
|
|
preHook = "mkdir -p ${config.certDir}";
|
|
args = [
|
|
"ca" "certificate"
|
|
"${config.subject}" "${config.certFile}" "${config.keyFile}"
|
|
"--not-before" "-5m"
|
|
"--not-after" "24h"
|
|
]
|
|
++ lib.optionals (config.provisioner != null) [ "--provisioner" "${config.provisioner}" ]
|
|
++ lib.optionals (config.provisionerPasswordFile != null) [
|
|
"--provisioner-password-file" "${config.provisionerPasswordFile}"
|
|
]
|
|
++ lib.optionals config.overwrite [ "-f" ]
|
|
++ mkSANArgs config.SANs;
|
|
postHook = ''
|
|
(umask 077; cat "${config.certFile}" "${config.keyFile}" > "${config.bundleFile}")
|
|
'';
|
|
};
|
|
});
|
|
|
|
renew = inputs.wrappers.lib.wrapModule ({ config, lib, wlib, ... }: {
|
|
# https://github.com/Lassulus/wrappers#generating-systemd-services
|
|
imports = [ wlib.modules.systemd ];
|
|
options = (mkOpts config);
|
|
config = {
|
|
binName = "mtls-renew";
|
|
package = config.pkgs.step-cli;
|
|
extraPackages = with config.pkgs; [ coreutils step-cli systemd ];
|
|
args = [
|
|
"ca" "renew"
|
|
"${config.certFile}" "${config.keyFile}"
|
|
];
|
|
postHook = ''
|
|
(umask 077; cat "${config.certFile}" "${config.keyFile}" > "${config.bundleFile}")
|
|
'';
|
|
|
|
systemd = {
|
|
description = "Renew the mTLS certificate when Smallstep marks it ready";
|
|
documentation = [
|
|
"https://smallstep.com/docs/step-ca/certificate-authority-server-production"
|
|
];
|
|
startLimitIntervalSec = 0;
|
|
after = [ "network-online.target" ];
|
|
wants = [ "network-online.target" ];
|
|
serviceConfig = {
|
|
Type = lib.mkDefault "oneshot";
|
|
ExecCondition = "${lib.getExe config.pkgs.step-cli} certificate needs-renewal ${config.certFile}";
|
|
};
|
|
startAt = "hourly";
|
|
};
|
|
};
|
|
});
|
|
|
|
check = inputs.wrappers.lib.wrapModule ({ config, lib, wlib, ... }: {
|
|
options = (mkOpts config);
|
|
config = {
|
|
binName = "mtls-check";
|
|
# This pattern is necessary to wrap packages like openssl that provide more than one binary
|
|
package = config.pkgs.symlinkJoin {
|
|
name = "openssl";
|
|
paths = [ config.pkgs.openssl.bin config.pkgs.openssl.man ];
|
|
meta.mainProgram = "openssl";
|
|
};
|
|
args = [
|
|
"x509"
|
|
"-noout"
|
|
"-in" config.bundleFile
|
|
"-subject"
|
|
"-issuer"
|
|
"-ext" "subjectAltName,extendedKeyUsage"
|
|
"-enddate"
|
|
];
|
|
};
|
|
});
|
|
};
|
|
} |