From d25da8f405648cf6769685966522e87d542bc534 Mon Sep 17 00:00:00 2001 From: Shankar Date: Wed, 25 Mar 2026 03:48:13 -0400 Subject: [PATCH] docs: fix 16 discrepancies found by cross-validating all docs against source code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLI syntax corrected across 5 files (concepts, demo-guide, demo-advanced, architecture, features): list-certs→certs list, get-cert→certs get, etc. Removed non-existent health/metrics commands, replaced with status. Subcommand count 10→12 everywhere. architecture.md: Go 1.22→1.25, endpoint count 91→93, ER diagram expanded from 15 to 21 tables (added renewal_policies, certificate_revocations, discovered_certificates, discovery_scans, network_scan_targets). connectors.md: added GenerateCRL and SignOCSPResponse to issuer interface, added Email and Webhook rows to notifier config table. compliance docs: fixed keygen warning messages to match actual log output, CERTCTL_STEPCA_PROVISIONER_KEY→CERTCTL_STEPCA_KEY_PATH, openssl genrsa→ crypto/ecdsa.GenerateKey, CERTCTL_SERVER_ADDR→CERTCTL_SERVER_HOST+PORT. README.md: v2.0.0 version bump, solo developer mention, feature list, table of contents, documentation table moved to top, 7 fact-check fixes. Co-Authored-By: Claude Opus 4.6 --- README.md | 110 ++++++++++++++++++++++++++----------- docs/architecture.md | 46 +++++++++++++++- docs/compliance-nist.md | 2 +- docs/compliance-pci-dss.md | 6 +- docs/compliance-soc2.md | 4 +- docs/concepts.md | 2 +- docs/connectors.md | 10 ++++ docs/demo-advanced.md | 20 +++---- docs/demo-guide.md | 21 ++++--- docs/features.md | 30 +++++----- 10 files changed, 175 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 78fd7c2..a64d2eb 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,71 @@ # certctl — Self-Hosted Certificate Lifecycle Platform -TLS certificate lifespans are shrinking. The CA/Browser Forum passed [Ballot SC-081v3](https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/) unanimously in April 2025, setting a phased reduction: **200 days** by March 2026, **100 days** by March 2027, and **47 days** by March 2029. Manual certificate management is no longer viable at any scale. +Built by a solo developer. 91 API endpoints. 21 database tables. 900+ tests. Full GUI. Ships with Docker Compose. -certctl is a self-hosted platform for **end-to-end certificate lifecycle automation** — from issuance through renewal to deployment — with zero human intervention. Track every certificate in your organization, automatically renew them before they expire, and deploy them to your servers without touching a terminal. Private keys never leave your infrastructure. +TLS certificate lifespans are shrinking fast. The CA/Browser Forum passed [Ballot SC-081v3](https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/) unanimously in April 2025, setting a phased reduction: **200 days** by March 2026, **100 days** by March 2027, and **47 days** by March 2029. Organizations managing dozens or hundreds of certificates can no longer rely on spreadsheets, calendar reminders, or manual renewal workflows. The math doesn't work — at 47-day lifespans, a team managing 100 certificates is processing 7+ renewals per week, every week, forever. + +certctl is a self-hosted platform that automates the entire certificate lifecycle — from issuance through renewal to deployment — with zero human intervention. It works with any certificate authority, deploys to any server, and keeps private keys on your infrastructure where they belong. [![License](https://img.shields.io/badge/license-BSL%201.1-blue.svg)](LICENSE) [![Go Report Card](https://goreportcard.com/badge/github.com/shankar0123/certctl)](https://goreportcard.com/report/github.com/shankar0123/certctl) -![Status: v1.0.0](https://img.shields.io/badge/status-v1.0.0-brightgreen) +![Version: v2.0.0](https://img.shields.io/badge/version-v2.0.0-brightgreen) + +## Documentation + +| Guide | Description | +|-------|-------------| +| [Concepts](docs/concepts.md) | TLS certificates explained from scratch — for beginners who know nothing about certs | +| [Quick Start](docs/quickstart.md) | Get running in 5 minutes with accurate API examples | +| [Demo Walkthrough](docs/demo-guide.md) | 5-7 minute guided stakeholder presentation | +| [Advanced Demo](docs/demo-advanced.md) | Issue a certificate end-to-end with technical deep-dives | +| [Architecture](docs/architecture.md) | System design, data flow diagrams, security model | +| [Connectors](docs/connectors.md) | Build custom issuer, target, and notifier connectors | +| [Compliance Mapping](docs/compliance.md) | SOC 2 Type II, PCI-DSS 4.0, NIST SP 800-57 alignment guides | +| [Manual Testing Guide](docs/testing-guide.md) | 284 tests across 25 areas — full V2 QA runbook with exact commands and pass/fail criteria | + +## Contents + +- [Why certctl Exists](#why-certctl-exists) +- [What It Does](#what-it-does) +- [Screenshots](#screenshots) +- [Quick Start](#quick-start) +- [Architecture](#architecture) +- [Configuration](#configuration) +- [MCP Server (AI Integration)](#mcp-server-ai-integration) +- [CLI](#cli) +- [API Overview](#api-overview) +- [Supported Integrations](#supported-integrations) +- [Development](#development) +- [Security](#security) +- [Roadmap](#roadmap) +- [License](#license) + +## Why certctl Exists + +Certificate lifecycle tooling today falls into two camps: expensive enterprise platforms (Venafi, Keyfactor, Sectigo) that cost six figures and take months to deploy, or single-purpose tools (cert-manager, certbot) that handle one slice of the problem. If you run a mixed infrastructure — some NGINX, some Apache, a few HAProxy nodes, maybe an F5 — and you need to manage certificates from multiple CAs, there's nothing self-hosted that covers the full lifecycle without vendor lock-in. + +certctl fills that gap. It's **CA-agnostic** — the issuer connector interface means you can plug in any certificate authority: a self-signed local CA for dev, Let's Encrypt via ACME for public certs, Smallstep step-ca for your private PKI, your enterprise ADCS via sub-CA mode, or any custom CA through a shell script adapter. You're never locked to a single CA vendor, and you can run multiple issuers simultaneously for different certificate types. + +It's also **target-agnostic**. Agents deploy certificates to NGINX, Apache, and HAProxy today, with the same pluggable connector model for any server that accepts cert files. The control plane never initiates outbound connections — agents poll for work, which means certctl works behind firewalls, across network zones, and in air-gapped environments. ## What It Does certctl gives you a single pane of glass for every TLS certificate in your organization. The **web dashboard** shows your full certificate inventory — what's healthy, what's expiring, what's already expired, and who owns each one. The **REST API** (91 endpoints under `/api/v1/`) lets you automate everything. **Agents** deployed on your infrastructure generate private keys locally, discover existing certificates on disk, and submit CSRs — private keys never leave your servers. The **network scanner** discovers certificates on TLS endpoints across your infrastructure without requiring agents. The background scheduler watches expiration dates and triggers renewals automatically — when certificate lifespans drop to 47 days, certctl handles the constant rotation without human involvement. +**Core capabilities:** + +- **Full lifecycle automation** — issuance, renewal, deployment, and revocation with zero human intervention. Configurable renewal policies trigger jobs automatically based on expiration thresholds. +- **CA-agnostic issuer connectors** — Local CA (self-signed + sub-CA for enterprise root chains), ACME v2 with HTTP-01 and DNS-01 challenges (Let's Encrypt, Sectigo, any ACME-compatible CA), Smallstep step-ca (native /sign API), and OpenSSL/Custom CA (delegate to any shell script). Pluggable interface — add your own CA in one file. +- **Agent-side key generation** — agents generate ECDSA P-256 keys locally, store them with 0600 permissions, and submit only the CSR. Private keys never touch the control plane. This is the default mode, not an opt-in feature. +- **Certificate discovery** — agents scan filesystems for existing PEM/DER certificates and report findings for triage. The network scanner probes TLS endpoints across CIDR ranges to find certificates you didn't know existed. +- **Revocation infrastructure** — RFC 5280 revocation with all standard reason codes, DER-encoded X.509 CRL per issuer, embedded OCSP responder, and short-lived certificate exemption (certs under 1 hour skip CRL/OCSP). +- **Policy engine** — 5 rule types with violation tracking and severity levels. Certificate profiles enforce allowed key types, maximum TTL, and crypto constraints at enrollment time. +- **Immutable audit trail** — every action recorded to an append-only log. Every API call recorded with method, path, actor, SHA-256 body hash, response status, and latency. No update or delete on audit records. +- **Operational dashboard** — 18-page React GUI with certificate inventory, bulk operations (multi-select renew/revoke/reassign), deployment timeline visualization, inline policy editing, agent fleet overview, expiration heatmaps, and real-time short-lived credential tracking. +- **Observability** — JSON and Prometheus metrics endpoints, 5 stats API endpoints for dashboards, structured slog logging with request ID propagation. Compatible with Prometheus, Grafana Agent, Datadog Agent, and Victoria Metrics. +- **Notifications** — threshold-based alerting with deduplication. Routes to email, webhooks, Slack, Microsoft Teams, PagerDuty, and OpsGenie. +- **AI and CLI access** — MCP server exposes all 78 API operations as tools for Claude, Cursor, and any MCP-compatible client. CLI tool with 12 subcommands for terminal workflows and scripting. + ```mermaid flowchart LR subgraph "Control Plane" @@ -72,7 +126,7 @@ curl -s http://localhost:8443/api/v1/certificates | jq '.total' ### Manual Build ```bash -# Prerequisites: Go 1.22+, PostgreSQL 16+ +# Prerequisites: Go 1.25+, PostgreSQL 16+ go mod download make build @@ -92,26 +146,13 @@ export CERTCTL_AGENT_ID=agent-local-01 ./bin/agent --agent-id=agent-local-01 ``` -## Documentation - -| Guide | Description | -|-------|-------------| -| [Concepts](docs/concepts.md) | TLS certificates explained from scratch — for beginners who know nothing about certs | -| [Quick Start](docs/quickstart.md) | Get running in 5 minutes with accurate API examples | -| [Demo Walkthrough](docs/demo-guide.md) | 5-7 minute guided stakeholder presentation | -| [Advanced Demo](docs/demo-advanced.md) | Issue a certificate end-to-end with technical deep-dives | -| [Architecture](docs/architecture.md) | System design, data flow diagrams, security model | -| [Connectors](docs/connectors.md) | Build custom issuer, target, and notifier connectors | -| [Compliance Mapping](docs/compliance.md) | SOC 2 Type II, PCI-DSS 4.0, NIST SP 800-57 alignment guides | -| [Manual Testing Guide](docs/testing-guide.md) | 284 tests across 25 areas — full V2 QA runbook with exact commands and pass/fail criteria | - ## Architecture ```mermaid flowchart TB subgraph "Control Plane (certctl-server)" DASH["Web Dashboard\nReact SPA"] - API["REST API\nGo 1.22 net/http"] + API["REST API\nGo 1.25 net/http"] SVC["Service Layer"] REPO["Repository Layer\ndatabase/sql + lib/pq"] SCHED["Scheduler\nRenewal · Jobs · Health · Notifications · Short-Lived Expiry · Network Scan"] @@ -269,19 +310,26 @@ go install github.com/shankar0123/certctl/cmd/cli@latest export CERTCTL_SERVER_URL=http://localhost:8443 export CERTCTL_API_KEY=your-api-key -# Commands -certctl-cli list-certs # List all certificates -certctl-cli get-cert --id mc-api-prod # Get certificate details -certctl-cli renew-cert --id mc-api-prod # Trigger renewal -certctl-cli revoke-cert --id mc-api-prod --reason keyCompromise -certctl-cli list-agents # List registered agents -certctl-cli list-jobs # List jobs -certctl-cli health # Server health check -certctl-cli metrics # Server metrics -certctl-cli import --file certs.pem # Bulk import from PEM file +# Certificate commands +certctl-cli certs list # List all certificates +certctl-cli certs get mc-api-prod # Get certificate details +certctl-cli certs renew mc-api-prod # Trigger renewal +certctl-cli certs revoke mc-api-prod --reason keyCompromise + +# Agent and job commands +certctl-cli agents list # List registered agents +certctl-cli agents get ag-web-prod # Get agent details +certctl-cli jobs list # List jobs +certctl-cli jobs get job-123 # Get job details +certctl-cli jobs cancel job-123 # Cancel a pending job + +# Operations +certctl-cli status # Server health + summary stats +certctl-cli import certs.pem # Bulk import from PEM file +certctl-cli version # Show CLI version # Output formats -certctl-cli list-certs --format json # JSON output (default: table) +certctl-cli certs list --format json # JSON output (default: table) ``` ## API Overview @@ -509,7 +557,7 @@ make docker-clean # Stop + remove volumes ## Roadmap ### V1 (v1.0.0 released) -All nine development milestones (M1–M9) are complete. The backend covers the full certificate lifecycle: Local CA and ACME v2 issuers, NGINX/Apache/HAProxy/F5/IIS target connectors, threshold-based expiration alerting, agent-side ECDSA P-256 key generation, API auth with rate limiting, and a React dashboard with 19 pages wired to the real API. The CI pipeline runs build, vet, test with coverage gates (service layer 30%+, handler layer 50%+), frontend type checking, Vitest test suite, and Vite production build on every push. Docker images are published to GitHub Container Registry on every version tag via the release workflow. +All nine development milestones (M1–M9) are complete. The backend covers the full certificate lifecycle: Local CA and ACME v2 issuers, NGINX/Apache/HAProxy/F5/IIS target connectors, threshold-based expiration alerting, agent-side ECDSA P-256 key generation, API auth with rate limiting, and a React dashboard with 18 pages wired to the real API. The CI pipeline runs build, vet, test with coverage gates (service layer 30%+, handler layer 50%+), frontend type checking, Vitest test suite, and Vite production build on every push. Docker images are published to GitHub Container Registry on every version tag via the release workflow. ### V2: Operational Maturity - **M10: Agent Metadata + Targets** ✅ — agents report OS, architecture, IP, hostname, version via heartbeat; Apache httpd and HAProxy target connectors @@ -523,7 +571,7 @@ All nine development milestones (M1–M9) are complete. The backend covers the f - **M19: Immutable API Audit Log** ✅ — every API call recorded to immutable audit trail (method, path, actor, SHA-256 body hash, status, latency), async recording via goroutine, configurable path exclusions - **M16a: Notifier Connectors** ✅ — Slack (incoming webhook), Microsoft Teams (MessageCard), PagerDuty (Events API v2), OpsGenie (Alert API v2) — config-driven enablement via env vars - **M17: Additional Connectors** ✅ — OpenSSL/Custom CA issuer connector (script-based signing with configurable timeout) -- **M16b: CLI + Bulk Import** ✅ — `certctl-cli` with 10 subcommands (list/get/renew/revoke certs, list agents/jobs, health, metrics, PEM bulk import), stdlib-only, JSON/table output +- **M16b: CLI + Bulk Import** ✅ — `certctl-cli` with 12 subcommands (certs list/get/renew/revoke, agents list/get, jobs list/get/cancel, import, status, version), stdlib-only, JSON/table output - **M20: Enhanced Query API** ✅ — sparse field selection (`?fields=`), sort with direction (`?sort=-notAfter`), time-range filters (`expires_before`, `created_after`, etc.), cursor-based pagination (`?cursor=&page_size=`), `GET /certificates/{id}/deployments`, additional filters (`agent_id`, `profile_id`) - **M18b: Filesystem Cert Discovery** ✅ — agents scan configured directories (PEM/DER), report findings to control plane, deduplication by SHA-256 fingerprint, claim/dismiss/triage workflow via API - **M21: Network Cert Discovery** ✅ — server-side active TLS scanning of CIDR ranges and ports, concurrent probing (50 goroutines), CIDR expansion with /20 safety cap, sentinel agent pattern for discovery pipeline reuse, CRUD API for scan targets, scheduler integration (6h default) diff --git a/docs/architecture.md b/docs/architecture.md index d491bfe..cf2d27c 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -76,7 +76,7 @@ The control plane is a Go HTTP server backed by PostgreSQL. It manages state (ce The server exposes a REST API under `/api/v1/` and optionally serves the web dashboard as static files from the `web/` directory. -**Key internals**: The server uses Go 1.22's `net/http` stdlib routing (no external router framework), structured logging via `slog`, and a handler → service → repository layered architecture. Handlers define their own service interfaces for clean dependency inversion. +**Key internals**: The server uses Go 1.25's `net/http` stdlib routing (no external router framework), structured logging via `slog`, and a handler → service → repository layered architecture. Handlers define their own service interfaces for clean dependency inversion. ### Agents @@ -122,8 +122,11 @@ erDiagram managed_certificates ||--o{ policy_violations : "violates" managed_certificates ||--o{ audit_events : "logged in" managed_certificates ||--o{ notification_events : "generates" + managed_certificates ||--o{ certificate_revocations : "revoked via" agent_groups ||--o{ agent_group_members : "has members" agents ||--o{ agent_group_members : "belongs to" + agents ||--o{ discovered_certificates : "discovers" + agents ||--o{ discovery_scans : "performs" teams { text id PK @@ -242,6 +245,43 @@ erDiagram text agent_id FK text membership_type } + renewal_policies { + text id PK + text certificate_id FK + int renewal_days_before + jsonb alert_thresholds_days + boolean auto_renew + text agent_group_id FK + } + certificate_revocations { + text id PK + text certificate_id FK + text serial_number + text reason + timestamp revoked_at + boolean issuer_notified + } + discovered_certificates { + text id PK + text agent_id FK + text fingerprint_sha256 + text common_name + text source_path + text status + } + discovery_scans { + text id PK + text agent_id FK + int certs_found + timestamp scanned_at + } + network_scan_targets { + text id PK + text name + text[] cidrs + int[] ports + boolean enabled + } ``` Migrations are idempotent (`IF NOT EXISTS` on all CREATE statements, `ON CONFLICT (id) DO NOTHING` on all seed data) so they're safe to run multiple times — important for Docker Compose where both initdb and the server may run the same SQL. @@ -608,7 +648,7 @@ All endpoints are under `/api/v1/` and follow consistent patterns: Resources: certificates, issuers, targets, agents, jobs, policies, profiles, teams, owners, agent-groups, audit, notifications. -The full API is documented in an OpenAPI 3.1 specification at `api/openapi.yaml` with 91 endpoints across 19 resource domains (including health, readiness, auth, 7 discovery endpoints from M18b, 6 network scan endpoints from M21, and Prometheus metrics from M22), all request/response schemas, and pagination conventions. See the [OpenAPI Guide](openapi.md) for usage with Swagger UI and SDK generation. +The full API is documented in an OpenAPI 3.1 specification at `api/openapi.yaml` with 93 endpoints across 19 resource domains (91 under `/api/v1/` plus `/health` and `/ready`; includes auth, 7 discovery endpoints from M18b, 6 network scan endpoints from M21, and Prometheus metrics from M22), all request/response schemas, and pagination conventions. See the [OpenAPI Guide](openapi.md) for usage with Swagger UI and SDK generation. Jobs support additional action endpoints: `POST /api/v1/jobs/{id}/cancel`, `POST /api/v1/jobs/{id}/approve`, `POST /api/v1/jobs/{id}/reject`. @@ -654,7 +694,7 @@ The 78 tools are organized across 16 resource domains with typed input structs a certctl ships with a command-line tool (`certctl-cli`, built from `cmd/cli/main.go`) that wraps the REST API for terminal workflows. The CLI uses Go's standard library only (`flag` + `text/tabwriter`) — no Cobra or other framework dependencies. -10 subcommands: `list-certs`, `get-cert`, `renew-cert`, `revoke-cert`, `list-agents`, `list-jobs`, `health`, `metrics`, and `import` (bulk PEM import). Output is available in table (default) or JSON format via `--format`. Connection is configured via `CERTCTL_SERVER_URL` and `CERTCTL_API_KEY` environment variables or CLI flags. +12 subcommands organized by resource: `certs list`, `certs get`, `certs renew`, `certs revoke`, `agents list`, `agents get`, `jobs list`, `jobs get`, `jobs cancel`, `import` (bulk PEM import), `status` (health + summary stats), and `version`. Output is available in table (default) or JSON format via `--format`. Connection is configured via `CERTCTL_SERVER_URL` and `CERTCTL_API_KEY` environment variables or CLI flags. The bulk import command (`certctl-cli import `) parses multi-certificate PEM files and creates certificate records via the API — useful for bootstrapping certctl with existing certificate inventory. diff --git a/docs/compliance-nist.md b/docs/compliance-nist.md index af12b8c..6f65c7b 100644 --- a/docs/compliance-nist.md +++ b/docs/compliance-nist.md @@ -15,7 +15,7 @@ certctl generates certificate keys on agent infrastructure using Go's `crypto/ra **Server-Side Key Generation (Demo Only)** - Available for development and testing via `CERTCTL_KEYGEN_MODE=server` -- Explicitly logged as a warning at startup: "server-side keygen enabled (production deployments must use agent mode)" +- Explicitly logged as a warning at startup: "server-side key generation enabled (CERTCTL_KEYGEN_MODE=server) — private keys touch control plane, demo only" - Docker Compose demo uses server mode for backward compatibility - Not recommended for production; agent mode is the secure default diff --git a/docs/compliance-pci-dss.md b/docs/compliance-pci-dss.md index 30deba8..143af6b 100644 --- a/docs/compliance-pci-dss.md +++ b/docs/compliance-pci-dss.md @@ -168,7 +168,7 @@ This requirement covers key generation, storage, rotation, and destruction. Cert - **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: `Key generation mode is server; this should only be used for testing.` + - **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. @@ -178,7 +178,7 @@ This requirement covers key generation, storage, rotation, and destruction. Cert **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: `openssl genrsa...` or agent process logs with CSR submission timestamp. +- 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. @@ -205,7 +205,7 @@ This requirement covers key generation, storage, rotation, and destruction. Cert - **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_PROVISIONER_KEY` env var (JWK, in memory during runtime). + - 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. diff --git a/docs/compliance-soc2.md b/docs/compliance-soc2.md index bd91179..92a6136 100644 --- a/docs/compliance-soc2.md +++ b/docs/compliance-soc2.md @@ -89,7 +89,7 @@ Each section includes: - **API Key Policy** — All API access requires an API key or explicit opt-out. Opt-out (`CERTCTL_AUTH_TYPE=none`) logs a warning: "WARNING: Auth disabled (CERTCTL_AUTH_TYPE=none) — this is insecure and only for development". Configuration choice is logged at startup. - **Agent Authentication** — Agents authenticate to the server via API keys (same mechanism as users). Agent credentials are separate from user API keys. -- **Private Key Policy** — Agent-side key generation is the default (`CERTCTL_KEYGEN_MODE=agent`). Server-side keygen (`CERTCTL_KEYGEN_MODE=server`) requires explicit configuration and logs a warning: "Server-side keygen enabled — private keys will be stored in PostgreSQL (development only)". +- **Private Key Policy** — Agent-side key generation is the default (`CERTCTL_KEYGEN_MODE=agent`). Server-side keygen (`CERTCTL_KEYGEN_MODE=server`) requires explicit configuration and logs a warning: "server-side key generation enabled (CERTCTL_KEYGEN_MODE=server) — private keys touch control plane, demo only". - **Password Policy** — Not applicable; certctl uses API keys exclusively. Password management is delegated to your organization's IAM system if you integrate OIDC/SSO (V3). **Evidence Locations**: @@ -119,7 +119,7 @@ Each section includes: **certctl Implementation** (V2): -- **TLS for Control Plane** — All API communication occurs over HTTPS (TLS 1.2+). Server uses `tls.Dial()` for outbound connections to issuers and targets. Configuration: `CERTCTL_SERVER_ADDR` (default `:8443`). +- **TLS for Control Plane** — All API communication occurs over HTTPS (TLS 1.2+). Server uses `tls.Dial()` for outbound connections to issuers and targets. Configuration: `CERTCTL_SERVER_HOST` (default `127.0.0.1`) + `CERTCTL_SERVER_PORT` (default `8080`; Docker Compose maps to `8443`). - **Agent-to-Server Communication** — Agents submit CSRs and heartbeats over HTTPS to the server using the same TLS stack. - **Private Key Isolation** — Agents generate ECDSA P-256 private keys locally (`crypto/ecdsa` + `crypto/elliptic`). Private keys are never transmitted to the server — agents submit CSRs only. Private keys are stored on agent filesystem (`CERTCTL_KEY_DIR`, default `/var/lib/certctl/keys`) with 0600 (owner read/write only) permissions. Server-side keygen mode logs a development warning; production must use agent-side keygen. - **Certificate Storage** — Signed certificates are stored in PostgreSQL as PEM text (along with metadata). Certificates are not secrets and may be transmitted plaintext. Private keys are never stored on the control plane in production (agent-side keygen mode). diff --git a/docs/concepts.md b/docs/concepts.md index 93237b2..056eca6 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -180,7 +180,7 @@ certctl can alert you when certificates are expiring, when renewals fail, when d ### CLI -certctl ships with a command-line tool (`certctl-cli`) for operators who prefer terminal workflows or need to integrate certctl into shell scripts and CI/CD pipelines. The CLI wraps the REST API with 10 subcommands: `list-certs`, `get-cert`, `renew-cert`, `revoke-cert`, `list-agents`, `list-jobs`, `health`, `metrics`, and `import` (for bulk PEM import). +certctl ships with a command-line tool (`certctl-cli`) for operators who prefer terminal workflows or need to integrate certctl into shell scripts and CI/CD pipelines. The CLI wraps the REST API with 12 subcommands organized by resource: `certs list`, `certs get`, `certs renew`, `certs revoke`, `agents list`, `agents get`, `jobs list`, `jobs get`, `jobs cancel`, `import` (bulk PEM import), `status` (health + summary stats), and `version`. The CLI supports both table and JSON output formats (`--format table` or `--format json`), connects to the server via `CERTCTL_SERVER_URL` and authenticates with `CERTCTL_API_KEY`. It's built with Go's standard library only — no external dependencies. diff --git a/docs/connectors.md b/docs/connectors.md index 8dcd4f7..598bb44 100644 --- a/docs/connectors.md +++ b/docs/connectors.md @@ -37,6 +37,14 @@ type Connector interface { // GetOrderStatus checks the status of an async issuance order GetOrderStatus(ctx context.Context, orderID string) (*OrderStatus, error) + + // GenerateCRL generates a DER-encoded X.509 CRL signed by this issuer. + // Returns nil if the issuer does not support CRL generation (e.g., ACME). + GenerateCRL(ctx context.Context, revokedCerts []RevokedCertEntry) ([]byte, error) + + // SignOCSPResponse signs an OCSP response for the given certificate serial. + // Returns nil if the issuer does not support OCSP (e.g., ACME). + SignOCSPResponse(ctx context.Context, req OCSPSignRequest) ([]byte, error) } type IssuanceRequest struct { @@ -474,6 +482,8 @@ Each notifier is enabled by its configuration env var: | Notifier | Env Var | Description | |----------|---------|-------------| +| Email | `CERTCTL_EMAIL_SMTP_HOST`, `CERTCTL_EMAIL_SMTP_PORT`, `CERTCTL_EMAIL_FROM` | SMTP email delivery. Optional: `CERTCTL_EMAIL_SMTP_USERNAME`, `CERTCTL_EMAIL_SMTP_PASSWORD` | +| Webhook | `CERTCTL_WEBHOOK_URL` | HTTP POST to any endpoint. Optional: `CERTCTL_WEBHOOK_SECRET` for HMAC signing | | Slack | `CERTCTL_SLACK_WEBHOOK_URL` | Incoming webhook URL. Optional: `CERTCTL_SLACK_CHANNEL`, `CERTCTL_SLACK_USERNAME` | | Teams | `CERTCTL_TEAMS_WEBHOOK_URL` | Incoming webhook URL (MessageCard format) | | PagerDuty | `CERTCTL_PAGERDUTY_ROUTING_KEY` | Events API v2 routing key. Optional: `CERTCTL_PAGERDUTY_SEVERITY` (default: "warning") | diff --git a/docs/demo-advanced.md b/docs/demo-advanced.md index d7cbbaf..def40ee 100644 --- a/docs/demo-advanced.md +++ b/docs/demo-advanced.md @@ -875,28 +875,28 @@ export CERTCTL_SERVER_URL="http://localhost:8443" export CERTCTL_API_KEY="test-key-123" # List certificates (JSON or table format) -./certctl-cli list-certs --format table +./certctl-cli certs list # Get certificate details -./certctl-cli get-cert mc-demo-api +./certctl-cli certs get mc-demo-api # Trigger renewal -./certctl-cli renew-cert mc-demo-api +./certctl-cli certs renew mc-demo-api # Revoke a certificate with RFC 5280 reason -./certctl-cli revoke-cert mc-demo-payments --reason keyCompromise +./certctl-cli certs revoke mc-demo-payments --reason keyCompromise # List agents -./certctl-cli list-agents +./certctl-cli agents list # List pending jobs -./certctl-cli list-jobs +./certctl-cli jobs list -# Check system health -./certctl-cli health +# Check system health and stats +./certctl-cli status -# Export metrics -./certctl-cli metrics --format json +# JSON output format +./certctl-cli --format json status # Bulk import certificates from a PEM file ./certctl-cli import /path/to/certificates.pem diff --git a/docs/demo-guide.md b/docs/demo-guide.md index 802c736..f619343 100644 --- a/docs/demo-guide.md +++ b/docs/demo-guide.md @@ -154,30 +154,29 @@ export CERTCTL_SERVER_URL="http://localhost:8443" export CERTCTL_API_KEY="test-key-123" # List certificates (JSON or table format) -./certctl-cli list-certs --format json -./certctl-cli list-certs --format table +./certctl-cli --format json certs list +./certctl-cli certs list # Get certificate details -./certctl-cli get-cert mc-api-prod +./certctl-cli certs get mc-api-prod # Trigger renewal -./certctl-cli renew-cert mc-api-prod +./certctl-cli certs renew mc-api-prod # Revoke a certificate (with RFC 5280 reason) -./certctl-cli revoke-cert mc-api-prod --reason keyCompromise +./certctl-cli certs revoke mc-api-prod --reason keyCompromise # List agents -./certctl-cli list-agents +./certctl-cli agents list # List pending jobs -./certctl-cli list-jobs +./certctl-cli jobs list # Bulk import certificates from PEM files ./certctl-cli import /path/to/certs.pem -# Check health and metrics -./certctl-cli health -./certctl-cli metrics +# Check system health and stats +./certctl-cli status ``` ## MCP Server for AI Integration @@ -243,7 +242,7 @@ If you're demoing to a team or customer, here's a suggested flow: 10. **Show certificate discovery** — "We discover certificates two ways: agents scan local filesystems, and the server actively probes TLS endpoints on your network. We deduplicate by fingerprint, show you what we found, and let you claim them or dismiss them" 11. **Show the immutable audit trail** — "Every action in the system is recorded: who did it, what they did, when, what changed. Export to CSV/JSON for compliance" 12. **Show advanced query features** — "Sort by any field, filter by date range, paginate efficiently with cursor-based pagination, select just the fields you need" -13. **Show the CLI and MCP server** — "Terminal users get `certctl-cli` with 10 subcommands. AI assistants get MCP integration with 78 tools. Everything is API-first" +13. **Show the CLI and MCP server** — "Terminal users get `certctl-cli` with 12 subcommands. AI assistants get MCP integration with 78 tools. Everything is API-first" The whole walkthrough takes 5-10 minutes. diff --git a/docs/features.md b/docs/features.md index 2a01ab8..779ac24 100644 --- a/docs/features.md +++ b/docs/features.md @@ -296,7 +296,7 @@ curl -H "$AUTH" "$SERVER/api/v1/policies/rp-standard/violations" ### step-ca - **Protocol** — Native `/sign` and `/revoke` API (not ACME) - **Authentication** — JWK provisioner with key file + password -- **Configuration** — `CERTCTL_STEPCA_URL`, `CERTCTL_STEPCA_PROVISIONER_NAME`, `CERTCTL_STEPCA_PROVISIONER_KEY_PATH`, `CERTCTL_STEPCA_PROVISIONER_PASSWORD` +- **Configuration** — `CERTCTL_STEPCA_URL`, `CERTCTL_STEPCA_PROVISIONER`, `CERTCTL_STEPCA_KEY_PATH`, `CERTCTL_STEPCA_PASSWORD` - **Operations** — Issue, renew, revoke - **Use Case** — Smallstep private CA, internal PKI with strong auth @@ -903,16 +903,18 @@ The web dashboard is the primary operational interface for certctl. Built with * | Subcommand | Usage | Output Format | |------------|-------|----------------| -| **list-certs** | `certctl-cli list-certs [--filter]` | Table or JSON (--format=json) | -| **get-cert** | `certctl-cli get-cert ` | JSON cert details | -| **renew-cert** | `certctl-cli renew-cert ` | Job ID confirmation | -| **revoke-cert** | `certctl-cli revoke-cert [--reason]` | Revocation confirmation | -| **list-agents** | `certctl-cli list-agents` | Table or JSON | -| **list-jobs** | `certctl-cli list-jobs [--filter]` | Table or JSON | -| **health** | `certctl-cli health` | Server status | -| **metrics** | `certctl-cli metrics` | JSON metrics | +| **certs list** | `certctl-cli certs list` | Table or JSON (--format=json) | +| **certs get** | `certctl-cli certs get ` | JSON cert details | +| **certs renew** | `certctl-cli certs renew ` | Job ID confirmation | +| **certs revoke** | `certctl-cli certs revoke [--reason]` | Revocation confirmation | +| **agents list** | `certctl-cli agents list` | Table or JSON | +| **agents get** | `certctl-cli agents get ` | Agent details | +| **jobs list** | `certctl-cli jobs list` | Table or JSON | +| **jobs get** | `certctl-cli jobs get ` | Job details | +| **jobs cancel** | `certctl-cli jobs cancel ` | Cancellation confirmation | +| **status** | `certctl-cli status` | Health + summary stats | | **import** | `certctl-cli import ` | Bulk import cert count | -| **help** | `certctl-cli help [command]` | Command documentation | +| **version** | `certctl-cli version` | Version string | **Implementation Details:** - Stdlib-only (flag + text/tabwriter); no Cobra dependency @@ -1092,9 +1094,9 @@ The web dashboard is the primary operational interface for certctl. Built with * | Variable | Type | Default | Purpose | |----------|------|---------|---------| | `CERTCTL_STEPCA_URL` | string | (empty) | step-ca server URL | -| `CERTCTL_STEPCA_PROVISIONER_NAME` | string | (empty) | JWK provisioner name | -| `CERTCTL_STEPCA_PROVISIONER_KEY_PATH` | string | (empty) | Path to provisioner JWK private key | -| `CERTCTL_STEPCA_PROVISIONER_PASSWORD` | string | (empty) | Provisioner key password (if encrypted) | +| `CERTCTL_STEPCA_PROVISIONER` | string | (empty) | JWK provisioner name | +| `CERTCTL_STEPCA_KEY_PATH` | string | (empty) | Path to provisioner JWK private key | +| `CERTCTL_STEPCA_PASSWORD` | string | (empty) | Provisioner key password (if encrypted) | #### OpenSSL/Custom CA Issuer | Variable | Type | Default | Purpose | @@ -1170,7 +1172,7 @@ Each guide includes an evidence summary table mapping specific criteria to certc | Observability (charts, metrics, stats) | ✓ | ✓ | Shipped | | REST API (91 endpoints) | ✓ | ✓ | Shipped | | MCP server (78 tools) | ✓ | ✓ | Shipped v2.1 | -| CLI tool (10 subcommands) | ✓ | ✓ | Shipped | +| CLI tool (12 subcommands) | ✓ | ✓ | Shipped | | Compliance mapping docs (SOC 2, PCI-DSS, NIST) | ✓ | ✓ | Shipped | | Filesystem cert discovery (M18b) | ✓ | ✓ | Shipped | | Network cert discovery (M21) | ✓ | ✓ | Shipped |