190 lines
5.9 KiB
Nix
190 lines
5.9 KiB
Nix
{ inputs, ... }:
|
|
{
|
|
flake.modules.nixos.step-ca = { config, pkgs, lib, ... }:
|
|
let
|
|
cfg = config.step-ca;
|
|
caAddress = "0.0.0.0";
|
|
caPort = 443;
|
|
|
|
caPasswordPath = (lib.getAttr cfg.secrets.caPassword config.sops.secrets).path;
|
|
intermediateKeyPath = (lib.getAttr cfg.secrets.intermediateKey config.sops.secrets).path;
|
|
sshHostCaKeyPath = (lib.getAttr cfg.secrets.sshHostCaKey config.sops.secrets).path;
|
|
sshUserCaKeyPath = (lib.getAttr cfg.secrets.sshUserCaKey config.sops.secrets).path;
|
|
adminProvisionerEncryptedKeyValue =
|
|
(lib.getAttr cfg.secrets.adminProvisionerEncryptedKey config.sops.placeholder);
|
|
|
|
renderedStepCaConfig = builtins.toJSON {
|
|
root = cfg.rootCertPath;
|
|
crt = cfg.intermediateCertPath;
|
|
key = intermediateKeyPath;
|
|
address = "${caAddress}:${toString caPort}";
|
|
dnsNames = cfg.dnsNames;
|
|
|
|
ssh = {
|
|
hostKey = sshHostCaKeyPath;
|
|
userKey = sshUserCaKeyPath;
|
|
};
|
|
|
|
db = {
|
|
type = "badgerv2";
|
|
dataSource = "/var/lib/step-ca/db";
|
|
};
|
|
|
|
authority = {
|
|
backdate = "1m0s";
|
|
provisioners = [
|
|
{
|
|
type = "ACME";
|
|
name = "acme";
|
|
}
|
|
{
|
|
type = "SSHPOP";
|
|
name = "sshpop";
|
|
claims.enableSSHCA = true;
|
|
}
|
|
{
|
|
type = "JWK";
|
|
name = "admin";
|
|
key = {
|
|
use = "sig";
|
|
kty = "EC";
|
|
kid = "xoxgOJFbveSLIL2gm1Yu5ZiRb9v8Jxe44F56i3v-Nf8";
|
|
crv = "P-256";
|
|
alg = "ES256";
|
|
x = "zFO8hPx_eH0Iyz7UJI-w8ODMusEKCZ28M76sGWmWYxA";
|
|
y = "XIWLLyKDzqxV9UH-2KeAkKPDrgLoPrxxW9-PzkXggME";
|
|
};
|
|
encryptedKey = adminProvisionerEncryptedKeyValue;
|
|
claims = {
|
|
enableSSHCA = true;
|
|
disableRenewal = false;
|
|
allowRenewalAfterExpiry = false;
|
|
disableSmallstepExtensions = false;
|
|
};
|
|
options = {
|
|
x509 = { };
|
|
ssh = { };
|
|
};
|
|
}
|
|
];
|
|
};
|
|
|
|
tls = {
|
|
cipherSuites = [
|
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
|
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
|
];
|
|
minVersion = 1.2;
|
|
maxVersion = 1.3;
|
|
renegotiation = false;
|
|
};
|
|
};
|
|
in
|
|
{
|
|
options.step-ca = {
|
|
rootCertPath = lib.mkOption {
|
|
description = "Path to the Step CA root certificate served by this host.";
|
|
type = lib.types.path;
|
|
};
|
|
intermediateCertPath = lib.mkOption {
|
|
description = "Path to the Step CA intermediate certificate served by this host. This is public material and does not need to be stored in SOPS.";
|
|
type = lib.types.path;
|
|
};
|
|
dnsNames = lib.mkOption {
|
|
description = "DNS names and IP SANs advertised by this Step CA instance.";
|
|
type = with lib.types; listOf str;
|
|
};
|
|
secrets = {
|
|
sopsFile = lib.mkOption {
|
|
description = "Host-local SOPS file that stores Step CA secret material.";
|
|
type = lib.types.path;
|
|
};
|
|
caPassword = lib.mkOption {
|
|
description = "SOPS key for the Step CA intermediate password.";
|
|
type = lib.types.str;
|
|
};
|
|
intermediateKey = lib.mkOption {
|
|
description = "SOPS key for the Step CA intermediate private key.";
|
|
type = lib.types.str;
|
|
};
|
|
sshHostCaKey = lib.mkOption {
|
|
description = "SOPS key for the Step SSH host CA private key.";
|
|
type = lib.types.str;
|
|
};
|
|
sshUserCaKey = lib.mkOption {
|
|
description = "SOPS key for the Step SSH user CA private key.";
|
|
type = lib.types.str;
|
|
};
|
|
adminProvisionerEncryptedKey = lib.mkOption {
|
|
description = "SOPS key for the Step CA admin provisioner encrypted key.";
|
|
type = lib.types.str;
|
|
};
|
|
};
|
|
};
|
|
|
|
config = {
|
|
# Placeholders are expected initially until real material is inserted into sops.
|
|
sops.secrets."${cfg.secrets.caPassword}" = {
|
|
sopsFile = cfg.secrets.sopsFile;
|
|
owner = "step-ca";
|
|
group = "step-ca";
|
|
mode = "0400";
|
|
restartUnits = [ "step-ca.service" ];
|
|
};
|
|
sops.secrets."${cfg.secrets.intermediateKey}" = {
|
|
sopsFile = cfg.secrets.sopsFile;
|
|
owner = "step-ca";
|
|
group = "step-ca";
|
|
mode = "0400";
|
|
restartUnits = [ "step-ca.service" ];
|
|
};
|
|
sops.secrets."${cfg.secrets.sshHostCaKey}" = {
|
|
sopsFile = cfg.secrets.sopsFile;
|
|
owner = "step-ca";
|
|
group = "step-ca";
|
|
mode = "0400";
|
|
restartUnits = [ "step-ca.service" ];
|
|
};
|
|
sops.secrets."${cfg.secrets.sshUserCaKey}" = {
|
|
sopsFile = cfg.secrets.sopsFile;
|
|
owner = "step-ca";
|
|
group = "step-ca";
|
|
mode = "0400";
|
|
restartUnits = [ "step-ca.service" ];
|
|
};
|
|
sops.secrets."${cfg.secrets.adminProvisionerEncryptedKey}" = {
|
|
sopsFile = cfg.secrets.sopsFile;
|
|
owner = "step-ca";
|
|
group = "step-ca";
|
|
mode = "0400";
|
|
restartUnits = [ "step-ca.service" ];
|
|
};
|
|
|
|
sops.templates."step-ca-config" = {
|
|
owner = "step-ca";
|
|
group = "step-ca";
|
|
mode = "0400";
|
|
content = renderedStepCaConfig;
|
|
};
|
|
|
|
# https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/security/step-ca.nix
|
|
services.step-ca = {
|
|
enable = true;
|
|
openFirewall = true;
|
|
address = caAddress;
|
|
port = caPort;
|
|
intermediatePasswordFile = caPasswordPath;
|
|
};
|
|
|
|
environment.etc."smallstep/ca.json".source =
|
|
lib.mkForce config.sops.templates."step-ca-config".path;
|
|
systemd.services.step-ca.restartTriggers =
|
|
lib.mkAfter [ config.sops.templates."step-ca-config".path ];
|
|
|
|
environment.systemPackages = with pkgs; [
|
|
step-ca
|
|
step-cli
|
|
];
|
|
};
|
|
};
|
|
} |