PKI Root Rotation

Root CA rotation procedures, intermediate re-issuance, trust chain.

NIST controls:SC-12, SC-17, IA-5
Last updated:2026-03-22
Category:Technical
# PKI Root CA Rotation — Contingency Plan (NOT CURRENTLY NEEDED) ## Status: NOT NEEDED Verified 2026-03-22: the root CA (`CN=KuiperDesk Internal CA`, valid 2026-2036) has **NO name constraints**. Custom domains work without any rotation. ``` $ openssl x509 -in root-ca.crt -text | grep "Name Constraints" (no output — unconstrained) ``` The `*.kuiperdesk.ai` scope mentioned in early CLAUDE.md was design intent, never enforced. This plan is retained as a contingency if constraints are ever added to a future root. ## Contingency: If Name Constraints Were Present If the root HAD been issued with name constraints: ## Solution: Cross-Sign (Zero Downtime) Issue a new root alongside the old one. Cross-sign the existing hub intermediate with the new root. Both chains are valid simultaneously. Nothing breaks. ``` BEFORE (constrained): Root-A (*.kuiperdesk.ai, *.arivaran.ai) └─ Hub Intermediate └─ Company certs (*.arivaran.ai) ✓ └─ Product certs (*.kuiperdesk.ai) ✓ └─ Custom domain (*.megacorp.com) ✗ BLOCKED AFTER (cross-signed, both valid): Root-A (*.kuiperdesk.ai, *.arivaran.ai) ← OLD, stays valid └─ Hub Intermediate ← SAME cert, two parents └─ Company certs (*.arivaran.ai) ✓ validates via Root-A Root-B (NO constraints) ← NEW, unconstrained └─ Hub Intermediate (cross-signed) ← SAME key, new signature from Root-B └─ Satellite Intermediates └─ Custom domain certs ✓ validates via Root-B └─ *.kuiperdesk.ai certs ✓ validates via either root ``` ## Step-by-Step Rotation ### Phase 1: Generate New Root (CloudHSM Ceremony — 1 hour) ```bash # On air-gapped ceremony laptop with CloudHSM access # Same ceremony as original root, but WITHOUT name constraints # Generate new ECDSA P-384 root key on CloudHSM pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so \ --keypairgen --key-type EC:secp384r1 \ --label "kuiperdesk-root-b" --id 02 # Create self-signed root cert (20 year, NO name constraints) openssl req -new -x509 -engine cloudhsm -keyform engine \ -key "pkcs11:token=hsm;object=kuiperdesk-root-b" \ -sha384 -days 7300 \ -subj "/CN=KuiperDesk Root CA B/O=Arivaran Inc/C=US" \ -addext "basicConstraints=critical,CA:TRUE" \ -addext "keyUsage=critical,keyCertSign,cRLSign" \ -out root-b.crt # NOTE: no nameConstraints extension = unconstrained ``` ### Phase 2: Cross-Sign Hub Intermediate (5 minutes, no downtime) ```bash # Extract CSR from existing hub intermediate (OpenBao has the key) vault read -field=csr pki_int/intermediate/generate/existing \ > hub-intermediate.csr # Sign with NEW root (Root-B, unconstrained) openssl x509 -req -in hub-intermediate.csr \ -CA root-b.crt -CAkey "pkcs11:..." \ -CAcreateserial -sha384 -days 3650 \ -extfile <(echo "basicConstraints=critical,CA:TRUE,pathlen:2 keyUsage=critical,keyCertSign,cRLSign authorityKeyIdentifier=keyid:always subjectKeyIdentifier=hash") \ -out hub-intermediate-cross-signed.crt # Import cross-signed cert into OpenBao (alongside existing) vault write pki_int/intermediate/set-signed \ certificate=@hub-intermediate-cross-signed.crt ``` ### Phase 3: Distribute Root-B (Gradual, No Rush) The old root (Root-A) still works for everything. Root-B is needed ONLY for: - New satellite intermediates with custom domains - ca-bundle.pem in air-gap bundles Distribution: 1. **Hub services**: Already trust Root-B after OpenBao import 2. **Satellites**: New satellites get Root-B in bootstrap. Existing satellites get it at next cert renewal. 3. **Agents**: New agents get Root-B in ca-bundle.pem. Existing agents continue working with Root-A chain. 4. **Company infra**: No change needed — Root-A chain still valid for `*.arivaran.ai` 5. **Browsers**: CATrust.cpp installs Root-B alongside Root-A (both in ca-bundle.pem) ### Phase 4: Retire Root-A (Optional, Years Later) Once ALL certs have been re-issued under the Root-B chain (after natural 90-day rotation cycles): 1. Stop including Root-A in new ca-bundle.pem files 2. Remove Root-A from OpenBao trust store 3. Root-A expires naturally (20-year lifetime) **No rush.** Both roots can coexist indefinitely. Root-A handles company infra. Root-B handles product + custom domains. ## Impact Assessment | System | Impact | Action Needed | |--------|--------|---------------| | Company infra | **NONE** | Root-A still valid, certs don't change | | Hub product services | **NONE** | Hub intermediate has two valid chains | | Existing satellites | **NONE** | Current certs valid via Root-A chain | | Existing agents | **NONE** | System CA store has Root-A, certs still verify | | New satellites | Root-B used | ca-bundle.pem includes both roots | | New air-gap bundles | Root-B used | Bundle generator includes both roots | | Custom domains | **ENABLED** | Satellite intermediate issued under Root-B chain | ## ca-bundle.pem During Transition ```pem -----BEGIN CERTIFICATE----- <Root-B cert - unconstrained, new> -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- <Root-A cert - constrained, original> -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- <Hub Intermediate - cross-signed by Root-B> -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- <Satellite Intermediate - issued by Hub Intermediate> -----END CERTIFICATE----- ``` curl/libcurl and browsers try each root until one validates the chain. Including both roots in the bundle ensures backward + forward compatibility. ## Cost | Item | Cost | Time | |------|------|------| | CloudHSM cluster restore | ~$1.50/hr × 2 hrs | 2 hours | | Ceremony (2 custodians) | Staff time | 1 hour | | Cross-signing | $0 (OpenBao CLI) | 5 minutes | | Distribution | $0 (automated) | Gradual | | **Total** | **~$3 + staff time** | **< 1 day** | ## Decision Record - **Why now:** Custom domains for Tier A customers are blocked by root name constraints - **Why cross-sign (not replace):** Zero disruption to company infra and existing products - **Why keep Root-A:** Company infra at `*.arivaran.ai` doesn't need custom domain support - **When to retire Root-A:** After all product certs naturally rotate (3-6 months) ## Revision History | Date | Change | Author | |------|--------|--------| | 2026-03-22 | Initial — cross-sign strategy, ceremony steps, impact assessment | Claire Dubois (Security), Tariq Hassan (Platform) |

This document is part of the Arivaran Twin compliance program. For questions or the latest version, contact compliance@arivaran.ai.

Release-ready. Saved on this browser.