====== Runbook: Renew Certificate ====== **Duration:** ~15 minutes \\ **Role:** PKI Operator \\ **Trigger:** Expiry warning (30/14/7 days) ---- ===== Workflow ===== flowchart TD A[Expiry warning] --> B{Key compromised?} B -->|Yes| C[-> Revocation Runbook] B -->|No| D{Same key pair?} D -->|Yes| E[Re-Certification] D -->|No| F[Re-Key] E --> G[New certificate] F --> H[New CSR] H --> G G --> I[Archive old certificate] I --> J[Deploy new certificate] J --> K[Update monitoring] style B fill:#ffebee style G fill:#e8f5e9 style J fill:#e3f2fd ---- ===== Step 1: Identify Expiring Certificates ===== # All certificates expiring in < 30 days find /etc/ssl/certs -name "*.pem" -exec sh -c ' enddate=$(openssl x509 -enddate -noout -in "$1" 2>/dev/null | cut -d= -f2) if [ -n "$enddate" ]; then expiry=$(date -d "$enddate" +%s 2>/dev/null) now=$(date +%s) days=$(( (expiry - now) / 86400 )) if [ "$days" -lt 30 ]; then echo "$1: $days days" fi fi ' _ {} \; # PowerShell: Find expiring certificates Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.NotAfter -lt (Get-Date).AddDays(30) } | Select-Object Subject, NotAfter, Thumbprint ---- ===== Step 2: Choose Renewal Method ===== | Method | When to use | Advantage | |--------|-------------|-----------| | **Re-Certification** | Key secure, no changes | Fast, no re-deploy | | **Re-Key** | New key length, policy change | Increased security | | **Replace** | New algorithm (-> PQ) | Future-proof | ---- ===== Step 3a: Re-Certification (Same Key Pair) ===== # Generate CSR from existing certificate + key openssl x509 -x509toreq -in old_cert.pem -signkey private.key -out renew.csr # Issue new certificate openssl ca -config openssl.cnf \ -extensions server_cert \ -in renew.csr \ -out renewed_cert.pem \ -days 365 \ -notext ---- ===== Step 3b: Re-Key (New Key Pair) ===== # Generate new key (EC P-384) openssl ecparam -genkey -name secp384r1 -out new_private.key # New CSR with same subject openssl req -new -key new_private.key -out rekey.csr \ -subj "$(openssl x509 -in old_cert.pem -subject -noout | sed 's/subject=//')" # Issue certificate openssl ca -config openssl.cnf \ -extensions server_cert \ -in rekey.csr \ -out rekeyed_cert.pem \ -days 365 ---- ===== Step 3c: Replace (Upgrade to Hybrid/PQ) ===== // Migration to Hybrid mode using var oldCert = new X509Certificate2("old_cert.pfx", "password"); // New key pair (ML-DSA-65 for Hybrid) using var mlDsa = MlDsaSigner.Create(MlDsaParameterSet.MlDsa65); using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP384); var request = new CertificateRequest( oldCert.SubjectName, ecdsa, HashAlgorithmName.SHA384); // Transfer extensions foreach (var ext in oldCert.Extensions) request.CertificateExtensions.Add(ext); // Create hybrid certificate var newCert = request.CreateSelfSigned( DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(365), CryptoMode.Hybrid); ---- ===== Step 4: Archive Old Certificate ===== # Archive with metadata ARCHIVE_DIR="/var/archive/certs/$(date +%Y)" mkdir -p "$ARCHIVE_DIR" # Certificate + metadata cp old_cert.pem "$ARCHIVE_DIR/$(openssl x509 -serial -noout -in old_cert.pem | cut -d= -f2).pem" # Archive log echo "$(date -Iseconds) RENEWED $(openssl x509 -serial -noout -in old_cert.pem)" >> /var/log/cert-archive.log ---- ===== Step 5: Deployment ===== | System | Deployment method | Restart required | |--------|-------------------|------------------| | Apache | ''cp cert.pem /etc/ssl/; systemctl reload apache2'' | No | | Nginx | ''cp cert.pem /etc/nginx/ssl/; nginx -s reload'' | No | | IIS | ''Import-PfxCertificate; netsh http update'' | No | | Kubernetes | ''kubectl create secret tls'' | Pod restart | # Apache/Nginx Reload systemctl reload apache2 # or nginx -s reload # Test connection openssl s_client -connect server.example.com:443 -brief ---- ===== Step 6: Update Monitoring ===== # Enter new fingerprint in monitoring NEW_FP=$(openssl x509 -fingerprint -sha256 -noout -in renewed_cert.pem | cut -d= -f2) echo "New fingerprint: $NEW_FP" # Update Prometheus alert (if fingerprint-based) # Expiry date in monitoring should update automatically ---- ===== Checklist After Renewal ===== | # | Checkpoint | Command | Done | |---|------------|---------|------| | 1 | New certificate active | ''openssl s_client -connect host:443'' | | | 2 | Chain complete | ''openssl verify -CAfile chain.pem cert.pem'' | | | 3 | Old certificate archived | ''ls /var/archive/certs/'' | | | 4 | Ticket closed | Ticket system | | | 5 | Monitoring updated | Check dashboard | | ---- ===== Troubleshooting ===== | Problem | Cause | Solution | |---------|-------|----------| | ''certificate has expired'' | Forgot reload | Restart service | | ''certificate chain incomplete'' | Intermediate missing | ''cat cert.pem intermediate.pem > fullchain.pem'' | | ''hostname mismatch'' | SAN not updated | CSR with correct SANs | | Client doesn't trust | CA not in store | Distribute CA certificate | ---- ===== Related Runbooks ===== * [[.:zertifikat-ausstellen|Issue Certificate]] - New certificates * [[.:zertifikat-widerrufen|Revoke Certificate]] - On compromise * [[..:automatisierung:scheduled-renewal|Automatic Renewal]] - Automation ---- << [[.:zertifikat-ausstellen|<- Issue Certificate]] | [[.:zertifikat-widerrufen|-> Revoke Certificate]] >> ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional// {{tag>runbook certificate renewal operator}}