From 4c3b7cbb167b7b0a30155298f2b64fe8e66891c4 Mon Sep 17 00:00:00 2001 From: shankar0123 Date: Fri, 3 Apr 2026 16:11:42 -0400 Subject: [PATCH] docs: fix stale references, seed data case bugs, and convert ASCII diagrams to Mermaid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit all docs and examples against current codebase state. Fix seed_demo.sql domain constant casing (IssuerType, TargetType, AgentStatus) that would cause agent dispatch failures. Fix example docker-compose health endpoints (/health not /api/v1/health) and env var names (CERTCTL_DATABASE_URL). Update connector counts, test numbers, and planned→implemented status across docs. Convert 3 ASCII flow diagrams to Mermaid. Co-Authored-By: Claude Opus 4.6 --- docs/architecture.md | 10 ++-- docs/concepts.md | 4 +- docs/connectors.md | 4 +- docs/demo-advanced.md | 4 +- docs/features.md | 14 +++--- docs/testing-guide.md | 4 +- examples/acme-nginx/acme-nginx.md | 22 +++++---- examples/acme-nginx/docker-compose.yml | 4 +- .../acme-wildcard-dns01/docker-compose.yml | 4 +- examples/multi-issuer/docker-compose.yml | 4 +- examples/multi-issuer/multi-issuer.md | 46 ++++++++++--------- .../private-ca-traefik/docker-compose.yml | 4 +- .../private-ca-traefik/private-ca-traefik.md | 33 ++++--------- examples/step-ca-haproxy/docker-compose.yml | 4 +- examples/step-ca-haproxy/step-ca-haproxy.md | 2 +- migrations/seed_demo.sql | 46 +++++++++---------- 16 files changed, 102 insertions(+), 107 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 26ebd14..322f53d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -90,8 +90,10 @@ flowchart TB T5["HAProxy\n(combined PEM + reload)"] T6["Traefik\n(file provider)"] T7["Caddy\n(admin API / file)"] + T8["Envoy\n(file-based SDS)"] + T9["Postfix/Dovecot\n(file + service reload)"] T2["F5 BIG-IP\n(proxy agent + iControl REST, planned)"] - T3["IIS\n(agent-local PowerShell, planned)"] + T3["IIS\n(WinRM + local)"] end DASH --> API @@ -119,7 +121,7 @@ The server exposes a REST API under `/api/v1/` and optionally serves the web das ### Agents -Lightweight Go processes that run on or near your infrastructure. Agents generate ECDSA P-256 private keys locally, create CSRs, and submit them to the control plane for signing — private keys never leave agent infrastructure. Agents also handle certificate deployment to target systems (NGINX, Apache httpd, HAProxy fully implemented; F5 BIG-IP, IIS interface only with V2 implementations planned) and report job status. They communicate with the control plane via HTTP and authenticate with API keys. +Lightweight Go processes that run on or near your infrastructure. Agents generate ECDSA P-256 private keys locally, create CSRs, and submit them to the control plane for signing — private keys never leave agent infrastructure. Agents also handle certificate deployment to target systems (NGINX, Apache httpd, HAProxy, Traefik, Caddy, Envoy, Postfix, Dovecot, IIS fully implemented; F5 BIG-IP interface stub only) and report job status. They communicate with the control plane via HTTP and authenticate with API keys. The agent runs two background loops: a heartbeat (every 60 seconds) to signal it's alive, and a work poll (every 30 seconds) to check for actionable jobs via `GET /api/v1/agents/{id}/work`. Jobs may be `AwaitingCSR` (agent needs to generate key + submit CSR) or `Deployment` (agent needs to deploy a certificate). Private keys are stored in `CERTCTL_KEY_DIR` (default `/var/lib/certctl/keys`) with 0600 permissions. @@ -521,8 +523,10 @@ flowchart TB TI --> HP["HAProxy"] TI --> TF["Traefik"] TI --> CD["Caddy"] + TI --> EV["Envoy"] + TI --> PO["Postfix/Dovecot"] + TI --> IIS["IIS"] TI --> F5["F5 BIG-IP (interface only)"] - TI --> IIS["IIS (interface only)"] end subgraph "Notifier Connectors" diff --git a/docs/concepts.md b/docs/concepts.md index ec68b8a..7e0eda2 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -125,9 +125,9 @@ Agents also report **metadata** about themselves — their operating system, CPU ### Deployment Targets -Targets are the systems where certificates actually get installed — NGINX web servers, Apache httpd servers, HAProxy load balancers, F5 BIG-IP appliances, Microsoft IIS servers. Each target type has a **connector** that knows how to deploy certificates to that specific system (e.g., writing files and reloading NGINX or Apache config, building a combined PEM for HAProxy). +Targets are the systems where certificates actually get installed — NGINX web servers, Apache httpd servers, HAProxy load balancers, Traefik reverse proxies, Caddy servers, Envoy gateways, Postfix/Dovecot mail servers, Microsoft IIS servers, and network appliances. Each target type has a **connector** that knows how to deploy certificates to that specific system (e.g., writing files and reloading NGINX or Apache config, building a combined PEM for HAProxy). -For targets where an agent runs directly on the machine (NGINX, Apache, HAProxy, IIS), the agent deploys certificates locally — no remote access needed. For network appliances where you can't install an agent (F5 BIG-IP, Palo Alto, etc.), a **proxy agent** in the same network zone picks up the deployment job and calls the appliance's API. The server never initiates outbound connections to any target. +For targets where an agent runs directly on the machine (NGINX, Apache, HAProxy, Traefik, Caddy, Envoy, Postfix, Dovecot, IIS), the agent deploys certificates locally — no remote access needed. For network appliances where you can't install an agent (F5 BIG-IP, Palo Alto, etc.), a **proxy agent** in the same network zone picks up the deployment job and calls the appliance's API. The server never initiates outbound connections to any target. ## The Certificate Lifecycle diff --git a/docs/connectors.md b/docs/connectors.md index 7904f4d..2d6dab8 100644 --- a/docs/connectors.md +++ b/docs/connectors.md @@ -53,8 +53,8 @@ Connectors extend certctl to integrate with external systems for certificate iss Three types of connectors: -1. **Issuer Connector** — Obtains certificates from CAs (Local CA with sub-CA support, ACME with HTTP-01 + DNS-01 + DNS-PERSIST-01, step-ca, OpenSSL/Custom CA implemented; additional CA integrations planned) -2. **Target Connector** — Deploys certificates to infrastructure (NGINX, Apache httpd, HAProxy, Traefik, Caddy, Envoy, IIS implemented; F5 via proxy agent planned; additional cloud and network targets planned) +1. **Issuer Connector** — Obtains certificates from CAs (Local CA with sub-CA support, ACME with HTTP-01 + DNS-01 + DNS-PERSIST-01, step-ca, OpenSSL/Custom CA, Vault PKI, DigiCert implemented; additional CA integrations planned) +2. **Target Connector** — Deploys certificates to infrastructure (NGINX, Apache httpd, HAProxy, Traefik, Caddy, Envoy, Postfix, Dovecot, IIS implemented; F5 via proxy agent planned; additional cloud and network targets planned) 3. **Notifier Connector** — Sends alerts about certificate events (Email, Webhooks, Slack, Microsoft Teams, PagerDuty, OpsGenie implemented) All connectors accept JSON configuration at initialization, support config validation, and are registered in the service layer. Issuer connectors run on the control plane; target connectors run on agents. For network appliances where agents can't be installed, a **proxy agent** in the same network zone handles deployment — the server never initiates outbound connections. diff --git a/docs/demo-advanced.md b/docs/demo-advanced.md index 5b8ef3f..7154f25 100644 --- a/docs/demo-advanced.md +++ b/docs/demo-advanced.md @@ -307,8 +307,8 @@ flowchart TD A --> F["ACME\n(Let's Encrypt)"] A --> G["step-ca\n(implemented)"] A --> H["OpenSSL / Custom CA\n(script-based)"] - A --> J["DigiCert API\n(planned)"] - A --> K["Vault PKI\n(planned)"] + A --> J["DigiCert API\n(implemented)"] + A --> K["Vault PKI\n(implemented)"] A --> L["Entrust / GlobalSign\n(planned)"] A --> M["Google CAS / EJBCA\n(planned)"] ``` diff --git a/docs/features.md b/docs/features.md index 474f443..9cb3cfb 100644 --- a/docs/features.md +++ b/docs/features.md @@ -1286,11 +1286,11 @@ The web dashboard is the primary operational interface for certctl. Built with * - **Docker Tags** — `:latest`, `:v{version}` (`shankar0123.docker.scarf.sh/certctl-server`, `shankar0123.docker.scarf.sh/certctl-agent`) ### Test Suite -- **Unit Tests** — 625+ test functions across service, handler, middleware, domain layers +- **Unit Tests** — 1,088+ test functions across service, handler, middleware, domain layers - **Integration Tests** — End-to-end workflows (issuance→renewal→deployment) - **Negative Tests** — Malformed input, nonexistent resources, error conditions -- **Frontend Tests** — 86 Vitest tests (API client, utilities, stats/metrics, full endpoint coverage) -- **Total Coverage** — 900+ tests (Go + frontend combined) +- **Frontend Tests** — 211 Vitest tests (API client, utilities, stats/metrics, full endpoint coverage) +- **Total Coverage** — 1,554+ tests (Go + frontend combined) ### Licensing - **License** — Business Source License 1.1 (BSL 1.1) @@ -1478,10 +1478,10 @@ Each guide includes an evidence summary table mapping specific criteria to certc | Category | Count | |----------|-------| -| **API Endpoints** | 95 (under /api/v1/ + /.well-known/est/) | +| **API Endpoints** | 97 (under /api/v1/ + /.well-known/est/) | | **Dashboard** | Full web GUI | -| **Issuer Connectors** | 4 (Local CA, ACME, step-ca, OpenSSL) | -| **Target Connectors** | 5 (3 impl: NGINX, Apache, HAProxy; 2 stubs: F5, IIS) | +| **Issuer Connectors** | 6 (Local CA, ACME, step-ca, OpenSSL, Vault PKI, DigiCert) | +| **Target Connectors** | 10 (9 impl: NGINX, Apache, HAProxy, Traefik, Caddy, Envoy, IIS, Postfix, Dovecot; 1 stub: F5) | | **Notifier Channels** | 6 (Email, Webhook, Slack, Teams, PagerDuty, OpsGenie) | | **Job Types** | 4 (Issuance, Renewal, Deployment, Validation) | | **Job States** | 7 (Pending, AwaitingCSR, AwaitingApproval, Running, Completed, Failed, Cancelled) | @@ -1492,6 +1492,6 @@ Each guide includes an evidence summary table mapping specific criteria to certc | **MCP Tools** | 76 (16 resource domains) | | **CLI Subcommands** | 10 | | **Database Tables** | 19 | -| **Test Suite** | 900+ tests (Go backend + frontend) | +| **Test Suite** | 1,554+ tests (Go backend + frontend) | | **Environment Variables** | 41+ configuration options | diff --git a/docs/testing-guide.md b/docs/testing-guide.md index 5683bdf..72d6fce 100644 --- a/docs/testing-guide.md +++ b/docs/testing-guide.md @@ -1600,7 +1600,7 @@ curl -s -w "\nHTTP %{http_code}\n" -X POST -H "$AUTH" -H "$CT" \ --- -**Test 7.1.6 — Create IIS target (stub)** +**Test 7.1.6 — Create IIS target** ```bash curl -s -w "\nHTTP %{http_code}\n" -X POST -H "$AUTH" -H "$CT" \ @@ -5833,7 +5833,7 @@ These must be green before starting manual QA: | 7.1.3 | Create Apache target | Manual | ☐ | | | | 7.1.4 | Create HAProxy target | Manual | ☐ | | | | 7.1.5 | Create F5 BIG-IP target (stub) | Auto | ☑ | 2026-03-30 | | -| 7.1.6 | Create IIS target (stub) | Auto | ☑ | 2026-03-30 | | +| 7.1.6 | Create IIS target | Auto | ☑ | 2026-03-30 | | | 7.1.7 | Get target verifies type-specific config stored | Manual | ☐ | | | | 7.1.8 | Update target config | Manual | ☐ | | | | 7.1.9 | Delete target returns 204 | Auto | ☑ | 2026-03-30 | | diff --git a/examples/acme-nginx/acme-nginx.md b/examples/acme-nginx/acme-nginx.md index 9583d2f..e016c63 100644 --- a/examples/acme-nginx/acme-nginx.md +++ b/examples/acme-nginx/acme-nginx.md @@ -13,16 +13,18 @@ This example demonstrates certctl's core use case: **automatically manage TLS ce ## Architecture -``` -Your Domain (example.com) - ↓ [HTTP-01 validation, port 80] - Let's Encrypt ACME - ↓ [CSR submission] - certctl Server (control plane) - ↓ [API polling] - certctl Agent (on NGINX server) - ↓ [deploy cert+key] - NGINX Reverse Proxy +```mermaid +flowchart TD + A["Your Domain (example.com)"] + B["Let's Encrypt ACME"] + C["certctl Server (control plane)"] + D["certctl Agent (on NGINX server)"] + E["NGINX Reverse Proxy"] + + A -->|HTTP-01 validation
port 80| B + B -->|CSR submission| C + C -->|API polling| D + D -->|deploy cert+key| E ``` ## Prerequisites diff --git a/examples/acme-nginx/docker-compose.yml b/examples/acme-nginx/docker-compose.yml index fce6853..1211345 100644 --- a/examples/acme-nginx/docker-compose.yml +++ b/examples/acme-nginx/docker-compose.yml @@ -26,7 +26,7 @@ services: container_name: certctl-server-acme-nginx environment: # Database - DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable + CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable # Server settings CERTCTL_SERVER_PORT: 8443 @@ -61,7 +61,7 @@ services: networks: - certctl-network healthcheck: - test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] + test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1'] interval: 10s timeout: 5s retries: 3 diff --git a/examples/acme-wildcard-dns01/docker-compose.yml b/examples/acme-wildcard-dns01/docker-compose.yml index 54a146d..e159aa2 100644 --- a/examples/acme-wildcard-dns01/docker-compose.yml +++ b/examples/acme-wildcard-dns01/docker-compose.yml @@ -50,7 +50,7 @@ services: container_name: certctl-server-dns01 environment: # Database - DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable + CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable # Server settings CERTCTL_SERVER_PORT: 8443 @@ -113,7 +113,7 @@ services: - certctl-network healthcheck: - test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] + test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1'] interval: 10s timeout: 5s retries: 3 diff --git a/examples/multi-issuer/docker-compose.yml b/examples/multi-issuer/docker-compose.yml index 0286f56..07bb315 100644 --- a/examples/multi-issuer/docker-compose.yml +++ b/examples/multi-issuer/docker-compose.yml @@ -27,7 +27,7 @@ services: container_name: certctl-server-multi-issuer environment: # Database - DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable + CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable # Server settings CERTCTL_SERVER_PORT: 8443 @@ -64,7 +64,7 @@ services: networks: - certctl-network healthcheck: - test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] + test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1'] interval: 10s timeout: 5s retries: 3 diff --git a/examples/multi-issuer/multi-issuer.md b/examples/multi-issuer/multi-issuer.md index cf35cbb..8ab4ec2 100644 --- a/examples/multi-issuer/multi-issuer.md +++ b/examples/multi-issuer/multi-issuer.md @@ -13,27 +13,29 @@ With certctl, both issuer types are configured and available. You assign each ce ## Architecture -``` -┌─────────────────────────────────────────────────────────────────┐ -│ certctl Server (Control Plane) │ -│ - Let's Encrypt ACME issuer (HTTP-01 challenges) │ -│ - Local CA issuer (self-signed or sub-CA mode) │ -│ - PostgreSQL database (cert inventory, audit, jobs) │ -└─────────────────────────────────────────────────────────────────┘ - ▲ - │ API polling - │ -┌─────────────────────────────────────────────────────────────────┐ -│ certctl Agent │ -│ - Discovers existing certs in /etc/nginx/ssl and /etc/app/ssl │ -│ - Polls server for renewal/issuance/deployment jobs │ -│ - Generates keys locally (agent-side crypto) │ -│ - Deploys certs to NGINX and app service directories │ -└─────────────────────────────────────────────────────────────────┘ - │ │ - ▼ ▼ - NGINX (public TLS) App Services (internal TLS) - (Let's Encrypt certs) (Local CA certs) +```mermaid +flowchart TD + subgraph Server ["certctl Server (Control Plane)"] + A["Let's Encrypt ACME issuer
(HTTP-01 challenges)"] + B["Local CA issuer
(self-signed or sub-CA mode)"] + C["PostgreSQL database
(cert inventory, audit, jobs)"] + end + + subgraph Agent ["certctl Agent"] + D["Discovers existing certs
(/etc/nginx/ssl, /etc/app/ssl)"] + E["Polls server for
renewal/issuance/deployment jobs"] + F["Generates keys locally
(agent-side crypto)"] + G["Deploys certs to NGINX
and app service directories"] + end + + subgraph Targets ["Target Services"] + H["NGINX (public TLS)
(Let's Encrypt certs)"] + I["App Services (internal TLS)
(Local CA certs)"] + end + + Server -->|API polling| Agent + Agent -->|Deploy| H + Agent -->|Deploy| I ``` ## Prerequisites @@ -212,7 +214,7 @@ Each agent independently manages its local cert inventory and deployments. The s - For ACME, ensure ports 80/443 are open and your domain resolves ### Agent can't reach server -- Check network: `docker compose exec certctl-agent curl http://certctl-server:8443/api/v1/health` +- Check network: `docker compose exec certctl-agent curl http://certctl-server:8443/health` - Verify `CERTCTL_SERVER_URL` environment variable ### No issuers showing up diff --git a/examples/private-ca-traefik/docker-compose.yml b/examples/private-ca-traefik/docker-compose.yml index 0090072..5feed5a 100644 --- a/examples/private-ca-traefik/docker-compose.yml +++ b/examples/private-ca-traefik/docker-compose.yml @@ -26,7 +26,7 @@ services: container_name: certctl-server-private-ca environment: # Database - DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable + CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable # Server settings CERTCTL_SERVER_PORT: 8443 @@ -77,7 +77,7 @@ services: networks: - certctl-network healthcheck: - test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] + test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1'] interval: 10s timeout: 5s retries: 3 diff --git a/examples/private-ca-traefik/private-ca-traefik.md b/examples/private-ca-traefik/private-ca-traefik.md index 219f5cd..ac303ea 100644 --- a/examples/private-ca-traefik/private-ca-traefik.md +++ b/examples/private-ca-traefik/private-ca-traefik.md @@ -17,29 +17,16 @@ This example demonstrates certctl managing certificates for **internal services ## Architecture -``` -┌──────────────────┐ -│ certctl-server │ (Local CA issuer) -│ (control │ -│ plane) │ -└────────┬─────────┘ - │ - │ REST API (job polling) - │ -┌────────▼──────────┐ -│ certctl-agent │ (certificate deployer) -└────────┬──────────┘ - │ - │ Write cert/key files - │ -┌────────▼──────────────────────┐ -│ Traefik │ -│ (watches cert directory) │ -└────────────────────────────────┘ - │ - │ TLS handshakes - │ - [Internal Services] +```mermaid +flowchart TD + A["certctl-server
(control plane)
(Local CA issuer)"] + B["certctl-agent
(certificate deployer)"] + C["Traefik
(watches cert directory)"] + D["[Internal Services]"] + + A -->|REST API
job polling| B + B -->|Write cert/key files| C + C -->|TLS handshakes| D ``` ## Quick Start (Self-Signed CA) diff --git a/examples/step-ca-haproxy/docker-compose.yml b/examples/step-ca-haproxy/docker-compose.yml index 4d462af..6bbf1df 100644 --- a/examples/step-ca-haproxy/docker-compose.yml +++ b/examples/step-ca-haproxy/docker-compose.yml @@ -81,7 +81,7 @@ services: container_name: certctl-server-stepca-haproxy environment: # Database - DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable + CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable # Server settings CERTCTL_SERVER_PORT: 8443 @@ -119,7 +119,7 @@ services: networks: - certctl-network healthcheck: - test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] + test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1'] interval: 10s timeout: 5s retries: 3 diff --git a/examples/step-ca-haproxy/step-ca-haproxy.md b/examples/step-ca-haproxy/step-ca-haproxy.md index 5a93f96..2cf5614 100644 --- a/examples/step-ca-haproxy/step-ca-haproxy.md +++ b/examples/step-ca-haproxy/step-ca-haproxy.md @@ -315,7 +315,7 @@ Common issues: Verify network: ```bash -docker compose exec certctl-agent curl http://certctl-server:8443/api/v1/health +docker compose exec certctl-agent curl http://certctl-server:8443/health ``` ### HAProxy config validation fails diff --git a/migrations/seed_demo.sql b/migrations/seed_demo.sql index 79e9b04..344a4f2 100644 --- a/migrations/seed_demo.sql +++ b/migrations/seed_demo.sql @@ -39,11 +39,11 @@ ON CONFLICT (id) DO NOTHING; -- 3. Issuers -- ============================================================ INSERT INTO issuers (id, name, type, config, enabled, created_at, updated_at) VALUES - ('iss-local', 'Local Dev CA', 'local', '{"ca_common_name": "CertCtl Demo CA", "validity_days": 90}', true, NOW() - INTERVAL '180 days', NOW() - INTERVAL '180 days'), - ('iss-acme-le', 'Let''s Encrypt Staging', 'acme', '{"directory_url": "https://acme-staging-v02.api.letsencrypt.org/directory", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '150 days', NOW() - INTERVAL '150 days'), - ('iss-stepca', 'step-ca Internal', 'stepca', '{"ca_url": "https://ca.internal:9000", "provisioner_name": "certctl", "validity_days": 90}', true, NOW() - INTERVAL '120 days', NOW() - INTERVAL '120 days'), - ('iss-acme-zs', 'ZeroSSL (EAB)', 'acme', '{"directory_url": "https://acme.zerossl.com/v2/DV90", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '60 days', NOW() - INTERVAL '60 days'), - ('iss-openssl', 'Custom OpenSSL CA', 'openssl', '{"sign_script": "/opt/ca/sign.sh", "timeout_seconds": 30}', false, NOW() - INTERVAL '30 days', NOW() - INTERVAL '30 days'), + ('iss-local', 'Local Dev CA', 'GenericCA', '{"ca_common_name": "CertCtl Demo CA", "validity_days": 90}', true, NOW() - INTERVAL '180 days', NOW() - INTERVAL '180 days'), + ('iss-acme-le', 'Let''s Encrypt Staging', 'ACME', '{"directory_url": "https://acme-staging-v02.api.letsencrypt.org/directory", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '150 days', NOW() - INTERVAL '150 days'), + ('iss-stepca', 'step-ca Internal', 'StepCA', '{"ca_url": "https://ca.internal:9000", "provisioner_name": "certctl", "validity_days": 90}', true, NOW() - INTERVAL '120 days', NOW() - INTERVAL '120 days'), + ('iss-acme-zs', 'ZeroSSL (EAB)', 'ACME', '{"directory_url": "https://acme.zerossl.com/v2/DV90", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '60 days', NOW() - INTERVAL '60 days'), + ('iss-openssl', 'Custom OpenSSL CA', 'OpenSSL', '{"sign_script": "/opt/ca/sign.sh", "timeout_seconds": 30}', false, NOW() - INTERVAL '30 days', NOW() - INTERVAL '30 days'), ('iss-vault', 'HashiCorp Vault PKI', 'VaultPKI', '{"addr": "https://vault.internal:8200", "mount": "pki", "role": "web-certs", "ttl": "8760h"}', true, NOW() - INTERVAL '20 days', NOW() - INTERVAL '20 days'), ('iss-digicert', 'DigiCert CertCentral', 'DigiCert', '{"base_url": "https://www.digicert.com/services/v2", "product_type": "ssl_basic"}', true, NOW() - INTERVAL '15 days', NOW() - INTERVAL '15 days') ON CONFLICT (id) DO NOTHING; @@ -52,33 +52,33 @@ ON CONFLICT (id) DO NOTHING; -- 4. Agents (8 agents across multiple platforms) -- ============================================================ INSERT INTO agents (id, name, hostname, status, last_heartbeat_at, registered_at, api_key_hash, os, architecture, ip_address, version) VALUES - ('ag-web-prod', 'web-prod-agent', 'web-prod-01.internal', 'online', NOW() - INTERVAL '30 seconds', NOW() - INTERVAL '120 days', 'demo_hash_1', 'linux', 'amd64', '10.0.1.10', '2.0.14'), - ('ag-web-staging', 'web-staging-agent', 'web-stg-01.internal', 'online', NOW() - INTERVAL '45 seconds', NOW() - INTERVAL '90 days', 'demo_hash_2', 'linux', 'amd64', '10.0.2.20', '2.0.14'), - ('ag-lb-prod', 'lb-prod-agent', 'lb-prod-01.internal', 'online', NOW() - INTERVAL '15 seconds', NOW() - INTERVAL '150 days', 'demo_hash_3', 'linux', 'amd64', '10.0.1.50', '2.0.14'), - ('ag-iis-prod', 'iis-prod-agent', 'iis-prod-01.internal', 'offline', NOW() - INTERVAL '3 hours', NOW() - INTERVAL '60 days', 'demo_hash_4', 'windows', 'amd64', '10.0.3.15', '2.0.12'), - ('ag-data-prod', 'data-prod-agent', 'data-prod-01.internal', 'online', NOW() - INTERVAL '20 seconds', NOW() - INTERVAL '90 days', 'demo_hash_5', 'linux', 'arm64', '10.0.4.30', '2.0.14'), - ('ag-edge-01', 'edge-eu-agent', 'edge-eu-01.internal', 'online', NOW() - INTERVAL '50 seconds', NOW() - INTERVAL '45 days', 'demo_hash_6', 'linux', 'arm64', '10.0.5.10', '2.0.14'), - ('ag-k8s-prod', 'k8s-prod-agent', 'k8s-node-01.internal', 'online', NOW() - INTERVAL '10 seconds', NOW() - INTERVAL '30 days', 'demo_hash_7', 'linux', 'amd64', '10.0.6.10', '2.0.14'), - ('ag-mac-dev', 'mac-dev-agent', 'dev-mac-01.internal', 'online', NOW() - INTERVAL '60 seconds', NOW() - INTERVAL '15 days', 'demo_hash_8', 'darwin', 'arm64', '10.0.7.5', '2.0.14') + ('ag-web-prod', 'web-prod-agent', 'web-prod-01.internal', 'Online', NOW() - INTERVAL '30 seconds', NOW() - INTERVAL '120 days', 'demo_hash_1', 'linux', 'amd64', '10.0.1.10', '2.0.14'), + ('ag-web-staging', 'web-staging-agent', 'web-stg-01.internal', 'Online', NOW() - INTERVAL '45 seconds', NOW() - INTERVAL '90 days', 'demo_hash_2', 'linux', 'amd64', '10.0.2.20', '2.0.14'), + ('ag-lb-prod', 'lb-prod-agent', 'lb-prod-01.internal', 'Online', NOW() - INTERVAL '15 seconds', NOW() - INTERVAL '150 days', 'demo_hash_3', 'linux', 'amd64', '10.0.1.50', '2.0.14'), + ('ag-iis-prod', 'iis-prod-agent', 'iis-prod-01.internal', 'Offline', NOW() - INTERVAL '3 hours', NOW() - INTERVAL '60 days', 'demo_hash_4', 'windows', 'amd64', '10.0.3.15', '2.0.12'), + ('ag-data-prod', 'data-prod-agent', 'data-prod-01.internal', 'Online', NOW() - INTERVAL '20 seconds', NOW() - INTERVAL '90 days', 'demo_hash_5', 'linux', 'arm64', '10.0.4.30', '2.0.14'), + ('ag-edge-01', 'edge-eu-agent', 'edge-eu-01.internal', 'Online', NOW() - INTERVAL '50 seconds', NOW() - INTERVAL '45 days', 'demo_hash_6', 'linux', 'arm64', '10.0.5.10', '2.0.14'), + ('ag-k8s-prod', 'k8s-prod-agent', 'k8s-node-01.internal', 'Online', NOW() - INTERVAL '10 seconds', NOW() - INTERVAL '30 days', 'demo_hash_7', 'linux', 'amd64', '10.0.6.10', '2.0.14'), + ('ag-mac-dev', 'mac-dev-agent', 'dev-mac-01.internal', 'Online', NOW() - INTERVAL '60 seconds', NOW() - INTERVAL '15 days', 'demo_hash_8', 'darwin', 'arm64', '10.0.7.5', '2.0.14') ON CONFLICT (id) DO NOTHING; -- Sentinel agent for network-discovered certificates INSERT INTO agents (id, name, hostname, status, last_heartbeat_at, registered_at, api_key_hash, os, architecture, ip_address, version) VALUES - ('server-scanner', 'Network Scanner (Server-Side)', 'certctl-server', 'online', NOW(), NOW() - INTERVAL '90 days', 'sentinel_no_auth', 'linux', 'amd64', '127.0.0.1', '2.0.14') + ('server-scanner', 'Network Scanner (Server-Side)', 'certctl-server', 'Online', NOW(), NOW() - INTERVAL '90 days', 'sentinel_no_auth', 'linux', 'amd64', '127.0.0.1', '2.0.14') ON CONFLICT (id) DO NOTHING; -- ============================================================ -- 5. Deployment Targets (8 targets across multiple connector types) -- ============================================================ INSERT INTO deployment_targets (id, name, type, agent_id, config, enabled, created_at, updated_at) VALUES - ('tgt-nginx-prod', 'NGINX Production', 'nginx', 'ag-web-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '120 days', NOW()), - ('tgt-nginx-staging', 'NGINX Staging', 'nginx', 'ag-web-staging', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW()), - ('tgt-haproxy-prod', 'HAProxy Production', 'haproxy', 'ag-lb-prod', '{"combined_pem_path": "/etc/haproxy/ssl/site.pem", "reload_command": "systemctl reload haproxy"}', true, NOW() - INTERVAL '150 days', NOW()), - ('tgt-apache-prod', 'Apache Production', 'apache', 'ag-web-prod', '{"cert_path": "/etc/httpd/ssl/cert.pem", "key_path": "/etc/httpd/ssl/key.pem", "chain_path": "/etc/httpd/ssl/chain.pem", "reload_command": "apachectl graceful"}', true, NOW() - INTERVAL '100 days', NOW()), - ('tgt-iis-prod', 'IIS Production', 'iis', 'ag-iis-prod', '{"site_name": "Default Web Site", "binding_info": "*:443:"}', true, NOW() - INTERVAL '60 days', NOW()), - ('tgt-traefik-prod', 'Traefik Production', 'traefik', 'ag-k8s-prod', '{"watch_dir": "/etc/traefik/dynamic/certs"}', true, NOW() - INTERVAL '30 days', NOW()), - ('tgt-caddy-prod', 'Caddy Production', 'caddy', 'ag-edge-01', '{"mode": "api", "admin_url": "http://localhost:2019"}', true, NOW() - INTERVAL '45 days', NOW()), - ('tgt-nginx-data', 'NGINX Data Services', 'nginx', 'ag-data-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW()) + ('tgt-nginx-prod', 'NGINX Production', 'NGINX', 'ag-web-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '120 days', NOW()), + ('tgt-nginx-staging', 'NGINX Staging', 'NGINX', 'ag-web-staging', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW()), + ('tgt-haproxy-prod', 'HAProxy Production', 'HAProxy', 'ag-lb-prod', '{"combined_pem_path": "/etc/haproxy/ssl/site.pem", "reload_command": "systemctl reload haproxy"}', true, NOW() - INTERVAL '150 days', NOW()), + ('tgt-apache-prod', 'Apache Production', 'Apache', 'ag-web-prod', '{"cert_path": "/etc/httpd/ssl/cert.pem", "key_path": "/etc/httpd/ssl/key.pem", "chain_path": "/etc/httpd/ssl/chain.pem", "reload_command": "apachectl graceful"}', true, NOW() - INTERVAL '100 days', NOW()), + ('tgt-iis-prod', 'IIS Production', 'IIS', 'ag-iis-prod', '{"site_name": "Default Web Site", "binding_info": "*:443:"}', true, NOW() - INTERVAL '60 days', NOW()), + ('tgt-traefik-prod', 'Traefik Production', 'Traefik', 'ag-k8s-prod', '{"watch_dir": "/etc/traefik/dynamic/certs"}', true, NOW() - INTERVAL '30 days', NOW()), + ('tgt-caddy-prod', 'Caddy Production', 'Caddy', 'ag-edge-01', '{"mode": "api", "admin_url": "http://localhost:2019"}', true, NOW() - INTERVAL '45 days', NOW()), + ('tgt-nginx-data', 'NGINX Data Services', 'NGINX', 'ag-data-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW()) ON CONFLICT (id) DO NOTHING; -- ============================================================ @@ -128,7 +128,7 @@ INSERT INTO certificate_profiles (id, name, description, allowed_key_algorithms, ON CONFLICT (id) DO NOTHING; -- ============================================================ --- 7. Managed Certificates (35 certs across multiple issuers and environments) +-- 7. Managed Certificates (32 certs across multiple issuers and environments) -- ============================================================ INSERT INTO managed_certificates (id, name, common_name, sans, environment, owner_id, team_id, issuer_id, renewal_policy_id, status, expires_at, tags, last_renewal_at, last_deployment_at, created_at, updated_at) VALUES -- ---- Active, healthy production certs (Local CA) ----