# PCI-DSS 4.0 Compliance Mapping This guide maps certctl's existing capabilities to PCI-DSS 4.0 requirements relevant to TLS certificate and cryptographic key management. It is **not a compliance attestation** — a qualified security assessor (QSA) must evaluate your organization's complete control environment. Rather, this document helps you understand which PCI-DSS control objectives certctl supports and where operator responsibility lies. Organizations subject to PCI-DSS typically need to demonstrate control over certificate issuance, renewal, rotation, revocation, and key management. Certctl automates the technical controls for certificate lifecycle; compliance depends on how you deploy, monitor, and audit it. ## Contents 1. [How to Use This Guide](#how-to-use-this-guide) 2. [Requirement 4: Protect Data in Transit](#requirement-4-protect-data-in-transit) - [4.2.1 — Strong Cryptography for Transmission](#421--strong-cryptography-for-transmission) - [4.2.2 — Certificate Inventory and Validation](#422--certificate-inventory-and-validation) 3. [Requirement 3: Protect Stored Cardholder Data (Key Management)](#requirement-3-protect-stored-cardholder-data-key-management) - [3.6 — Cryptographic Key Documentation](#36--cryptographic-key-documentation) - [3.7 — Key Lifecycle Procedures](#37--key-lifecycle-procedures) 4. [Requirement 8: Identify and Authenticate](#requirement-8-identify-and-authenticate) - [8.3 — Strong Authentication](#83--strong-authentication) - [8.6 — Application Account Management](#86--application-account-management) 5. [Requirement 10: Log and Monitor](#requirement-10-log-and-monitor) - [10.2 — Implement Automated Audit Logging](#102--implement-automated-audit-logging) - [10.3 — Protect Audit Trail](#103--protect-audit-trail) - [10.4 — Promptly Review and Address Audit Trail Exceptions](#104--promptly-review-and-address-audit-trail-exceptions) - [10.7 — Retain and Protect Audit Trail History](#107--retain-and-protect-audit-trail-history) 6. [Requirement 6: Develop and Maintain Secure Systems and Applications](#requirement-6-develop-and-maintain-secure-systems-and-applications) - [6.3.1 — Security Coding Practices](#631--security-coding-practices) - [6.5.10 — Broken Authentication and Cryptography Prevention](#6510--broken-authentication-and-cryptography-prevention) 7. [Requirement 7: Restrict Access by Business Need-to-Know](#requirement-7-restrict-access-by-business-need-to-know) - [7.2 — Implement Access Control](#72--implement-access-control) 8. [Evidence Summary Table](#evidence-summary-table) 9. [Operator Responsibilities](#operator-responsibilities) 10. [V3 Enhancements for PCI-DSS](#v3-enhancements-for-pci-dss) 11. [Next Steps for Compliance](#next-steps-for-compliance) 12. [Questions?](#questions) ## How to Use This Guide Your QSA will request evidence that your certificate and key management systems meet specific PCI-DSS 4.0 requirements. For each applicable requirement, this guide identifies: 1. **Which certctl features support the control** — API endpoints, database tables, background processes 2. **What evidence you can produce** — audit logs, dashboard metrics, API queries, deployment configs 3. **Operator responsibilities** — what you must do outside certctl (policy, monitoring, access control) 4. **Status** — Available (v1.0 shipped), Planned (future release), or Operator Responsibility (outside scope) --- ## Requirement 4: Protect Data in Transit **Objective**: Ensure strong cryptography is used to protect sensitive data during transmission. ### 4.2.1 — Strong Cryptography for Transmission **Requirement**: Use appropriate and current cryptographic algorithms for all TLS and SSH connections protecting card data in transit. **certctl Support**: - **Automated TLS certificate lifecycle** — Certctl issues TLS certificates to NGINX, Apache HAProxy targets via `POST /api/v1/deployments`. Certificates include RSA 2048-bit and ECDSA P-256 key types (configurable per profile, M11a). - **Control plane TLS enforcement** — All REST API endpoints served exclusively over HTTPS. Agent-to-server heartbeat and work polling use TLS. No plaintext protocol options. - **Issuer connector key negotiation** — ACME v2 (Let's Encrypt, ZeroSSL) validates issuer cryptography. Local CA enforces RSA/ECDSA constraints. step-ca integration ensures Smallstep's cryptography standards. - **Certificate profiles** (M11a) document allowed key types and minimum key sizes per environment (development, production, cardholder-network). **Evidence You Can Provide**: - Exported certificate inventory via `GET /api/v1/certificates` with key algorithm and size (serial JSON). - Issued certificate details showing RSA 2048+ or ECDSA P-256 for all deployed certificates. - Audit trail (`GET /api/v1/audit`) showing issuer connector selection and certificate profile assignment per certificate. - Target deployment logs showing TLS certificate installation on NGINX/Apache/HAProxy. **Operator Responsibility**: - Configure certificate profiles for your environments with approved key algorithms. - Audit cipher suite configuration on deployed targets (certctl deploys certs; you verify target TLS settings). - Periodically review `CERTCTL_KEYGEN_MODE` — must be `agent` in production (never `server`). - Monitor issuer connector configuration to ensure issuers meet your cryptography standards. **Status**: **Available** (v1.0 shipped) --- ### 4.2.2 — Certificate Inventory and Validation **Requirement**: Ensure all TLS/SSL certificates used for data transmission are valid, current, and meet required cryptographic standards. **certctl Support**: - **Managed Certificate Inventory** — Full CRUD API (`/api/v1/certificates`) with sortable, filterable list. Fields: common name, SANs, subject, issuer, serial number, key type/size, not-before/after dates, issuer ID, profile ID, owner, team, status (Active/Expiring/Expired/Revoked). - **Filesystem Certificate Discovery** (M18b) — Agents scan configured directories (`CERTCTL_DISCOVERY_DIRS` env var) for existing PEM/DER certificates every 6 hours and on startup. Control plane deduplicates by SHA-256 fingerprint. Three triage statuses: Unmanaged (not managed by certctl), Managed (linked to a managed certificate), Dismissed (operator-marked as out-of-scope). - API endpoints: - `GET /api/v1/discovered-certificates?status=Unmanaged` — find orphaned certs - `GET /api/v1/discovery-summary` — aggregate counts by status - `POST /api/v1/discovered-certificates/{id}/claim` — link to managed certificate - `POST /api/v1/discovered-certificates/{id}/dismiss` — mark out-of-scope - **Expiration Threshold Alerting** — Renewal policies support `alert_thresholds_days` (default 30, 14, 7, 0). Background scheduler evaluates daily; certificates transition to Expiring/Expired status automatically. Notifications sent to owners via email/webhook/Slack/Teams/PagerDuty. - **Certificate Status Tracking** — Four statuses: Active (deployed, not yet expired), Expiring (within threshold, awaiting renewal), Expired (past not-after date), Revoked (revoked via RFC 5280 revocation API). Dashboard charts show status distribution. - **Revocation Infrastructure** (M15a, M15b): - CRL endpoint: `GET /api/v1/crl` (JSON format) or `GET /api/v1/crl/{issuer_id}` (DER X.509 CRL, 24h validity, signed by issuing CA) - OCSP responder: `GET /api/v1/ocsp/{issuer_id}/{serial}` (returns DER-encoded OCSP response: good/revoked/unknown) - Short-lived cert exemption: certs with TTL < 1 hour skip CRL/OCSP (expiry is sufficient revocation) - **Stats API** (M14) — Real-time visibility: - `GET /api/v1/stats/summary` — total certs, by status, by issuer - `GET /api/v1/stats/expiration-timeline?days=90` — expiration distribution (weekly buckets) - `GET /api/v1/stats/job-trends?days=30` — renewal/issuance job success rates - `GET /api/v1/certificates` with `?sort=-notAfter&fields=id,commonName,notAfter,status` — sparse, sorted inventory **Evidence You Can Provide**: - Discovered certificate report: `GET /api/v1/discovered-certificates` JSON export showing all certs on systems, fingerprints, and status. - Managed certificate inventory: `GET /api/v1/certificates` with filters (`?status=Expiring` for upcoming renewals). - Expiration alert configuration: policy JSON showing `alert_thresholds_days` for each environment. - CRL/OCSP availability proof: HTTP GET requests to `/api/v1/crl` and `/api/v1/ocsp/{issuer}/{serial}` with signed responses. - Audit trail for certificate creation/renewal/revocation: `GET /api/v1/audit?type=certificate_issued,certificate_renewed,certificate_revoked`. - Dashboard charts showing expiration timeline, renewal success trends, status distribution. **Operator Responsibility**: - Configure `CERTCTL_DISCOVERY_DIRS` on agents to scan all certificate storage locations (e.g., `/etc/nginx/certs`, `/etc/apache2/certs`, `/usr/local/share/ca-certificates`). - Regularly triage discovered certificates: `GET /api/v1/discovered-certificates?status=Unmanaged`, claim or dismiss each. - Set renewal policies for all certificate profiles with appropriate `alert_thresholds_days` (recommendation: 30, 14, 7, 0). - Monitor expiration dashboard and respond to Expiring alerts before certificates expire. - Verify that issued certificates meet your organization's cryptography standards (key type, key size, SANs). - Test CRL/OCSP endpoints periodically to confirm they are reachable and signed correctly. **Status**: **Available** (v1.0 shipped, discovery M18b, revocation M15a/M15b) --- ## Requirement 3: Protect Stored Cardholder Data (Key Management) **Objective**: Render cardholder data unreadable anywhere it is stored; protect cryptographic keys used to encrypt data. ### 3.6 — Cryptographic Key Documentation **Requirement**: Document and implement all key management processes and procedures covering generation, storage, archival, destruction, and change; protect cryptographic keys; and restrict access to keys to the minimum required. **certctl Support**: - **Certificate Profile Documentation** (M11a) — Named profiles define allowed key types, maximum TTL, and allowed EKUs per use case. Each profile is a documented policy: ```json { "id": "p-web-tls", "name": "Web TLS Production", "allowed_key_types": ["RSA_2048", "ECDSA_P256"], "max_ttl_seconds": 31536000, "require_sans": true, "description": "Production TLS certs for external web services" } ``` - **Owner and Team Tracking** (M11b) — Every certificate is assigned an owner (person + email) and optionally a team. This documents key responsibility and escalation paths. - **Issuer Connector Specification** — Configuration and API endpoints document which CA and protocol issues each certificate: - `GET /api/v1/issuers/{id}` returns issuer type (local-ca, acme, step-ca, openssl), CA endpoint, authentication method, constraints - Each issuer type has documented key handling (e.g., Local CA loads CA key from `CERTCTL_CA_CERT_PATH`, step-ca via JWK provisioner) - **Immutable Audit Trail** (M19) — Every certificate lifecycle event recorded in append-only `audit_events` table: - `certificate_issued` — when certificate created, by whom, issuer type, profile - `certificate_renewed` — when renewed, by whom, issuer - `certificate_revoked` — when revoked, by whom, RFC 5280 reason code - `certificate_deployed` — when deployed to target, by agent, target type - Query: `GET /api/v1/audit?resource_type=certificate&resource_id={cert_id}` **Evidence You Can Provide**: - Exported certificate profiles: `GET /api/v1/profiles` showing documented key types, max TTLs, constraints per environment. - Certificate-to-owner mapping: `GET /api/v1/certificates` with owner/team fields. - Issuer configuration audit: `GET /api/v1/issuers` showing CA endpoints, key storage paths, auth methods. - Audit trail for a certificate: `GET /api/v1/audit?resource_type=certificate&resource_id={cert_id}` showing complete lifecycle. **Operator Responsibility**: - Define and document certificate profiles for each environment and use case. - Assign owner and team to each certificate via API or dashboard. - Document issuer connector configuration (CA endpoint, auth method, key storage location). - Maintain baseline audit trail exports for compliance evidence. - Establish certificate retirement policy (how long to retain audit records after certificate expiry/revocation). **Status**: **Available** (v1.0 shipped) --- ### 3.7 — Key Lifecycle Procedures **Requirement**: Generate, store, protect, access, and destroy cryptographic keys used to encrypt data in transit or at rest. This requirement covers key generation, storage, rotation, and destruction. Certctl addresses the certificate/TLS key portion (not symmetric encryption keys used for cardholder data at rest — those are outside scope). #### 3.7.1 — Key Generation **Requirement**: Generate new keys using strong cryptography. **certctl Support**: - **Agent-Side Key Generation** (M8) — Production mode (default `CERTCTL_KEYGEN_MODE=agent`): - Agents generate ECDSA P-256 key pairs using `crypto/ecdsa` + `crypto/elliptic.P256()` + `crypto/rand` (cryptographically secure random). - Key generation happens **only on the agent**, never on the control plane. - Agent submits Certificate Signing Request (CSR) with public key to control plane via `POST /api/v1/agents/{id}/csr`. - Issued certificate is returned; private key remains on agent at `CERTCTL_KEY_DIR` (default `/var/lib/certctl/keys`). - **Server-Side Fallback** (demo/development only) — `CERTCTL_KEYGEN_MODE=server`: - Control plane generates RSA 2048-bit or ECDSA P-256 keys using `crypto/rand` + `crypto/rsa`. - Server signs CSR and stores the private key in the certificate version record for agent deployment. **Security note:** In server keygen mode, the control plane holds private keys — this is why agent keygen mode is the recommended default for production. - **Must not be used in production.** Explicit warning logged: `server-side key generation enabled (CERTCTL_KEYGEN_MODE=server) — private keys touch control plane, demo only` - **Issuer-Specific Key Negotiation**: - **ACME (Let's Encrypt, ZeroSSL)**: Let's Encrypt controls key types; certctl requests ECDSA P-256 by default. - **Local CA**: Supports RSA 2048+, ECDSA (P-256, P-384), PKCS#8 format. Key algorithm inherited from CA cert or specified via profile. - **step-ca**: Smallstep's provisioner defines key type; certctl respects server constraints. - **OpenSSL / Custom CA**: User-provided signing script; key type depends on CA backend. **Evidence You Can Provide**: - Deployment configuration: `CERTCTL_KEYGEN_MODE=agent` in production (verify in `docker-compose.yml`, Kubernetes manifests, or systemd units). - Agent log excerpt showing key generation: Go `crypto/ecdsa.GenerateKey(elliptic.P256())` via agent process logs with CSR submission timestamp. - Certificate CSR audit: `GET /api/v1/audit?type=certificate_issued` showing CSR fingerprint (SHA-256 hash of CSR PEM). - Renewal job logs showing agent-submitted CSR, not server-generated key. **Operator Responsibility**: - **Enforce `CERTCTL_KEYGEN_MODE=agent` in all production deployments.** Never use `server` mode outside demos. - Verify agent hardware is adequately isolated (crypto/rand relies on OS `/dev/urandom` quality). - Monitor `CERTCTL_KEY_DIR` on agents for unauthorized file access (use OS-level file audit if available). - Backup agent key directory (`/var/lib/certctl/keys`) as part of disaster recovery procedure. **Status**: **Available** (v1.0 shipped) #### 3.7.2 — Key Storage and Access Control **Requirement**: Restrict cryptographic key access to the minimum required and protect keys from unauthorized access. **certctl Support**: - **Agent-Side Key Storage** (M8) — Private keys written to `CERTCTL_KEY_DIR` (default `/var/lib/certctl/keys`): - File permissions: `0600` (readable/writable by agent process owner only). - Filename convention: one file per certificate (e.g., `web-tls-prod.key`, `api-service.key`). - No key data passed over the network between agent and control plane (CSR only). - Keys used locally by agent to sign TLS handshakes, never transmitted to control plane or other systems. - **Control Plane Key Storage** — Sensitive credentials managed via environment variables or `.env` files: - CA private key path: `CERTCTL_CA_CERT_PATH` + `CERTCTL_CA_KEY_PATH` (for Local CA sub-CA mode). - ACME account key: embedded in ACME issuer config (not stored separately; ACME library handles in memory). - step-ca provisioner key: `CERTCTL_STEPCA_KEY_PATH` env var (path to JWK private key file, loaded into memory during runtime). - API keys: `CERTCTL_API_KEY` (SHA-256 hashed in database, plaintext never stored). - Database credentials: `CERTCTL_DATABASE_URL` in `.env` file, not in source code. - **Docker Compose Credential Management** — `.env` file (git-ignored) holds all secrets: ```bash CERTCTL_API_KEY=sk-test-... CERTCTL_DATABASE_URL=postgres://user:pass@db:5432/certctl CERTCTL_CA_KEY_PATH=/run/secrets/ca.key ``` Credentials never in `docker-compose.yml` or Dockerfile. - **Kubernetes Secrets** (operator responsibility) — Deploy control plane with: ```yaml env: - name: CERTCTL_DATABASE_URL valueFrom: secretKeyRef: name: certctl-secrets key: database-url - name: CERTCTL_API_KEY valueFrom: secretKeyRef: name: certctl-secrets key: api-key ``` **Evidence You Can Provide**: - Agent key directory listing (without keys): `ls -la /var/lib/certctl/keys` (shows file count, permissions, timestamps). - Deployment manifest (`docker-compose.yml` or Kubernetes YAML) showing secrets via env var or Secret object (not inline). - `.env` file (do not share contents, only confirm existence and git-ignore status). - API key hash verification: `GET /api/v1/auth/check` with API key, verifying hash matching without plaintext exposure. **Operator Responsibility**: - **Store `.env` and credential files outside version control.** Verify `.gitignore` includes `.env`, `*.key`, `ca.key`, etc. - **Restrict file system access to `/var/lib/certctl/keys` on agents** via OS-level permissions (Linux: `chmod 0700`, owned by agent user). - **Limit CA key file read access** — `CERTCTL_CA_KEY_PATH` should be readable only by certctl server process (OS permissions). - **Rotate API keys periodically** (recommendation: annually or when personnel changes). No audit trail for API key rotation (outside certctl scope). - **Backup private key stores** (agent key dirs, CA key file) as part of disaster recovery. Encrypt backups at rest. - **Monitor access logs** to `/var/lib/certctl/keys` and CA key file location (use OS audit or file integrity monitoring). **Status**: **Available** (v1.0 shipped) #### 3.7.3 — Key Rotation **Requirement**: Rotate cryptographic keys upon expiration or compromise. **certctl Support**: - **Automated Certificate Renewal** — Renewal policies trigger certificate renewal automatically: - Background scheduler checks every 60 minutes (configurable via `CERTCTL_SCHEDULER_RENEWAL_CHECK_INTERVAL`). - For each policy, evaluates all managed certificates: if `(not-after - now) <= policy.renewal_threshold_days`, trigger renewal. - Renewal job created in AwaitingCSR state; agent receives work, generates new key pair, submits new CSR. - Issuer connector signs new CSR with new key; old key discarded by agent after new certificate installed. - New certificate deployed to target via deployment job. - **Expiration-Based Rotation** — Certificate profiles (M11a) define `max_ttl_seconds` (e.g., 31536000 for 1 year, 3600 for short-lived certs): - Short-lived certificates (TTL < 1 hour) rotate every deployment cycle, providing defense-in-depth (RFC 5280 revocation not needed). - Longer-lived certs (90/180/365 days) rotated via renewal policy thresholds (30/14/7 day alerts). - **Renewal Audit Trail** — Every renewal recorded: - `GET /api/v1/audit?type=certificate_renewed&resource_id={cert_id}` shows each renewal, old serial, new serial, issuer, actor. **Evidence You Can Provide**: - Renewal policy configuration: `GET /api/v1/policies` showing `renewal_threshold_days` and `alert_thresholds_days`. - Renewal job history: `GET /api/v1/jobs?type=Renewal&status=Completed` with timestamp, before/after serial numbers. - Certificate version history: `GET /api/v1/certificates/{id}/versions` showing all issued versions, dates, issuers. - Audit trail: `GET /api/v1/audit?type=certificate_renewed` for trending and compliance reporting. **Operator Responsibility**: - **Define renewal policies for all certificate profiles** with appropriate thresholds (typically 30 days before expiration for 90+ day certs, more aggressive for shorter-lived). - **Monitor renewal job success** via dashboard (M14 charts show renewal success trends) and alerts. - **Investigate renewal failures** (stuck AwaitingCSR, issuer connectivity, deployment errors) promptly to avoid expired certificates. - **Test renewal workflow in staging environment** before rolling out to production. - **Document key rotation schedule** for your organization (renewal policy thresholds, approval workflows if AwaitingApproval). **Status**: **Available** (v1.0 shipped) #### 3.7.4 — Key Destruction **Requirement**: Render cryptographic keys unreadable and unusable when they reach the end of their cryptographic lifetime. **certctl Support**: - **Certificate Revocation API** (M15a) — `POST /api/v1/certificates/{id}/revoke` with RFC 5280 reason codes: - `unspecified` — general revocation - `keyCompromise` — suspected key compromise - `caCompromise` — CA compromise - `affiliationChanged`, `superseded`, `cessationOfOperation`, `certificateHold`, `privilegeWithdrawn` — lifecycle management - Revocation recorded in `certificate_revocations` table with timestamp and reason. - Issuer notified (best-effort; ACME lacks standard revocation, Local CA skips issuer step). - Revocation notifications sent to owner via email/webhook/Slack/Teams/PagerDuty. - **CRL and OCSP Publication** (M15b) — Revoked certificates published in: - CRL: `GET /api/v1/crl` (JSON format) or `GET /api/v1/crl/{issuer_id}` (DER X.509, signed by CA, 24h validity) - OCSP: `GET /api/v1/ocsp/{issuer_id}/{serial}` (returns revoked status for clients validating certificate chain) - Clients checking certificate status via OCSP or CRL see revoked status within 24 hours. - **Private Key Destruction on Agent** — When certificate renewed or revoked: - Agent removes old private key file from `CERTCTL_KEY_DIR` when new certificate deployed. - Job status tracking confirms old key is no longer needed. - No audit trail of key deletion (private keys don't pass through control plane). **Evidence You Can Provide**: - Revocation requests: `GET /api/v1/audit?type=certificate_revoked` with RFC 5280 reason codes. - CRL publication: HTTP GET `/api/v1/crl` and parse JSON to show revoked serial numbers and timestamps. - OCSP responder validation: Query `GET /api/v1/ocsp/{issuer}/{serial}` for a known-revoked cert; response includes `revoked` status. - Audit trail: Certificate status transitions (Active → Revoked) recorded in `audit_events`. **Operator Responsibility**: - **Revoke certificates immediately upon key compromise suspicion** using reason code `keyCompromise`. - **Revoke certificates at end of lifecycle** (host decommissioning, service sunset) using reason code `cessationOfOperation`. - **Monitor CRL/OCSP availability** — ensure clients can check revocation status (test with TLS validator tools). - **Establish certificate revocation procedure** (who can revoke, approval workflow if required, documentation). - **Physically destroy backup private keys** (if offline backups are kept) when certificate is revoked or after archival period expires. - **Test revocation workflow in staging** — issue test cert, revoke, verify OCSP/CRL reflects revocation within SLA. **Status**: **Available** (v1.0 shipped) --- ## Requirement 8: Identify and Authenticate **Objective**: Limit access to system components and cardholder data by business need-to-know, and authenticate and manage all access. ### 8.3 — Strong Authentication **Requirement**: Authentication mechanisms must use strong cryptography and render authentication credentials (passwords, passphrases, keys) unreadable during transmission and storage. **certctl Support**: - **API Key Authentication** — All REST API endpoints require authentication (default): - Bearer token format: `Authorization: Bearer sk-...` - Key stored as SHA-256 hash in database (plaintext never persisted). - Comparison uses `crypto/subtle.ConstantTimeCompare` to prevent timing attacks. - Configuration: `CERTCTL_AUTH_TYPE=api-key` (enforced by default, no opt-out without explicit env var). - **GUI Authentication Context** — Web dashboard login flow: - Login page (`/login`) accepts API key entry. - AuthProvider context stores API key in session (localStorage in browser, sent in Authorization header for all API calls). - 401 Unauthorized responses trigger automatic redirect to login. - Logout button clears session. - No session server-side (stateless API). - **Credential Transmission** — All API traffic over TLS: - HTTPS enforced at server level (no plaintext HTTP). - API key transmitted in Authorization header (not URL parameter, not cookie). - Browser to server: TLS. - Agent to server: TLS. - No credential logging (API key hash only, never plaintext). **Evidence You Can Provide**: - API configuration: `CERTCTL_AUTH_TYPE=api-key` in deployment manifest. - Database schema: `api_keys` table showing SHA-256 hash column, not plaintext. - API audit log: `GET /api/v1/audit?action=api_call` showing Bearer token validation (no plaintext keys logged). - TLS certificate on control plane: `openssl s_client -connect {server}:8443` showing valid certificate, TLS 1.2+, strong cipher. - GUI login flow: browser network tab showing Authorization header (token value redacted in compliance report). **Operator Responsibility**: - **Issue API keys to users/systems** requiring API access (outside certctl; you maintain key registry). - **Rotate API keys using zero-downtime rotation** — `CERTCTL_AUTH_SECRET` supports comma-separated keys (e.g., `new-key,old-key`). Add the new key, migrate clients, then remove the old key. Recommendation: rotate at least annually, or immediately when personnel changes. - **Revoke API keys immediately** when user leaves or token is compromised (set `enabled=false` in API key management — not yet implemented in v1, owner must track manually). - **Enforce strong TLS** on control plane: TLS 1.2+, modern ciphers (configure on reverse proxy or `CERTCTL_TLS_*` env vars if operator-controlled). - **Protect `.env` and credential files** where API key is defined (restrict file system access, no version control). - **Monitor API audit trail** for suspicious access patterns (many 401 errors, access from unexpected IPs, etc.). **Status**: **Available** (v1.0 shipped) ### 8.6 — Application Account Management **Requirement**: Users' system access must be restricted to the minimum level of application functions or data needed to perform duties. Application accounts (non-human) must use strong authentication. **certctl Support**: - **No Application Account Management in v1** — Certctl does not manage user accounts (no user directory, LDAP, OIDC). - All authentication via API key (service-to-service or human user with API key). - No per-user roles or permissions (that's V3 RBAC feature). - Single API key shared across team or one key per automation script (operator's responsibility to manage). - **Credentials Not in Source Code** — Security hardening: - API keys via `CERTCTL_API_KEY` env var (not in `main.go`, Dockerfile, `docker-compose.yml`). - Database credentials via `CERTCTL_DATABASE_URL` in `.env` (git-ignored). - CA private key path via `CERTCTL_CA_CERT_PATH`/`CERTCTL_CA_KEY_PATH` (not inline). - **Service Account Isolation** (planned for V3) — Future RBAC will support: - Automation script API keys with scoped permissions (e.g., read-only, renew-only, deploy-only). - OIDC/SSO for human users with fine-grained role assignment (admin, operator, viewer). - Audit trail showing which account/role performed each action. **Evidence You Can Provide**: - Deployment manifest (Dockerfile, docker-compose.yml) showing no hardcoded API keys, database credentials, or CA key paths. - `.env` file existence (confirm via CI or compliance check, without sharing contents). - `.gitignore` configuration showing `.env`, `*.key`, secrets excluded. - Code review: grep `main.go`, `config.go` for `CERTCTL_API_KEY` — should only see env var reference, not hardcoded values. **Operator Responsibility**: - **Manage API keys externally** (issue, rotate, revoke). - **Document who/what has API key access** (automation scripts, team members, third-party integrations). - **Rotate application credentials** (API keys, database passwords) according to your organization's policy. - **Segregate credentials** — one API key per automation script where possible, or use V3 RBAC scoping. - **Monitor application account usage** via audit trail — `GET /api/v1/audit` filtered by action/actor. **Status**: **Available in part** (v1.0: credentials out of source code). **Planned V3**: scoped API keys and RBAC. --- ## Requirement 10: Log and Monitor **Objective**: Log and monitor access to network resources and cardholder data. ### 10.2 — Implement Automated Audit Logging **Requirement**: Automatically log and monitor all access to system components and records containing cardholder data. **certctl Support**: - **Immutable API Audit Log** (M19) — Middleware captures every API call: - `audit_events` table (append-only, no UPDATE/DELETE): - `method`: HTTP method (GET, POST, PUT, DELETE) - `path`: API endpoint path only, excluding query parameters (e.g., `/api/v1/certificates` — query strings intentionally omitted to prevent sensitive data persistence in the append-only audit trail) - `actor`: authenticated user/service (extracted from API key or context) - `body_hash`: SHA-256 hash of request body (truncated to 16 chars, first 8 chars shown in logs) - `status_code`: HTTP response status (200, 201, 400, 401, 404, 500, etc.) - `latency_ms`: request duration in milliseconds - `timestamp`: RFC 3339 timestamp - **Certificate Lifecycle Events** — Higher-level events logged separately: - `certificate_issued` — new certificate created, issuer, profile, profile ID - `certificate_renewed` — certificate renewed, old/new serial, renewal policy - `certificate_revoked` — certificate revoked, RFC 5280 reason code - `certificate_deployed` — certificate deployed to target, agent, target type - `certificate_validated` — validation job result (success/failure reason) - **Job Lifecycle Events** — Job status transitions: - `job_created` — renewal/issuance/deployment/validation job created - `job_status_updated` — job state change (Pending → AwaitingCSR → Running → Completed/Failed) - **Policy and Configuration Events** — Administrative changes: - `policy_created`, `policy_updated`, `policy_deleted` — renewal policy changes - `profile_created`, `profile_updated`, `profile_deleted` — certificate profile changes - `issuer_created`, `issuer_deleted` — CA connector registration changes - **Excluded Paths** — Health/readiness probes not logged to reduce noise: - `GET /health` (excluded by default) - `GET /ready` (excluded by default) - Configurable via `CERTCTL_AUDIT_EXCLUDE_PATHS` env var **Evidence You Can Provide**: - Audit trail export: `GET /api/v1/audit` or manual database query, showing sample events with timestamp, actor, action, resource. - API call audit log: Query `audit_events` table showing method, path, actor, status code for last 24-48 hours. - Configuration changes: `GET /api/v1/audit?type=policy_created,policy_updated,issuer_created` showing who changed what and when. - Certificate lifecycle: `GET /api/v1/audit?resource_type=certificate&resource_id={cert_id}` showing complete issuance → deployment → renewal/revocation history. **Operator Responsibility**: - **Enable audit logging** — it's on by default; verify `CERTCTL_AUDIT_EXCLUDE_PATHS` is not set to exclude certificate-related paths. - **Monitor audit log growth** — `audit_events` table will grow with every API call. Recommend database maintenance (log rotation policy, archival after 90 days, etc.). - **Export and archive audit logs** — periodically `SELECT * FROM audit_events WHERE timestamp > {date}` and export to secure storage (S3, syslog, SIEM). - **Establish audit review procedure** — QSA may request sample of logs; have export process documented. - **Test audit logging** — make API call, verify event appears in audit trail within seconds. **Status**: **Available** (M19 shipped) ### 10.3 — Protect Audit Trail **Requirement**: Promptly protect audit trail files from unauthorized modifications. **certctl Support**: - **Append-Only Database Design** — PostgreSQL triggers and constraints prevent modification: - `audit_events` table has no `UPDATE` or `DELETE` triggers. - Application code never executes UPDATE/DELETE on `audit_events`. - Primary key is `id` (serial); new events always INSERT. - **Read-Only API Access** — Audit events accessible only via read (`GET /api/v1/audit`): - No `POST /api/v1/audit/{id}` endpoint (no creation from API). - No `PUT /api/v1/audit/{id}` endpoint (no modification). - No `DELETE /api/v1/audit/{id}` endpoint (no deletion). - Only control plane can record events (via internal service layer, not exposed API). - **Database Access Control** (operator responsibility) — PostgreSQL user permissions: - `certctl` application user: INSERT, SELECT on `audit_events`. - `certctl_read_only` user (for compliance/audit team): SELECT only on `audit_events`. - `postgres` superuser: restricted to DBA operations, logged separately by PostgreSQL. **Evidence You Can Provide**: - Database schema: `\d audit_events` showing columns, primary key, no UPDATE/DELETE triggers. - Application code review: `internal/service/audit.go` showing `RecordEvent(...)` as only INSERT operation. - API endpoint audit: grep `internal/api/handler/audit*.go` or `internal/api/router/router.go` — no PUT/DELETE routes for events. - PostgreSQL permissions: `psql -d certctl -c "\dp audit_events"` showing INSERT/SELECT grants only. **Operator Responsibility**: - **Restrict database access** — issue read-only PostgreSQL user for compliance/audit team (no write privileges). - **Enable PostgreSQL query logging** — log all database connections and operations for DBA audit trail. - **Backup audit logs** — regularly export `audit_events` to offsite storage (S3, archive tape, syslog aggregator) for long-term retention. - **Monitor database modifications** — alert if any UPDATE/DELETE is attempted on `audit_events` (log-based alerting or PostgreSQL event triggers). - **Encrypt audit exports** — if archiving to external storage, encrypt backups at rest. **Status**: **Available** (v1.0 shipped) ### 10.4 — Promptly Review and Address Audit Trail Exceptions **Requirement**: Promptly review audit logs and investigate exceptions/anomalies. **certctl Support**: - **Dashboard Charts** (M14) — Real-time observability: - **Renewal Success Trends** (30-day line chart) — shows job success rate; spikes in failures warrant investigation. - **Certificate Status Distribution** (donut chart) — shows Expiring/Expired counts; high Expired = missed renewals. - **Expiration Timeline** (90-day weekly heatmap) — shows upcoming expirations; bunching = renewal policy tuning needed. - **Issuance Rate** (30-day bar chart) — shows certificate creation/renewal activity; anomalies (zero issuances for weeks) indicate stopped automation. - **Stats API** (M14) — Machine-readable trends: - `GET /api/v1/stats/job-trends?days=30` — renewal/issuance/deployment success/failure counts per day. - `GET /api/v1/stats/summary` — total certs, counts by status. - `GET /api/v1/stats/expiration-timeline?days=90` — expiration buckets for forecasting. - **Agent Fleet Overview** (M14) — Agent health visibility: - Pie chart: agent status distribution (healthy, offline, error). - Version breakdown: agent versions in use (identify outdated agents). - Per-agent detail: last heartbeat timestamp, OS/architecture, IP address, recent jobs. - **Alert Notifications** (M3, M16a) — Configurable escalation: - Email alerts: certificate approaching expiration, renewal failure, revocation notification. - Webhook: custom HTTP POST to your monitoring system (Slack, Teams, PagerDuty, OpsGenie, custom webhook). - Deduplication: one alert per threshold/certificate per day (avoid alert fatigue). - **Audit Trail Filtering and Export** (M13) — Compliance reporting: - `GET /api/v1/audit?actor={user}×tamp_after={date}` — filter audit log by actor, timestamp, type. - Export CSV/JSON via dashboard: audit page → select filters → "Export CSV" or "Export JSON". - Can export full audit trail for QSA review. **Evidence You Can Provide**: - Dashboard screenshots: expiration timeline, renewal success trends, status distribution. - Job trend report: `GET /api/v1/stats/job-trends?days=90` showing success/failure rates. - Agent fleet health: `GET /api/v1/agents` showing heartbeat status, version count distribution. - Audit log sample: `GET /api/v1/audit?limit=100` showing certificate issuance/renewal/revocation activity. - Alert configuration: screenshot of renewal policy `alert_thresholds_days` (30, 14, 7, 0) and notifier settings (email, Slack, etc.). **Operator Responsibility**: - **Review dashboard charts weekly** — look for anomalies (high Expired count, failure spike, renewal stalled). - **Respond to alerts promptly** — expiration alert = investigate renewal (check job logs, issuer connectivity, agent heartbeat). - **Set alert thresholds appropriately** — default 30/14/7/0 days is a starting point; adjust per your SLA and staffing. - **Maintain alert distribution list** — ensure alerts reach the right on-call engineer/team. - **Archive and review audit logs** — export monthly/quarterly for compliance trending (e.g., "all certificate changes last quarter"). - **Test alert delivery** — trigger a test renewal failure or manual revocation, verify alert is sent. **Status**: **Available** (v1.0 shipped, M14 observable charts, M19 audit log) ### 10.7 — Retain and Protect Audit Trail History **Requirement**: Retain audit trail history for at least one year and ensure it can be retrieved. **certctl Support**: - **Immutable Audit Trail** (M19) — `audit_events` table stores all API calls and certificate lifecycle events with timestamps. - **No Automatic Purge** — Certctl does not delete audit events. They remain in PostgreSQL indefinitely. - **Queryable History** — All events accessible via `GET /api/v1/audit` with time range, actor, resource filters. **Evidence You Can Provide**: - Database retention policy: confirm `audit_events` table has no DELETE triggers or maintenance jobs that purge events. - Sample audit query: `SELECT COUNT(*) FROM audit_events WHERE timestamp > NOW() - INTERVAL '365 days'` showing one year+ of events. - Export procedure: documented process for exporting audit logs to cold storage (S3, archive tape, syslog). **Operator Responsibility**: - **Configure PostgreSQL backup/retention** — certctl relies on database backups for audit trail protection. - Backup `audit_events` table daily or per your RPO/RTO. - Retain backups for at least 1 year (configure retention policy on backup system). - Test restore procedure annually. - **Export and archive audit logs** — periodically export `SELECT * FROM audit_events WHERE timestamp > {start_date}` to offsite storage. - Recommendation: monthly exports to S3 with versioning enabled. - Encrypt exports at rest. - Retain archives for at least 3 years (adjust per your compliance requirements). - **Monitor audit log growth** — `audit_events` table will grow ~1-5 MB/day depending on API call volume. - Estimate: 10,000 API calls/day = ~50 MB/month. - Plan PostgreSQL storage and backup capacity accordingly. **Status**: **Available** (v1.0 shipped) --- ## Requirement 6: Develop and Maintain Secure Systems and Applications **Objective**: Develop and maintain secure systems and applications. ### 6.3.1 — Security Coding Practices **Requirement**: Develop all custom application code in accordance with secure coding practices and include authentication, access control, input validation, and error handling. **certctl Support**: - **Input Validation** — Centralized validators enforce strong input constraints: - Common name: max 253 chars, DNS-safe characters only, no leading/trailing hyphens. - CSR PEM: must be valid PEM format (regex validation). - Policy type: whitelist enum (Issuance, Renewal, Revocation, etc.). - API key: alphanumeric + hyphens only. - Implemented in `internal/domain/validation.go` and called from all handler layer inputs. - **Error Handling** — No sensitive data leakage in error responses: - HTTP 500 errors return generic "Internal Server Error" message, not stack trace. - Database errors logged internally (structured slog), not exposed to client. - 404 errors do not reveal whether resource exists (consistent "Not Found" regardless of auth vs. not-found). - **No Hardcoded Credentials** — All secrets via environment variables: - `CERTCTL_API_KEY`, `CERTCTL_DATABASE_URL`, `CERTCTL_CA_KEY_PATH` — env vars only. - Credentials not in `main.go`, Dockerfile, `docker-compose.yml`, or Git history. - `.env` file git-ignored and excluded from version control. - **Dependency Management** — Go module pinning (`go.mod`): - All external dependencies pinned to specific versions. - No wildcard versions or `latest` tags. - CI runs `go mod verify` to detect tampering. **Evidence You Can Provide**: - Code review: `internal/domain/validation.go` showing input validation functions (Common name length, CSR PEM, policy type, etc.). - Error handling audit: `internal/api/handler/certificates.go` showing HTTP error responses (no stack traces). - Credentials in source code check: `grep -r "CERTCTL_API_KEY\|DATABASE_URL\|CA_KEY" cmd/ internal/ | grep -v ".env"` (should only show env var references, not values). - `go.mod` review: no wildcard versions, all pinned. - CI workflow: `.github/workflows/ci.yml` showing `go mod verify` step. **Operator Responsibility**: - **Review dependency updates** — keep Go version current, update certctl dependencies regularly (security patches). - **Scan container images** — use Trivy, Clair, or similar to scan Docker images for known vulnerabilities. - **Maintain secure coding practices** in any custom issuer/target connectors you deploy (scripts for OpenSSL, BASH/PowerShell for IIS/F5). **Status**: **Available** (v1.0 shipped) ### 6.5.10 — Broken Authentication and Cryptography Prevention **Requirement**: Prevent broken authentication and cryptography weaknesses. **certctl Support**: - **Authentication** — API key with SHA-256 hashing, constant-time comparison (`crypto/subtle.ConstantTimeCompare`). - **Cryptography** — Go's `crypto/*` standard library (no weak ciphers). ECDSA P-256, RSA 2048+. - **TLS** — HTTPS enforced (no plaintext HTTP endpoints). - **No Sessions** — Stateless API (no session cookies, no session fixation risk). **Status**: **Available** (v1.0 shipped) --- ## Requirement 7: Restrict Access by Business Need-to-Know **Objective**: Limit access to system components and cardholder data by business need-to-know and ensure users are authenticated and authorized. ### 7.2 — Implement Access Control **Requirement**: Ensure proper user identity management and implement access controls based on business need-to-know. **certctl v1 Support** (limited): - **Certificate Ownership** (M11b) — Each certificate assigned to owner (person + email) and optional team. Ownership is metadata; access control is not enforced at API level. - **Agent Groups** (M11b) — Renewal policies target specific agent groups (OS, architecture, CIDR, version). Groups are used for policy targeting, not user access control. - **Interactive Approval** (M11b) — `AwaitingApproval` job state allows manual approval/rejection of renewals (enforcement of business workflows, not user access control). **certctl v3 Support** (planned): - **OIDC/SSO** — Okta, Azure AD, Google integration. Users log in via identity provider. - **Role-Based Access Control (RBAC)** — Three roles: admin (all operations), operator (issue/renew/deploy), viewer (read-only). Roles assigned via OIDC claims or group membership. - **Profile/Owner Gating** — Operator can renew only certificates assigned to their team; viewer cannot modify anything. - **Audit Trail Attribution** — Every action shows which user/role performed it. **Evidence You Can Provide** (v1): - Certificate ownership mapping: `GET /api/v1/certificates` showing owner, team fields (metadata only; access not controlled). - Agent group targeting: `GET /api/v1/policies` showing `agent_group_id` field. - Interactive approval workflow: job detail showing `AwaitingApproval` state, approve/reject endpoints in API docs. **Operator Responsibility** (v1): - **Manage API key distribution** externally — only issue API keys to authorized users/systems. - **Implement reverse proxy auth** (Nginx, Apache, Okta proxy) in front of certctl to enforce OIDC/LDAP (outside certctl). - **Plan for V3 RBAC** — budget for upgrade when finer-grained access control is needed. **Planned** (V3): - Upgrade to certctl Pro with OIDC/RBAC and per-role audit trail. **Status**: **Available in part** (v1.0: ownership metadata, agent group targeting). **Planned V3**: OIDC/RBAC enforcement. --- ## Evidence Summary Table | PCI-DSS Requirement | certctl Feature | API/UI Evidence | Database/Config | Audit Trail | Status | |---|---|---|---|---|---| | **4.2.1** Strong Crypto | TLS cert issuance, ACME/step-ca/Local CA, RSA 2048+/ECDSA P-256 | `GET /api/v1/certificates` (key_type, key_size) | Certificate profiles | `GET /api/v1/audit?type=certificate_issued` | Available | | **4.2.2** Cert Inventory & Validation | Managed cert CRUD, discovery (M18b), expiration alerting, CRL/OCSP | `GET /api/v1/certificates`, `GET /api/v1/discovered-certificates`, `GET /api/v1/crl`, `GET /api/v1/ocsp/{issuer}/{serial}` | `managed_certificates`, `discovered_certificates` tables | `GET /api/v1/audit?type=certificate_*` | Available | | **3.6** Key Documentation | Profiles, owner/team tracking, issuer config, audit trail | `GET /api/v1/profiles`, `GET /api/v1/issuers`, certificate detail with owner/team | Profiles, certificate owner/team fields, issuer config | `GET /api/v1/audit?resource_type=certificate` | Available | | **3.7.1** Key Generation | Agent-side ECDSA P-256, server keygen (demo only) | Agent logs, renewal job detail, CSR audit | `CERTCTL_KEYGEN_MODE=agent` (config), job_type=AwaitingCSR | `GET /api/v1/audit?type=certificate_issued` with CSR hash | Available | | **3.7.2** Key Storage | Agent `/var/lib/certctl/keys` (0600), env var secrets, .env excluded | Deployment manifest (env var refs), agent key dir listing | `.env` file (git-ignored), `CERTCTL_KEY_DIR`, `CERTCTL_CA_KEY_PATH` | No API audit (keys off-platform) | Available | | **3.7.3** Key Rotation | Auto renewal, expiration thresholds, renewal jobs | Dashboard renewal trends, `GET /api/v1/jobs?type=Renewal`, certificate versions | Renewal policies, certificate version history | `GET /api/v1/audit?type=certificate_renewed` | Available | | **3.7.4** Key Destruction | Revocation API (RFC 5280), CRL/OCSP, private key cleanup | `POST /api/v1/certificates/{id}/revoke`, `GET /api/v1/crl`, OCSP endpoint | `certificate_revocations` table, CRL publication | `GET /api/v1/audit?type=certificate_revoked` | Available | | **8.3** Strong Authentication | API key (SHA-256 hash, TLS), GUI login, 401 redirect | GUI login screenshot, API key auth header, TLS cert | API key hash in database | `GET /api/v1/audit` showing API calls | Available | | **8.6** Acct Management | Credentials out of source, .env excluded, env var config | Code review (no hardcoded secrets), `.gitignore` check | Deployment manifests showing env var refs only | No account lifecycle audit (outside scope) | Available in part | | **10.2** Audit Logging | API audit middleware (M19), certificate lifecycle events | `GET /api/v1/audit` with filter/pagination | `audit_events` table (every API call) | Real-time via API | Available | | **10.3** Audit Protection | Append-only table design, read-only API, DB permissions | API endpoint audit (no PUT/DELETE on events), DB schema | `audit_events` table, PostgreSQL GRANT SELECT | Immutable by design | Available | | **10.4** Review & Alert | Dashboard charts, stats API, notifier integrations | Dashboard (renewal trends, status pie, expiration heatmap), `GET /api/v1/stats/*` | Job results, alert config in policies | `GET /api/v1/audit?type=job_*` | Available | | **10.7** Retention | 1+ year in PostgreSQL, export/archive procedures | Database query `SELECT COUNT(*) FROM audit_events WHERE timestamp > NOW() - INTERVAL '1 year'` | `audit_events` table retention (no auto-delete) | Manual export/archival (operator) | Available | | **6.3.1** Secure Coding | Input validation, error handling, no hardcoded secrets, dependency pinning | Code review (validation.go, handlers), error responses | `go.mod` with pinned versions, `.gitignore` | GitHub Actions CI with `go mod verify` | Available | | **7.2** Access Control | Ownership metadata, agent groups, interactive approval | `GET /api/v1/certificates` (owner/team), `GET /api/v1/agent-groups` | Certificate owner/team fields, agent group criteria | User identity from auth context | Available in part (V3: RBAC) | --- ## Operator Responsibilities The following control objectives are **outside certctl's scope** and must be managed by your organization: | Control Objective | Responsibility | Example Actions | |---|---|---| | **Network Segmentation** | Isolate certctl control plane from cardholder network | Place certctl on separate VLAN, firewall rules | | **Physical Security** | Restrict access to servers/databases | Data center access controls, logging | | **Personnel Screening** | Background checks for staff with access | HR/employment verification | | **Access Control Enforcement** | User authentication & authorization outside API | Implement reverse proxy with OIDC (V3: use certctl Pro RBAC) | | **Incident Response** | Procedures for certificate compromise or breach | Document key revocation process, alert escalation | | **Disaster Recovery** | Backup and restore procedures | Database backup schedule, offsite replication | | **Change Management** | Approval process for config/cert changes | CAB meetings, documented procedures | | **Vulnerability Scanning** | ASV scanning, penetration testing, code review | Annual PCI-DSS penetration test | | **Key Backup & Escrow** | Secure offline storage of CA private keys (if required) | Hardware security module (HSM) or encrypted vault | | **Audit Log Retention** | Long-term archival and protection of audit logs | Export to S3/syslog, retain 3+ years | | **QSA Engagement** | Schedule and coordination of compliance assessment | Annual audit with qualified security assessor | --- ## V3 Enhancements for PCI-DSS Certctl v3 (Pro) adds paid features that strengthen PCI-DSS compliance posture: | Feature | PCI-DSS Benefit | |---|---| | **OIDC/SSO Authentication** | Centralized identity management, audit integration with corporate directory | | **Role-Based Access Control (RBAC)** | Least-privilege enforcement: admin, operator, viewer roles with profile/team gating | | **Bulk Revocation by Profile/Owner/Agent** | Rapid incident response (revoke all certs in cardholder network in minutes) | | **NATS Event Bus with JetStream Audit Streaming** | Real-time event streaming to SIEM (Splunk, ELK, Datadog) for centralized audit trail | | **Certificate Health Scores** | Proactive risk identification (composite scoring: expiration proximity, rotation age, key strength) | | **Advanced Search DSL** | Complex audit queries (POST /search with nested AND/OR, regex, field projection) for compliance reporting | | **CT Log Monitoring** | Detect unauthorized certificate issuance (security vulnerability detection) | | **DigiCert Issuer Connector** | Enterprise CA integration for compliance audits | --- ## Next Steps for Compliance 1. **Review this mapping with your QSA** — Confirm which requirements apply to your cardholder data environment. 2. **Configure certctl for your environment**: - Set `CERTCTL_KEYGEN_MODE=agent` in production. - Define certificate profiles with approved key types. - Configure renewal policies with appropriate thresholds (e.g., 30 days for 90-day certs). - Enable notifier integrations (email, Slack, PagerDuty) for alerts. - Plan `CERTCTL_DISCOVERY_DIRS` on agents to scan all certificate locations. 3. **Implement operator controls**: - Document certificate management procedures (issuance, renewal, revocation, archival). - Establish API key rotation schedule. - Set up audit log export and archival (monthly to S3, retain 1+ year). - Configure PostgreSQL backups (daily, 1+ year retention). - Plan incident response (who revokes certs, escalation process, timeline). 4. **Test compliance readiness**: - Trigger a test renewal and verify CRL/OCSP publication. - Export audit trail and verify it shows expected events. - Test revocation workflow and confirm OCSP reflects status within 24 hours. - Run discovery scan and verify unknown certs are detected and triaged. 5. **Prepare evidence for QSA**: - API endpoint documentation (OpenAPI spec: `api/openapi.yaml`). - Audit log sample (last 90 days of events). - Configuration export (profiles, policies, issuer/target definitions). - Deployment manifest (showing env var config, no hardcoded secrets). - Test certificates and CRL/OCSP query results. 6. **Plan for V3** (if RBAC/centralized audit required): - Evaluate certctl Pro for OIDC/SSO and NATS audit streaming. - Assess integration with existing identity provider (Okta, Azure AD, etc.). --- ## Questions? For additional guidance on certctl features and PCI-DSS mapping: - Review the [Architecture Guide](architecture.md) for system design. - Check [Connectors Documentation](connectors.md) for issuer/target/notifier capabilities. - Run the [Quick Start Guide](quickstart.md) to see features in action. - Consult your QSA for final compliance determination. **Last Updated**: March 24, 2026 (certctl v1.0 with M18b discovery and M19 audit logging)