infra/terraform/vault/ica2.nix
Raito Bezarius c9aa82ba49 feat(terraform): support declarative subCAs and their Vault policies
We can now derive an infinite amount of subCAs as long as we do not
violate extensions constraints.

Additionally, we can build Vault policies specific to the PKI endpoint
without encoding the mountpoints.

Additionally, we can build Vault roles specific to the PKI endpoint
without encoding the mountpoints.

This adds an example of deep-derivation.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2025-01-01 01:54:37 +01:00

110 lines
3.6 KiB
Nix

{ config, lib, ... }:
let
inherit (lib) tf mkOption mkEnableOption types mkIf;
parentConf = config.infra.pki;
cfgIca1 = config.infra.pki.ica1;
cfg = config.infra.pki.ica2;
hour_in_secs = 1 * 60 * 60;
year_in_secs = 365 * 24 * hour_in_secs;
in
{
options.infra.pki.ica2 = {
enable = mkEnableOption "provision an ICA2";
enableVersioning = mkOption {
type = types.bool;
default = true;
readOnly = true;
};
name = mkOption {
type = types.str;
default = "ica2";
readOnly = true;
};
partialResourceId = mkOption {
type = types.str;
default = "v${toString cfg.version}_ica2_v${toString cfg.certVersion}";
readOnly = true;
};
resourceId = mkOption {
type = types.str;
default = "${parentConf.org.id}_${cfg.partialResourceId}";
readOnly = true;
};
signId = mkOption {
type = types.str;
default = "${cfg.resourceId}_by_ica1_v${toString cfgIca1.certVersion}";
readOnly = true;
};
version = mkOption {
type = types.int;
default = 1;
description = "Version number of the ICA2 chain";
};
certVersion = mkOption {
type = types.int;
default = 1;
description = "Version number of the same ICA2 chain for the certificate itself";
};
subCA = mkOption {
type = types.lazyAttrsOf (types.submodule (import ./sub-ca-options.nix));
default = { };
description = "Sub-CAs derived from ICA2";
};
};
config = mkIf cfg.enable {
resource.vault_mount."${cfg.resourceId}" = {
inherit (parentConf) provider;
path = "${parentConf.org.id}/v${toString cfg.version}/ica2/v${toString cfg.certVersion}";
type = "pki";
description = "PKI engine hosting v${toString cfg.version} intermediate CA2 v${toString cfg.certVersion} for ${parentConf.org.displayName}";
# 1 hr in seconds.
default_lease_ttl_seconds = 1 * hour_in_secs;
max_lease_ttl_seconds = 1 * year_in_secs;
};
resource.vault_pki_secret_backend_intermediate_cert_request."${cfg.resourceId}" = {
inherit (parentConf) provider;
depends_on = [ "vault_mount.${cfg.resourceId}" ];
backend = tf.ref "vault_mount.${cfg.resourceId}.path";
type = "internal";
common_name = "Intermediate CA2 v${toString cfg.certVersion} ";
key_type = "ed25519";
inherit (parentConf.org) ou organization country locality province;
};
resource.vault_pki_secret_backend_root_sign_intermediate."${cfg.signId}" = {
inherit (parentConf) provider;
depends_on = [
"vault_mount.${cfg.resourceId}"
"vault_pki_secret_backend_intermediate_cert_request.${cfg.resourceId}"
];
backend = tf.ref "vault_mount.${cfgIca1.resourceId}.path";
csr = tf.ref "vault_pki_secret_backend_intermediate_cert_request.${cfg.resourceId}.csr";
common_name = "Intermediate CA2 v${toString cfgIca1.certVersion}.${toString cfg.certVersion}";
exclude_cn_from_sans = true;
inherit (parentConf.org) ou organization country locality province;
max_path_length = 1;
ttl = 1 * year_in_secs;
};
resource.vault_pki_secret_backend_intermediate_set_signed."${cfg.resourceId}_signed_cert" = {
inherit (parentConf) provider;
depends_on = [ "vault_pki_secret_backend_root_sign_intermediate.${cfg.signId}" ];
backend = tf.ref "vault_mount.${cfg.resourceId}.path";
certificate = ''
${tf.ref "vault_pki_secret_backend_root_sign_intermediate.${cfg.signId}.certificate"}
${builtins.readFile cfgIca1.signedCert}
'';
};
};
}