# Vault PKI for S/MIME Certificates # RFC 0041: Self-Hosted DNS and Email # ADR 0006: Zero-Knowledge Zero-Trust (Layer 3 encryption support) # # This configuration creates a PKI secrets engine in Vault for issuing # S/MIME certificates to users. S/MIME provides end-to-end email encryption # (Layer 3) where only the sender and recipient can read the email content. terraform { required_providers { vault = { source = "hashicorp/vault" version = "~> 4.0" } } } # ============================================================================= # ROOT CA (Offline - used only to sign intermediate) # ============================================================================= resource "vault_mount" "pki_root_smime" { path = "pki-smime-root" type = "pki" description = "S/MIME Root CA - Offline, used only to sign intermediate" # Root CA has a longer lifetime default_lease_ttl_seconds = 315360000 # 10 years max_lease_ttl_seconds = 315360000 # 10 years } resource "vault_pki_secret_backend_root_cert" "smime_root" { backend = vault_mount.pki_root_smime.path type = "internal" common_name = "Alignment S/MIME Root CA" ttl = "315360000" # 10 years key_type = "rsa" key_bits = 4096 organization = "Alignment" country = "US" exclude_cn_from_sans = true } # ============================================================================= # INTERMEDIATE CA (Online - used to issue user certificates) # ============================================================================= resource "vault_mount" "pki_smime" { path = "pki-smime" type = "pki" description = "S/MIME Intermediate CA - Issues user certificates" # Intermediate has shorter lifetime default_lease_ttl_seconds = 31536000 # 1 year max_lease_ttl_seconds = 94608000 # 3 years } # Generate intermediate CSR resource "vault_pki_secret_backend_intermediate_cert_request" "smime_intermediate" { backend = vault_mount.pki_smime.path type = "internal" common_name = "Alignment S/MIME Intermediate CA" key_type = "rsa" key_bits = 4096 organization = "Alignment" country = "US" } # Sign intermediate with root resource "vault_pki_secret_backend_root_sign_intermediate" "smime_intermediate" { backend = vault_mount.pki_root_smime.path common_name = "Alignment S/MIME Intermediate CA" csr = vault_pki_secret_backend_intermediate_cert_request.smime_intermediate.csr ttl = "157680000" # 5 years organization = "Alignment" country = "US" # Intermediate CA permissions permitted_dns_domains = ["alignment.dev"] } # Set the signed intermediate certificate resource "vault_pki_secret_backend_intermediate_set_signed" "smime_intermediate" { backend = vault_mount.pki_smime.path certificate = vault_pki_secret_backend_root_sign_intermediate.smime_intermediate.certificate } # ============================================================================= # S/MIME CERTIFICATE ROLE # ============================================================================= resource "vault_pki_secret_backend_role" "smime_user" { backend = vault_mount.pki_smime.path name = "smime-user" # Certificate lifetime ttl = 31536000 # 1 year max_ttl = 63072000 # 2 years # Domain restrictions allow_any_name = false allowed_domains = ["alignment.dev"] allow_subdomains = false enforce_hostnames = false # Allow email addresses allow_bare_domains = true # Key configuration key_type = "rsa" key_bits = 4096 key_usage = ["DigitalSignature", "KeyEncipherment", "ContentCommitment"] # S/MIME specific - Email Protection extended key usage ext_key_usage = ["EmailProtection"] # Certificate properties require_cn = true use_csr_common_name = true use_csr_sans = true # Organization defaults organization = ["Alignment"] country = ["US"] # Don't include SANs automatically allow_ip_sans = false allow_localhost = false allowed_uri_sans = [] allowed_other_sans = [] # Generate certificates (not just sign CSRs) generate_lease = true no_store = false } # ============================================================================= # POLICY FOR S/MIME CERTIFICATE ISSUANCE # ============================================================================= resource "vault_policy" "smime_user_issue" { name = "smime-user-issue" policy = <<-EOT # Allow users to issue S/MIME certificates for their own email # Users authenticate via OIDC, and their email claim is used to verify # they can only request certificates for their own email address. # Issue S/MIME certificate path "pki-smime/issue/smime-user" { capabilities = ["create", "update"] # Restrict to user's own email allowed_parameters = { "common_name" = [] "alt_names" = [] "ttl" = [] } } # Read certificate chain path "pki-smime/ca/pem" { capabilities = ["read"] } path "pki-smime/ca_chain" { capabilities = ["read"] } # List own certificates path "pki-smime/certs" { capabilities = ["list"] } EOT } # ============================================================================= # CRL CONFIGURATION # ============================================================================= resource "vault_pki_secret_backend_config_urls" "smime_urls" { backend = vault_mount.pki_smime.path issuing_certificates = [ "https://vault.alignment.dev/v1/pki-smime/ca" ] crl_distribution_points = [ "https://vault.alignment.dev/v1/pki-smime/crl" ] ocsp_servers = [ "https://vault.alignment.dev/v1/pki-smime/ocsp" ] } # ============================================================================= # OUTPUTS # ============================================================================= output "smime_ca_chain" { description = "S/MIME CA certificate chain" value = vault_pki_secret_backend_intermediate_set_signed.smime_intermediate.certificate sensitive = false } output "smime_issue_path" { description = "Path to issue S/MIME certificates" value = "${vault_mount.pki_smime.path}/issue/${vault_pki_secret_backend_role.smime_user.name}" }