hearth/terraform/vault-pki-smime.tf
Eric Garcia e78000831e Initial commit: Port infrastructure from coherence-mcp
Hearth is the infrastructure home for the letemcook ecosystem.

Ported from coherence-mcp/infra:
- Terraform modules (VPC, EKS, IAM, NLB, S3, storage)
- Kubernetes manifests (Forgejo, ingress, cert-manager, karpenter)
- Deployment scripts (phased rollout)

Status: Not deployed. EKS cluster needs to be provisioned.

Next steps:
1. Bootstrap terraform backend
2. Deploy phase 1 (foundation)
3. Deploy phase 2 (core services including Forgejo)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:06:13 -05:00

212 lines
6.2 KiB
HCL

# 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}"
}