# Certificate Authority Infrastructure Plan ## Overview Build a secure, self-contained Certificate Authority (CA) infrastructure on an isolated Ubuntu machine (`192.168.8.248`) using two YubiKeys for hardware-secured key storage, with a web-based Key Vault UI for certificate management. --- ## Architecture ``` ┌─────────────────────────────────────────────────────┐ │ certauth Machine (192.168.8.248) │ │ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ YubiKey #1 │ │ YubiKey #2 │ │ │ │ Root CA Key │ │ Intermediate │ │ │ │ (PIN+Touch) │ │ CA Key │ │ │ └──────┬───────┘ │ (PIN+Touch) │ │ │ │ └──────┬───────┘ │ │ │ │ │ │ Root Certificate Intermediate Cert │ │ (signed on YK1) (signed by Root) │ │ │ │ │ ┌─────────▼─────────┐ │ │ │ Certificate API │ │ │ │ + Key Vault UI │ │ │ └─────────┬─────────┘ │ │ │ │ │ ┌─────────▼─────────┐ │ │ │ Certificate DB │ │ │ │ (SQLite/Postgres) │ │ │ └───────────────────┘ │ │ │ │ Firewall: Only local network (192.168.8.0/24) │ │ No outbound internet except Ubuntu package updates │ └─────────────────────────────────────────────────────┘ ``` --- ## Phase 1: Machine Hardening ### 1.1 Base System Configuration - Fresh Ubuntu Server installation verification - Create dedicated `certauth` user with sudo privileges - Disable root login, enforce key-based SSH - Configure SSH to only accept connections from local network (192.168.8.0/24) - Set up UFW firewall: - Allow SSH (port 22) from 192.168.8.0/24 only - Allow HTTPS (port 443) for Key Vault UI from 192.168.8.0/24 only - Allow HTTP (port 80) for redirect from 192.168.8.0/24 only - Deny all other inbound traffic - Deny all outbound traffic except: - Ubuntu package repositories (archive.ubuntu.com, security.ubuntu.com) - DNS (port 53) - NTP (port 123) - Local network traffic (192.168.8.0/24) ### 1.2 System Hardening - Automatic security updates enabled - Fail2ban for SSH protection - Auditd for security auditing - Remove unnecessary packages and services - ConfigureAppArmor profiles - Set up encrypted swap - Configure secure kernel parameters (sysctl) ### 1.3 YubiKey Preparation - Install `yubikey-manager`, `pcscd`, `opensc`, `gnutls-bin` - Verify YubiKey connectivity and PIV applet - Test both YubiKeys are recognized --- ## Phase 2: YubiKey #1 - Root CA ### 2.1 YubiKey Configuration - Set PIV PIN (strong, 9-16 chars) - Set PIV PUK (for PIN reset) - Set management key - Configure touch policy to `callback` or `fixed-on` for the signing key slot - Generate RSA 4096-bit (or EC P-384) key pair **on the YubiKey** (never leaves device) - Key stored in PIV slot `9c` (signing) ### 2.2 Root Certificate Generation - Generate self-signed Root CA certificate on YubiKey - Validity: 20-30 years - Key usage: Certificate Signing, CRL Signing - Basic constraints: CA:TRUE, pathlen:1 - Subject: `CN=certauth Root CA, O=Home, C=US` (customizable) - Store Root CA certificate in `/etc/ssl/ca/root/` ### 2.3 Security - Root CA certificate is public and stored on disk - Root private key **never** leaves YubiKey #1 - YubiKey #1 can be physically removed and stored offline when not in use - All signing operations require PIN + physical touch --- ## Phase 3: YubiKey #2 - Intermediate CA ### 3.1 YubiKey Configuration - Set PIV PIN (strong, 9-16 chars, different from YK1) - Set PIV PUK - Set management key - Configure touch policy to `callback` or `fixed-on` for signing key slot - Generate RSA 4096-bit (or EC P-384) key pair **on the YubiKey** - Key stored in PIV slot `9c` (signing) ### 3.2 Intermediate Certificate Generation - Generate CSR on YubiKey #2 - Sign CSR using YubiKey #1 (Root CA) — requires PIN + touch on YK1 - Validity: 10-15 years - Key usage: Certificate Signing, CRL Signing - Basic constraints: CA:TRUE, pathlen:0 - Subject: `CN=certauth Intermediate CA, O=Home, C=US` - Store Intermediate CA certificate in `/etc/ssl/ca/intermediate/` ### 3.3 Security - Intermediate private key **never** leaves YubiKey #2 - All signing operations require PIN + physical touch - Certificate chain: Root CA → Intermediate CA → Leaf Certificates --- ## Phase 4: Certificate Management API & Key Vault UI ### 4.1 Technology Stack - **Backend**: Python FastAPI (lightweight, async, good OpenAPI support) - **Database**: SQLite (simple, file-based, sufficient for this scale) - **Frontend**: HTMX + Tailwind CSS (minimal JS, server-rendered, fast) - **Reverse Proxy**: Caddy (automatic HTTPS, simple config) - **Process Manager**: systemd ### 4.2 API Endpoints ``` Authentication: POST /api/auth/login - Admin login (username + password + TOTP) POST /api/auth/logout - Logout GET /api/auth/verify - Verify API key Domain Management: POST /api/domains - Register a new domain (e.g., *.example.com) GET /api/domains - List all registered domains GET /api/domains/{id} - Get domain details DELETE /api/domains/{id} - Revoke domain registration Certificate Management: POST /api/certs/request - Request a new certificate for a domain GET /api/certs - List all certificates GET /api/certs/{id} - Get certificate details GET /api/certs/{id}/download - Download certificate + chain POST /api/certs/{id}/revoke - Revoke a certificate POST /api/certs/{id}/renew - Renew a certificate Health & Status: GET /api/health - Health check GET /api/yubikeys - YubiKey status (connected, slots) ``` ### 4.3 Key Vault UI Features - Dashboard showing certificate inventory, expiring certs, YubiKey status - Domain registration form with validation - Certificate request workflow: 1. Select registered domain 2. Specify SANs (Subject Alternative Names) 3. Choose validity period 4. Confirm request (triggers signing workflow) - Certificate signing workflow: 1. System generates CSR locally 2. Admin inserts YubiKey #2, enters PIN, touches YubiKey 3. Certificate is signed and stored 4. Certificate + chain available for download - Certificate download page with PEM files - Audit log viewer - Settings page for CA configuration ### 4.4 Signing Workflow (Human-in-the-Loop) Since YubiKey requires physical touch + PIN, the signing process is semi-interactive: ``` 1. Admin requests certificate via UI/API 2. System generates CSR and stores pending request 3. Admin runs: certauth sign --request - This prompts for YubiKey #2 PIN - Admin touches YubiKey #2 when prompted - Certificate is signed by Intermediate CA 4. Signed certificate stored in database 5. Status updated to "issued" 6. Certificate available for download ``` Alternative: Web-based signing using WebAuthn/CTAP2 (future enhancement) ### 4.5 API Key Authentication - Admin generates API keys via UI - API keys are scoped (read-only, sign, admin) - Services authenticate with API key header: `X-API-Key: ` - API keys stored hashed in database --- ## Phase 5: Security Hardening ### 5.1 Application Security - All API endpoints require authentication - Rate limiting on API endpoints - Input validation and sanitization - SQL injection prevention (parameterized queries) - CSRF protection for UI - Content Security Policy headers - Secure cookie flags (HttpOnly, Secure, SameSite) ### 5.2 Data Protection - Database encrypted at rest (LUKS encrypted partition) - Certificate files stored with restricted permissions (root:certauth, 0640) - No secrets in plaintext logs - API keys hashed (bcrypt) - Passwords hashed (bcrypt) ### 5.3 Network Security - Caddy configured with strong TLS settings - Only binds to local network interfaces - No services exposed to internet - Outbound connections restricted by firewall ### 5.4 Operational Security - Audit logging of all certificate operations - Regular backup of certificates and configuration (encrypted) - Monitoring for failed authentication attempts - Log rotation and retention policy --- ## Phase 6: Setup Script ### 6.1 Automated Setup Script (`setup-certauth.sh`) A single script that can provision a fresh Ubuntu machine: - Validates prerequisites (Ubuntu version, YubiKeys present) - Runs all hardening steps - Configures YubiKeys (interactive prompts for PINs) - Generates CA certificates - Installs and configures the Certificate API - Sets up firewall rules - Creates systemd services - Outputs configuration summary and credentials ### 6.2 Configuration File (`certauth.conf`) All configurable values in one file: - CA subject information - Certificate validity periods - Network configuration - Admin credentials - YubiKey PIN policies ### 6.3 Documentation - README with architecture overview - OPERATIONS.md with daily usage instructions - TROUBLESHOOTING.md with common issues - BACKUP.md with backup and restore procedures --- ## Directory Structure ``` certauth/ ├── setup-certauth.sh # Main setup script ├── certauth.conf # Configuration file ├── README.md # Project documentation ├── OPERATIONS.md # Operations guide ├── scripts/ │ ├── harden-system.sh # System hardening │ ├── configure-yubikey.sh # YubiKey setup │ ├── generate-ca.sh # CA certificate generation │ ├── install-api.sh # API installation │ └── configure-firewall.sh # Firewall setup ├── api/ │ ├── main.py # FastAPI application │ ├── models.py # Database models │ ├── auth.py # Authentication │ ├── signing.py # Certificate signing logic │ ├── templates/ # HTML templates │ ├── static/ # Static assets │ └── requirements.txt # Python dependencies ├── systemd/ │ ├── certauth-api.service # API service unit │ └── certauth-sign.timer # Signing timer unit ├── caddy/ │ └── Caddyfile # Caddy configuration ├── ssl/ │ └── openssl.cnf # OpenSSL configuration └── tests/ └── test_api.py # API tests ``` --- ## Implementation Order 1. **Plan Review** — You review and approve this plan 2. **Machine Hardening** — SSH into machine, verify state, apply hardening 3. **YubiKey Setup** — Configure both YubiKeys with Root and Intermediate CAs 4. **API Development** — Build the Certificate Management API and UI 5. **Integration** — Connect API to YubiKeys for signing 6. **Testing** — End-to-end testing of certificate issuance 7. **Setup Script** — Create reproducible setup script 8. **Documentation** — Final documentation and handover --- ## Security Considerations & Trade-offs ### YubiKey Touch Policy - `callback`: Prompts user to touch (most flexible, requires polling) - `fixed-on`: Always requires touch (most secure, slightly slower UX) - **Recommendation**: `fixed-on` for both keys ### Key Algorithm - RSA 4096: Wider compatibility, larger keys/certs - EC P-384: Smaller, faster, modern - **Recommendation**: RSA 4096 for maximum compatibility with all services/browsers ### Signing Workflow - Fully automated signing is **not possible** with YubiKey touch requirement - Admin must be present to touch YubiKey and enter PIN - This is a **feature**, not a limitation — it provides human-in-the-loop security - For bulk operations, a CLI tool handles batch signing requests ### Offline Root CA - YubiKey #1 (Root) can be removed after Intermediate CA is created - Root is only needed if Intermediate CA key is compromised - This provides true offline root CA capability --- ## Questions for Confirmation 1. **Key algorithm**: RSA 4096 vs EC P-384? (RSA 4096 recommended for compatibility) 2. **Certificate validity**: Root: 25 years, Intermediate: 15 years, Leaf: configurable per-request? 3. **TOTP for admin login**: Enable two-factor authentication? 4. **Backup strategy**: Encrypted backups to local disk only, or also to network share? 5. **Additional domains**: Any specific domains to pre-register beyond `*.example.com`? 6. **CRL/OCSP**: Do we need Certificate Revocation List or OCSP responder? (Adds complexity) 7. **Admin username**: Should the admin account be `certauth` or a different username?