Files
panxiao81 88a02ababa
lint / yaml (push) Has been cancelled
lint / ansible (push) Has been cancelled
lint / terraform (push) Has been cancelled
Establish clean homelab infrastructure baseline
Reorganize the brownfield repository, remove retired and generated artifacts, harden ignore rules, and record the GitOps/IaC redesign.
2026-09-09 16:47:20 +00:00

75 lines
3.9 KiB
Terraform

# ── issuing role ──────────────────────────────────────────────────────────
# Caps what ACME (and direct issuance) may mint. dc1's LDAPS cert comes from here.
resource "vault_pki_secret_backend_role" "bao_server" {
backend = vault_mount.pki.path
name = "bao-server"
allowed_domains = ["ad.ddupan.top"]
allow_subdomains = true
allow_bare_domains = false
allow_glob_domains = false
allow_any_name = false
allow_ip_sans = true # dc1's cert carries IP:192.168.10.5
server_flag = true
client_flag = true
key_type = "rsa"
key_bits = 2048
max_ttl = 31536000 # 1y
# 60d. NOT 0: ttl=0 falls back to the system default of 768h (32 days), which
# is what dc1's cert was getting. That is fine for lego (samba_ad_acme renews at
# 10 days left) but breaks Proxmox: PVE's renewal threshold is hardcoded at "30
# days to expiry" (PVE/API2/ACME.pm), so a 32-day cert renews every ~2 days and
# restarts pveproxy each time. 60d leaves PVE a full 30-day retry window -- which
# matters given the flaky WAN -- and stays well under OpenBao's 90d ACME cap.
ttl = 5184000 # 60d
use_csr_common_name = true
}
# ── cluster paths ─────────────────────────────────────────────────────────
# ACME directory/order URLs are built from these and embedded in issued certs as
# AIA URLs, so they must be reachable by clients exactly as written. Uses the
# public hostname (real Let's Encrypt cert via the openbao_acme Ansible role),
# not the bare IP.
resource "vault_pki_secret_backend_config_cluster" "this" {
backend = vault_mount.pki.path
path = "${var.bao_address}/v1/${vault_mount.pki.path}"
aia_path = "${var.bao_address}/v1/${vault_mount.pki.path}"
}
# ── ACME ──────────────────────────────────────────────────────────────────
# WHY: dc1's LDAPS cert was hand-issued 2026-07-25 and expires 2027-07-25 with
# nothing to renew it. If it lapses, Authelia loses its LDAPS backend and every
# SSO consumer fails at once. ACME takes the human out of that loop.
resource "vault_pki_secret_backend_config_acme" "this" {
backend = vault_mount.pki.path
enabled = var.acme_enabled
# SECURITY: OpenBao's default is "sign-verbatim" — it would issue ANY name a
# client asks for, meaning anything able to reach bao could mint a cert for
# dc1.ad.ddupan.top from the ROOT CA. Pinning to the role caps issuance at
# that role's allowed_domains.
default_directory_policy = "role:${vault_pki_secret_backend_role.bao_server.name}"
allowed_roles = [vault_pki_secret_backend_role.bao_server.name]
allowed_issuers = ["*"]
# See variables.tf for the not-required vs EAB trade-off.
eab_policy = var.acme_eab_policy
# Empty = server's own resolver. bao resolves ad.ddupan.top correctly
# (verified), so http-01 validation against internal hosts works.
dns_resolver = ""
depends_on = [vault_pki_secret_backend_config_cluster.this]
}
# ── issuing / CRL URLs ────────────────────────────────────────────────────
# Embedded in every issued cert so clients can fetch the CA and check the CRL.
# Previously set by ../ansible (pki.yml, "Configure issuing/CRL URLs") — moved
# here as part of the Terraform-owns-configuration split.
resource "vault_pki_secret_backend_config_urls" "this" {
backend = vault_mount.pki.path
issuing_certificates = ["${var.bao_address}/v1/${vault_mount.pki.path}/ca"]
crl_distribution_points = ["${var.bao_address}/v1/${vault_mount.pki.path}/crl"]
}