Files
certctl/docs/features.md
T
shankar0123 667a30870d feat: M18b Filesystem Certificate Discovery — agent scanning, server dedup, triage API
Agent-side:
- Filesystem scanner walks configured directories (CERTCTL_DISCOVERY_DIRS)
- Parses PEM (.pem, .crt, .cer, .cert) and DER (.der) certificate files
- Extracts CN, SANs, serial, issuer/subject DN, validity, key info, SHA-256 fingerprint
- Reports discoveries to control plane on startup + every 6 hours
- Skips files >1MB and private key files

Server-side:
- Migration 000006: discovered_certificates + discovery_scans tables
- Domain model: DiscoveredCertificate, DiscoveryScan, DiscoveryReport
- Three triage states: Unmanaged, Managed (claimed), Dismissed
- Repository with upsert dedup (fingerprint + agent + path)
- Service layer: process reports, claim, dismiss, list, summary
- 7 new API endpoints (84 total):
  POST /agents/{id}/discoveries, GET /discovered-certificates,
  GET /discovered-certificates/{id}, POST .../claim, POST .../dismiss,
  GET /discovery-scans, GET /discovery-summary
- Audit trail: scan_completed, cert_claimed, cert_dismissed events

Tests: 28 new test functions (domain, handler, service layers)
Docs: README, quickstart, demo-guide, demo-advanced, architecture,
      concepts, connectors, features.md all updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 00:25:00 -04:00

925 lines
46 KiB
Markdown

# certctl V2 Feature Inventory
Complete reference of all features shipped in the V2 release (as of March 2026).
---
## API Surface
### Overview
- **84 endpoints** across 17 resource domains under `/api/v1/`
- REST API with HTTP semantics (GET, POST, PUT, DELETE)
- All endpoints require authentication by default (configurable)
- OpenAPI 3.1 spec with full schema documentation
### Authentication & Security
- **API Key Authentication** — SHA-256 hashed keys with constant-time comparison
- **Bearer Token Flow** — `Authorization: Bearer {api_key}` header
- **Auth Configuration** — Configurable via `CERTCTL_AUTH_TYPE` (api-key, jwt, none)
- **Auth Info Endpoint** — `GET /api/v1/auth/info` (no auth required for GUI pre-login detection)
- **Auth Check Endpoint** — `GET /api/v1/auth/check` (validate credentials)
### Rate Limiting
- **Token Bucket Algorithm** — Configurable requests-per-second (RPS) and burst size
- **429 Responses** — Rate limit exceeded with `Retry-After` header
- **Configuration** — `CERTCTL_RATE_LIMIT_ENABLED`, `CERTCTL_RATE_LIMIT_RPS` (default 50), `CERTCTL_RATE_LIMIT_BURST` (default 100)
### CORS
- **Configurable Per-Origin Allowlist** — `CERTCTL_CORS_ORIGINS` (comma-separated or wildcard)
- **Preflight Caching** — Standard CORS headers
### Query Features (M20)
| Feature | Details |
|---------|---------|
| **Sorting** | `?sort=-notAfter` (8 fields: notAfter, expiresAt, createdAt, updatedAt, commonName, name, status, environment) |
| **Pagination (Page-Based)** | `?page=1&per_page=50` (max 500, default 50) |
| **Pagination (Cursor)** | `?cursor=base64_token&page_size=100` (keyset pagination with `next_cursor` in response) |
| **Time-Range Filters** | `?expires_before=2026-12-31T23:59:59Z&expires_after=2026-01-01T00:00:00Z&created_after=...&updated_after=...` (RFC3339 format) |
| **Sparse Fields** | `?fields=id,common_name,status` (reduce response size) |
| **Additional Filters** | `?status=active&agent_id=a-xxx&profile_id=p-xxx&issuer_id=...&owner_id=...&team_id=...` |
### Endpoint Breakdown by Domain
| Domain | Endpoints | Key Operations |
|--------|-----------|-----------------|
| **Certificates** | 11 | List, create, get, update (archive), versions, deployments, trigger renewal, trigger deployment, revoke |
| **CRL & OCSP** | 3 | JSON CRL, DER CRL per issuer, OCSP responder |
| **Issuers** | 6 | List, create, get, update, delete, test connection |
| **Targets** | 5 | List, create, get, update, delete |
| **Agents** | 7 | List, register, get, heartbeat, CSR submit, certificate pickup, get work, report job status |
| **Jobs** | 5 | List, get, cancel, approve, reject |
| **Policies** | 6 | List, create, get, update, delete, list violations |
| **Profiles** | 5 | List, create, get, update, delete |
| **Teams** | 5 | List, create, get, update, delete |
| **Owners** | 5 | List, create, get, update, delete |
| **Agent Groups** | 6 | List, create, get, update, delete, list agents in group |
| **Discovery** | 7 | Submit scan results, list discovered certs, get detail, claim, dismiss, list scans, summary stats |
| **Audit** | 3 | List events, list by resource, export (CSV/JSON) |
| **Notifications** | 3 | List, get, mark as read |
| **Stats** | 5 | Dashboard summary, certificates by status, expiration timeline, job trends, issuance rate |
| **Metrics** | 1 | JSON metrics (gauges, counters, uptime) |
| **Health** | 4 | Health check, readiness check, auth info, auth check |
---
## Certificate Lifecycle
### Certificate States (8 total)
- **Pending** — Created, awaiting issuance
- **Active** — Valid and deployed
- **Expiring** — Within configured threshold (default 30 days)
- **Expired** — Past NotAfter date
- **RenewalInProgress** — Renewal job submitted
- **Failed** — Issuance or renewal failed
- **Revoked** — Revoked via POST /api/v1/certificates/{id}/revoke
- **Archived** — Manually archived via DELETE endpoint
### Key Generation Modes
| Mode | Details |
|------|---------|
| **Agent-Side (Default)** | ECDSA P-256 key generation on agent; private keys never touch control plane |
| **Server-Side (Demo Only)** | RSA-2048 key generation on server; requires explicit `CERTCTL_KEYGEN_MODE=server` with log warning |
### Certificate Versions
- Multiple versions per certificate (issuance, renewal)
- Each version includes: serial number, fingerprint, PEM-encoded chain
- CSR preserved for audit trail
- Version history with rollback capability in GUI
### AwaitingCSR Job State
- Renewal and issuance jobs pause when `CERTCTL_KEYGEN_MODE=agent`
- Agent generates ECDSA P-256 key locally, creates CSR, submits via `POST /api/v1/agents/{id}/csr`
- Server signs and stores certificate version
- Work endpoint enriched with `common_name` and `sans` for agent CSR generation
---
## Revocation Infrastructure
### Revocation API
- **Endpoint** — `POST /api/v1/certificates/{id}/revoke` (RFC 5280 reason codes)
- **8 Reason Codes** — unspecified, keyCompromise, caCompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold, privilegeWithdrawn
- **Best-Effort Issuer Notification** — Issuer connector failure doesn't block revocation
- **Immutable Recording** — `certificate_revocations` table with idempotent ON CONFLICT logic
### CRL (Certificate Revocation List)
- **JSON CRL** — `GET /api/v1/crl` returns entries array with serial numbers, reasons, revoked timestamps
- **DER X.509 CRL** — `GET /api/v1/crl/{issuer_id}` returns proper DER-encoded CRL signed by issuing CA
- **24-Hour Validity** — CRL refreshed every 24 hours
- **CA Key Required** — Sub-CA or issuing CA key must be available for signing
### OCSP Responder
- **Endpoint** — `GET /api/v1/ocsp/{issuer_id}/{serial}`
- **Responses** — good (certificate valid), revoked (in CRL), unknown (not issued by this CA)
- **Signed** — OCSP responses signed by issuing CA
### Short-Lived Certificate Exemption
- **Policy** — Certificates with TTL < 1 hour (from profile) skip CRL/OCSP
- **Rationale** — Expiry is sufficient revocation signal for short-lived certs
- **Exemption Applied** — During CRL generation and OCSP response construction
### Revocation Notifications
- Webhook + email notifications on revocation events
- Routed by certificate owner email via existing notifier system
---
## Certificate Profiles
### Profile Model
Named enrollment profiles defining certificate issuance constraints.
| Field | Details |
|-------|---------|
| **ID** | Prefixed text PK (p-xxx) |
| **Name** | Human-readable profile name |
| **Allowed Key Algorithms** | RSA, ECDSA, Ed25519 with minimum key sizes (e.g., RSA 2048+, ECDSA P-256+) |
| **Max TTL** | Maximum certificate lifetime (days or duration) |
| **Allowed EKUs** | Extended key usage OIDs (serverAuth, clientAuth, etc.) |
| **Required SANs** | Mandatory Subject Alternative Names (patterns or fixed values) |
| **Short-Lived Support** | TTL < 1 hour triggers CRL/OCSP exemption |
### GUI Management
- Full CRUD page with profile details
- Crypto constraint badges visible in list view
- Profile assignment dropdown on certificate detail
---
## Policy Engine
### Policy Rules (5 types)
| Rule Type | Purpose | Example |
|-----------|---------|---------|
| **AllowedIssuers** | Restrict which CAs can issue | Only LetsEncrypt or Internal CA |
| **AllowedDomains** | Domain whitelist/blacklist | Allow *.example.com, deny *.staging.example.com |
| **RequiredMetadata** | Enforce ownership, team | Require owner_id and team_id populated |
| **AllowedEnvironments** | Environment constraints | Restrict to production or staging |
| **RenewalLeadTime** | Minimum renewal window | Renew 60 days before expiry (minimum) |
### Violation Tracking
- **Severity Levels** — Warning, Error, Critical
- **Per-Policy Violations** — `GET /api/v1/policies/{id}/violations` with timestamp and violated certificate ID
- **Real-Time Evaluation** — Violations checked during issuance, renewal, and deployment
- **Audit Trail** — All violations logged to audit events table
### Policy Application Scope
- Applied at renewal policy level
- Scoped to agent groups via `agent_group_id` foreign key
- Rule set can be enabled/disabled per policy
---
## Issuer Connectors (4 Implemented)
### Local CA
- **Mode** — Self-signed (default) or sub-CA (production)
- **Sub-CA Configuration** — Load CA cert+key from disk (`CERTCTL_CA_CERT_PATH`, `CERTCTL_CA_KEY_PATH`)
- **Key Formats Supported** — RSA, ECDSA, PKCS#8
- **CRL Generation** — Signed by CA, 24h validity
- **OCSP Signing** — Delegates to CA's private key
- **Use Case** — Internal PKI, enterprise trust chains
### ACME v2
- **Challenge Types** — HTTP-01 (default) and DNS-01 (wildcard support)
- **DNS-01 Script Hooks** — Pluggable DNS solver for any provider (Cloudflare, Route53, Azure DNS, etc.)
- **Configuration** — `CERTCTL_ACME_DIRECTORY_URL`, `CERTCTL_ACME_EMAIL`, `CERTCTL_ACME_CHALLENGE_TYPE=dns-01`, `CERTCTL_ACME_DNS_PRESENT_SCRIPT`, `CERTCTL_ACME_DNS_CLEANUP_SCRIPT`
- **DNS Propagation Wait** — Configurable timeout before validation
- **Use Case** — Public CAs (LetsEncrypt), wildcard certs
### 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`
- **Operations** — Issue, renew, revoke
- **Use Case** — Smallstep private CA, internal PKI with strong auth
### OpenSSL / Custom CA
- **Mechanism** — Delegate signing to user-provided shell scripts
- **Scripts** — Sign script (CSR→cert), revoke script (serial+reason), CRL script (full CRL)
- **Timeout** — Configurable timeout (default 30s) with process interruption
- **Configuration** — `CERTCTL_OPENSSL_SIGN_SCRIPT`, `CERTCTL_OPENSSL_REVOKE_SCRIPT`, `CERTCTL_OPENSSL_CRL_SCRIPT`, `CERTCTL_OPENSSL_TIMEOUT_SECONDS`
- **Use Case** — PKIX-compliant external CAs, PowerShell issuers, custom workflows
---
## Target Connectors (3 Implemented + 2 Stubs)
### NGINX
- **Deployment** — Separate cert, chain, and key files
- **Validation** — `nginx -t` configuration test
- **Reload** — Graceful reload via SIGHUP (or nginx -s reload)
- **Target Config** — Certificate path, chain path, key path
- **Status** — Fully implemented (M10)
### Apache httpd
- **Deployment** — Separate cert, chain, and key files
- **Validation** — `apachectl configtest` or `apache2ctl configtest`
- **Reload** — Graceful reload via `apachectl graceful` or `apache2ctl graceful`
- **Target Config** — Certificate path, chain path, key path
- **Status** — Fully implemented (M10)
### HAProxy
- **Deployment** — Combined PEM file (cert + chain + key concatenated)
- **Validation** — Optional `haproxy -c -f config` test
- **Reload** — Process signal or socket-based reload (configurable)
- **Target Config** — Combined PEM path, optional reload command
- **Status** — Fully implemented (M10)
### F5 BIG-IP (Stub)
- **Protocol** — iControl REST API via proxy agent
- **Status** — Interface only in V2; implementation planned for V2 or V3
- **Deployment Model** — Proxy agent + BIG-IP API client in same network zone
- **Authentication** — iControl credentials stored in target config
### IIS (Stub)
- **Dual-Mode Architecture** — Agent-local PowerShell (primary) or proxy agent WinRM (agentless)
- **Status** — Interface only in V2; implementation planned for V2 or V3
- **Deployment Model** — Agent runs PowerShell cmdlets locally or proxy agent invokes WinRM
- **Binding** — Bind certificate to IIS site by hostname
---
## Notifier Connectors (6 Channels)
### Email
- **SMTP** — Standard SMTP or TLS endpoint
- **Configuration** — Server, port, auth credentials (env vars)
- **Use Case** — Owner notifications, compliance distribution lists
### Webhook
- **HTTP POST** — Custom JSON payload to any endpoint
- **Headers** — Content-Type, custom auth headers (configurable)
- **Use Case** — Slack (via custom webhook), Microsoft Power Automate, custom platforms
### Slack
- **Protocol** — Incoming Webhook
- **Message Format** — Markdown with bold subject, formatted body
- **Overrides** — Channel (`CERTCTL_SLACK_CHANNEL`), username (`CERTCTL_SLACK_USERNAME`), emoji
- **Configuration** — `CERTCTL_SLACK_WEBHOOK_URL`
- **Use Case** — Team notifications, ops channels
### Microsoft Teams
- **Protocol** — Incoming Webhook
- **Message Format** — MessageCard with ThemeColor, Summary, Sections
- **Markdown Support** — Formatted text within sections
- **Configuration** — `CERTCTL_TEAMS_WEBHOOK_URL`
- **Use Case** — Team-wide alerts, cross-team visibility
### PagerDuty
- **Protocol** — Events API v2
- **Trigger Events** — Alert on expiration, failure, revocation
- **Severity** — Configurable default (default "warning")
- **Custom Details** — Certificate ID, days remaining, owner, etc.
- **Configuration** — `CERTCTL_PAGERDUTY_ROUTING_KEY`, `CERTCTL_PAGERDUTY_SEVERITY`
- **Use Case** — Incident response, on-call escalations
### OpsGenie
- **Protocol** — Alert API v2
- **Priority** — Configurable default (default "P3")
- **Tags** — Category tags (cert expiration, deployment failure, etc.)
- **Responders** — Optional team routing
- **Configuration** — `CERTCTL_OPSGENIE_API_KEY`, `CERTCTL_OPSGENIE_PRIORITY`
- **Use Case** — Multi-team alerting, escalation policies
### Notification Types
- **Expiration Alert** — Certificate approaching threshold (30/14/7/0 days)
- **Renewal Started** — Renewal job initiated
- **Renewal Completed** — Certificate successfully renewed
- **Deployment Completed** — Certificate deployed to target
- **Deployment Failed** — Target deployment error
- **Revocation** — Certificate revoked with reason
- **Policy Violation** — Certificate violates renewal policy
---
## Agent Fleet
### Agent Registration & Heartbeat
- **Registration** — `POST /api/v1/agents` with agent name and API key
- **Heartbeat** — `POST /api/v1/agents/{id}/heartbeat` every 60 seconds
- **Auto-Offline** — Agents marked offline after 3 missed heartbeats (configurable)
- **Last Heartbeat Timestamp** — Tracked in `agents` table
### Agent Metadata (M10)
Collected via runtime introspection and network utilities.
| Field | Source | Example |
|-------|--------|---------|
| **OS** | `runtime.GOOS` | linux, darwin, windows |
| **Architecture** | `runtime.GOARCH` | amd64, arm64 |
| **Hostname** | `os.Hostname()` | nginx-prod-1 |
| **IP Address** | `net.Interface` + `net.IP` | 10.0.1.5 |
| **Version** | Agent binary version (from build flags) | v2.1.0 |
### Agent Groups (M11b)
Dynamic grouping and filtering for policy assignment and deployment targeting.
| Criterion | Details | Example |
|-----------|---------|---------|
| **OS Match** | Exact string match | linux, darwin, windows |
| **Architecture Match** | Exact string match | amd64, arm64, 386 |
| **IP CIDR Match** | IPv4 or IPv6 CIDR block | 10.0.0.0/8, 192.168.1.0/24 |
| **Version Match** | Semantic version range (optional) | >=2.0.0, <3.0.0 |
| **Manual Membership** | Explicit include/exclude | Include a-xxx, exclude a-yyy |
| **MatchesAgent()** | Dynamic evaluation at job time | Criteria match→agent included |
### Agent Group GUI
- List with dynamic match criteria badges (color-coded)
- Enable/disable toggle per group
- Manual membership editor (include/exclude lists)
- Agent count per group (dynamic)
- Scoped to renewal policies via `agent_group_id` FK
### Agent Capabilities
Agents report to `/api/v1/agents/{id}/work` with supported target types and issuers.
- **Target Deployment** — NGINX, Apache httpd, HAProxy, F5 BIG-IP (proxy), IIS (proxy)
- **Key Management** — ECDSA P-256 keygen, key storage at `CERTCTL_KEY_DIR` (default `/var/lib/certctl/keys`), 0600 file permissions
- **CSR Submission** — `POST /api/v1/agents/{id}/csr` for AwaitingCSR jobs
### Fleet Overview Page
- **OS/Architecture Grouping** — Agents grouped by GOOS + GOARCH
- **Charts** — Status distribution (pie), version breakdown (bar)
- **Per-Platform Listing** — Expandable agent list under each OS/Arch combo
- **Health Indicators** — Online/offline status, last heartbeat, uptime
---
## Certificate Discovery (M18b)
### Overview
Agents automatically discover existing certificates in the infrastructure — on filesystem, in key stores, or elsewhere — report findings to the control plane, and operators triage them for enrollment.
### Agent-Side Discovery
- **Configuration** — `CERTCTL_DISCOVERY_DIRS` env var (comma-separated list) or `--discovery-dirs` CLI flag
- **Scan Execution** — Runs on agent startup and every 6 hours in background
- **Supported Formats** — PEM (.pem, .crt, .cer, .cert) and DER (.der) files
- **Recursive Walk** — Scans directory trees to find all certificates
- **File Filtering** — Skips files > 1MB and obvious key files
### Certificate Extraction
Each discovered certificate is parsed and its metadata extracted:
| Field | Source | Example |
|-------|--------|---------|
| **Common Name** | X.509 Subject CN | api.example.com |
| **SANs** | X.509 SubjectAltNames | api.example.com, *.api.example.com |
| **Serial** | Certificate serial number | 0x123abc... |
| **Issuer DN** | X.509 Issuer | CN=Internal CA, O=Acme Inc |
| **Subject DN** | X.509 Subject | CN=api.example.com, O=Acme Inc |
| **Not Before** | Validity start | 2024-01-15T00:00:00Z |
| **Not After** | Validity end | 2026-01-15T00:00:00Z |
| **Key Algorithm** | Key type | RSA, ECDSA, Ed25519 |
| **Key Size** | Bits | 2048, 256, 4096 |
| **Is CA** | CA flag in extensions | true/false |
| **Fingerprint** | SHA-256 hash (dedup key) | a1b2c3d4e5f6... |
### Server-Side Processing
- **Deduplication** — Uses fingerprint + agent ID + path as unique key; prevents duplicates
- **Status Tracking** — Three statuses: **Unmanaged** (discovered, not yet claimed), **Managed** (linked to control plane cert), **Dismissed** (operator decided not to manage)
- **Audit Trail** — `discovery_scan_completed`, `discovery_cert_claimed`, `discovery_cert_dismissed` events logged with actor and reason
- **Storage** — `discovered_certificates` and `discovery_scans` tables in PostgreSQL
### Triage Workflow
1. Agent submits scan results via `POST /api/v1/agents/{id}/discoveries`
2. Server deduplicates and stores discovery records
3. Operator views `GET /api/v1/discovered-certificates?status=Unmanaged`
4. For each unmanaged cert:
- **Claim it** — `POST /api/v1/discovered-certificates/{id}/claim` links to managed cert or creates new enrollment
- **Dismiss it** — `POST /api/v1/discovered-certificates/{id}/dismiss` removes from triage queue
5. Tracking enables visibility into what's deployed vs. what's managed
### Discovery API Endpoints (M18b)
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/v1/agents/{id}/discoveries` | POST | Agent submits scan results |
| `/api/v1/discovered-certificates` | GET | List discovered certs (with ?agent_id, ?status filters) |
| `/api/v1/discovered-certificates/{id}` | GET | Get single discovered cert detail |
| `/api/v1/discovered-certificates/{id}/claim` | POST | Link to managed cert or create enrollment |
| `/api/v1/discovered-certificates/{id}/dismiss` | POST | Dismiss from triage |
| `/api/v1/discovery-scans` | GET | List scan history with timestamps |
| `/api/v1/discovery-summary` | GET | Aggregate status counts (Unmanaged, Managed, Dismissed) |
### Use Cases
- **Inventory Baseline** — Scan production servers at deployment time to establish baseline of existing certificates
- **Compliance Discovery** — Find all TLS certs before renewing certificate policies
- **Migration Planning** — Discover unmanaged certs to plan migration from other CA/platforms
- **Audit Preparation** — Triage discovered certs into managed and dismissed for compliance reports
- **Multi-CA Migration** — Find all certs currently issued by old CA, claim them for renewal under new issuer
---
## Ownership & Accountability
### Teams
- **Model** — Team grouping for organizational structure
- **Team Assignment** — Certificates and policies assigned to teams
- **Email Distribution** — Optional team email for notifications
- **Resolver Logic** — Team name → member lookup via API (external resolution)
- **GUI** — CRUD page with member management
### Owners
- **Model** — Individual person responsible for certificates
- **Email Routing** — Owner email used for notification delivery
- **Team Association** — Owners belong to teams
- **Certificate Assignment** — Certificates assigned to owner (1:1 or group)
- **Notification Routing** — Expiration/renewal/revocation alerts sent to owner email
- **GUI** — CRUD page with team picker, email validation
### Interactive Renewal Approval (M11b)
- **AwaitingApproval Job State** — Renewal jobs pause for human approval
- **Approval Flow** — `POST /api/v1/jobs/{id}/approve` (proceed with renewal)
- **Rejection Flow** — `POST /api/v1/jobs/{id}/reject` with reason text (cancel job)
- **Reason Tracking** — Approval/rejection reason logged to job history and audit
- **Use Case** — Change control, compliance gates, sensitive certificate renewal
---
## Observability
### Observability Layers
#### Dashboard Charts (M14)
Live aggregated views of certificate and job metrics.
| Chart | Type | Details |
|-------|------|---------|
| **Expiration Heatmap** | Stacked bar | 90-day weekly buckets; per-status color bands |
| **Renewal Success Rate** | Line (30-day) | Success % trending over time |
| **Certificate Status Distribution** | Donut | Pie breakdown: Active, Expiring, Expired, Failed, Revoked, etc. |
| **Issuance Rate** | Bar (30-day) | Certs issued per day; trend line |
#### Metrics Endpoint
- **URL** — `GET /api/v1/metrics`
- **Format** — JSON with timestamp
- **Gauges** — Certificate counts by status, agent count (online/offline), pending job count
- **Counters** — Total jobs completed, total jobs failed, total renewals, total issuances
- **Uptime** — Server uptime in seconds
#### Stats API (M14)
Five parameterized endpoints for dashboard data.
| Endpoint | Parameters | Response |
|----------|------------|----------|
| **GET /api/v1/stats/summary** | None | Total certs, expiring soon, renewals in progress, failed jobs, agents online |
| **GET /api/v1/stats/certificates-by-status** | None | Count per status (Active, Expiring, Expired, etc.) |
| **GET /api/v1/stats/expiration-timeline** | days (default 90) | Weekly buckets with cert counts; 90-day default |
| **GET /api/v1/stats/job-trends** | days (default 30) | Daily completed/failed job counts; line chart ready |
| **GET /api/v1/stats/issuance-rate** | days (default 30) | Certs issued per day; 30-day default |
#### Structured Logging (M14)
- **Library** — Go's `log/slog` (structured, context-aware)
- **Request ID Propagation** — Per-request UUID in context; logged on all operations
- **Middleware** — `NewLogging(logger *slog.Logger)` middleware wrapping all API calls
- **Log Format** — JSON (default) or text; configurable via `CERTCTL_LOG_FORMAT`
- **Log Level** — debug, info, warn, error; configurable via `CERTCTL_LOG_LEVEL`
#### API Audit Middleware (M19)
Every API call recorded to immutable `audit_events` table.
| Logged Field | Details |
|--------------|---------|
| **Method** | HTTP verb (GET, POST, PUT, DELETE) |
| **Path** | Request path (e.g., /api/v1/certificates) |
| **Actor** | Authenticated user/API key (or "anonymous") |
| **Body Hash** | SHA-256 of request body (truncated first 16 chars for brevity) |
| **Response Status** | HTTP status code |
| **Latency** | Request processing time in ms |
| **Timestamp** | RFC3339 format |
#### Immutable Audit Trail
- **Table** — `audit_events` append-only (no UPDATE/DELETE)
- **Events** — Issuance, renewal, deployment, revocation, policy violations, approval/rejection
- **Retention** — Indefinite (no expiration)
- **GUI Export** — CSV/JSON export with applied time-range, actor, action filters
- **Query API** — `GET /api/v1/audit?actor=...&resource=...&action=...&before=...&after=...`
#### Deployment Rollback Support (M14)
- **Version History** — Sorted by deployment timestamp
- **Current Badge** — Visual indicator on latest deployed version
- **Rollback Button** — Click to re-deploy previous version
- **Versioning** — Each cert version tracked (serial, fingerprint, PEM)
---
## Job System
### Job Types (4 total)
| Type | Trigger | States | Output |
|------|---------|--------|--------|
| **Issuance** | New certificate creation | Pending → AwaitingCSR/Running → Completed/Failed | Certificate version with serial |
| **Renewal** | Auto-renewal or manual trigger | Pending → AwaitingCSR/AwaitingApproval/Running → Completed/Failed | New certificate version |
| **Deployment** | Automatic or manual post-renewal | Pending → AwaitingCSR/Running → Completed/Failed | Target-specific status |
| **Validation** | Scheduled or manual | Pending → Running → Completed/Failed | Validation report (TBD V3) |
### Job States (7 total)
| State | Meaning | Transition |
|-------|---------|-----------|
| **Pending** | Created, awaiting processing | → AwaitingCSR or Running |
| **AwaitingCSR** | Agent needs to generate key + submit CSR | → Running (after CSR received) |
| **AwaitingApproval** | Human approval required (renewal only) | → Running (approve) or Cancelled (reject) |
| **Running** | Active processing (issuance, deployment, etc.) | → Completed or Failed |
| **Completed** | Successfully finished | (terminal) |
| **Failed** | Error during processing; no retry auto-scheduled | (terminal; manual retry available) |
| **Cancelled** | Explicitly cancelled by user or system | (terminal) |
### Job Lifecycle Example (Agent Keygen)
1. **Renewal triggered** → Job created in `Pending` state
2. **Scheduler polls** → Job transitioned to `AwaitingCSR`
3. **Work endpoint** → Agent receives job with common_name and SANs
4. **Agent keygen** → ECDSA P-256 key created locally; CSR submitted
5. **CSR received** → Server signs; Job transitioned to `Running`
6. **Deployment scheduled** → New Deployment job created in `Pending`
7. **Agent deploys** → Deployment job → `Running``Completed`
8. **Status reported**`POST /api/v1/agents/{id}/jobs/{job_id}/status`
### Approval Flow (Interactive)
1. **Renewal job created** in `AwaitingApproval` state (if policy requires)
2. **Human reviews** on GUI
3. **Approve**`POST /api/v1/jobs/{id}/approve` → Job → `Running`
4. **Reject**`POST /api/v1/jobs/{id}/reject` + reason → Job → `Cancelled`
### Background Scheduler (5 loops)
| Loop | Interval | Task |
|------|----------|------|
| **Renewal Checker** | 1 hour | Scan policies; trigger renewals if cert expires soon |
| **Job Processor** | 30 seconds | Process Pending → AwaitingCSR/Running; poll agent status |
| **Health Checker** | 2 minutes | Check agent heartbeat; mark offline if >3 missed |
| **Notification Processor** | 1 minute | Send queued notifications (email, Slack, webhook, etc.) |
| **Short-Lived Cleanup** | 30 seconds | Audit short-lived credential expirations |
All loops have configurable intervals via environment variables (`CERTCTL_SCHEDULER_*_INTERVAL`).
---
## Web Dashboard (19 Pages)
### Overview
The web dashboard is the primary operational interface for certctl. Built with **Vite + React 18 + TypeScript + TanStack Query v5 + Tailwind CSS 3 + Recharts**.
| Page | Route | Purpose |
|------|-------|---------|
| **Dashboard** | `/` | Overview: summary cards, 4 charts (expiration, renewal rate, status, issuance), quick actions |
| **Certificates** | `/certificates` | List with multi-select, bulk operations (renew/revoke/reassign), new cert modal, sorting/filtering |
| **Certificate Detail** | `/certificates/:id` | Full cert view: deployment timeline, inline policy editor, version history, rollback, revoke, archive, renew actions |
| **Agents** | `/agents` | List with metadata (OS, architecture, IP, version), online status, uptime |
| **Agent Detail** | `/agents/:id` | Full system information, recent jobs, heartbeat graph, capabilities, metrics |
| **Agent Fleet Overview** | `/fleet` | OS/architecture grouping with pie charts (status, version), per-platform agent listing |
| **Jobs** | `/jobs` | Queue view with type filter, status filter, inline cancel/approve/reject, retry button |
| **Notifications** | `/notifications` | Grouped by certificate, mark-as-read toggle, filter by type (expiration, deployment, revocation) |
| **Policies** | `/policies` | CRUD with rule builder, enable/disable toggle, violations summary bar, violation list |
| **Profiles** | `/profiles` | List with crypto constraints (key algorithms, TTL, EKUs), create/edit/delete |
| **Issuers** | `/issuers` | List, create new issuer, test connection button, delete |
| **Targets** | `/targets` | List, 3-step configuration wizard (Select Type → Configure → Review), type-specific fields |
| **Owners** | `/owners` | List, create/edit with team picker, email field, delete |
| **Teams** | `/teams` | List, create/edit with member resolver, delete |
| **Agent Groups** | `/agent-groups` | List with dynamic match criteria badges (OS, arch, IP CIDR, version), manual membership editor |
| **Audit Trail** | `/audit` | Filtered view (time range, actor, action), CSV/JSON export buttons, event detail modal |
| **Short-Lived Credentials** | `/short-lived` | Filtered by profile with TTL < 1 hour, live countdown timer, auto-refresh every 10s, stats bar |
| **Login** | `/login` | API key entry, auth mode detection, redirect after successful auth |
| **ErrorBoundary** | (all pages) | Graceful crash recovery; displays user-friendly error message instead of white screen |
### Dashboard Features
#### Bulk Operations
- **Multi-Select** — Checkbox column in certificate list; "Select All" toggle
- **Bulk Renew** — Trigger renewal on selected certs; progress bar
- **Bulk Revoke** — Select reason codes per cert; sequential revocation; progress
- **Bulk Reassign** — Owner picker modal; assign to multiple certs at once
#### Deployment Timeline
- **Visual 4-Step Timeline** — Requested → Issued → Deploying → Active
- **Per-Certificate Job Queries** — Query jobs to get current phase
- **Status Indicators** — Checkmarks for completed phases; spinner for running; X for failed
#### Inline Policy Editor
- **Edit Mode** — Click edit button on cert detail
- **Policy Dropdown** — Select from list of policies
- **Renewal Threshold Config** — Inline sliders/inputs for 30/14/7/0 day thresholds
- **Save/Cancel** — API mutations with optimistic updates via TanStack Query
#### Target Configuration Wizard
- **Step 1: Select Type** — Radio or dropdown (NGINX, Apache, HAProxy, F5, IIS)
- **Step 2: Configure** — Type-specific fields (cert path, chain path, key path, etc.)
- **Step 3: Review** — Summary of config; confirm create
- **Validation** — Real-time field validation; show errors; disable Create if invalid
#### Auth & Session
- **Auth Context** — React context with API key, auth mode, session state
- **Auto-Redirect** — 401 response → redirect to /login
- **Logout** — Button in sidebar; clears context; redirects to /login
- **Remember API Key** — Persisted in localStorage (production should clear on logout)
#### Demo Mode
- Activates when API is unreachable
- Renders realistic mock data for screenshots
- Useful for offline presentations
---
## Integration Interfaces
### MCP Server (M18a)
**Separate binary** (`cmd/mcp-server/`) providing AI-native access to certctl via Claude, Cursor, OpenClaw.
- **Transport** — stdio (stdin/stdout)
- **Protocol** — Model Context Protocol v1
- **SDK** — Official `modelcontextprotocol/go-sdk` v1.4.1
- **Tools** — 76 MCP tools covering all API endpoints
- **Organization** — 16 resource domains (Certificates, Issuers, Targets, Agents, Jobs, etc.)
- **Authentication** — Bearer token via `CERTCTL_API_KEY` env var
- **Configuration** — `CERTCTL_SERVER_URL` (e.g., http://localhost:8080) + `CERTCTL_API_KEY`
- **Input Types** — 33 typed structs with `jsonschema` tags for auto-generated LLM-friendly schemas
- **Stateless Design** — HTTP proxy (no state held in MCP server; all logic in REST API)
### CLI Tool (certctl-cli, M16b)
**Lightweight command-line wrapper** around REST API.
| Subcommand | Usage | Output Format |
|------------|-------|----------------|
| **list-certs** | `certctl-cli list-certs [--filter]` | Table or JSON (--format=json) |
| **get-cert** | `certctl-cli get-cert <id>` | JSON cert details |
| **renew-cert** | `certctl-cli renew-cert <id>` | Job ID confirmation |
| **revoke-cert** | `certctl-cli revoke-cert <id> [--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 |
| **import** | `certctl-cli import <pem-file>` | Bulk import cert count |
| **help** | `certctl-cli help [command]` | Command documentation |
**Implementation Details:**
- Stdlib-only (flag + text/tabwriter); no Cobra dependency
- JSON + table output formatters
- PEM parser for bulk import (multi-cert PEM files)
- Environment variables: `CERTCTL_SERVER_URL`, `CERTCTL_API_KEY`
- CLI flags: `--server`, `--api-key`, `--format` (json/table)
- Tested with httptest mock server; all commands covered
### OpenAPI 3.1 Specification
- **File** — `api/openapi.yaml`
- **Scope** — 78 operations (76 API endpoints + /health + /ready)
- **Schemas** — Complete domain models with examples
- **Enums** — Job types, states, policy rule types, notification types
- **Pagination** — Standard envelope (data, total, page, per_page)
- **Security** — Bearer token security scheme
- **SDK Generation** — Supports go-swagger, openapi-generator, etc.
---
## Security Architecture
### Private Key Isolation
- **Agent-Side Keygen (Default)** — ECDSA P-256 keys generated on agents via Go's `crypto/ecdsa`
- **Local Key Storage** — Keys written to agent's `CERTCTL_KEY_DIR` (default `/var/lib/certctl/keys`) with 0600 permissions (user-readable only)
- **Server-Side Keygen (Demo Only)** — RSA-2048 keygen available via `CERTCTL_KEYGEN_MODE=server` with explicit log warning; never used in production
- **CSR Submission Only** — Agents submit CSRs (public) to control plane; private keys never leave agent infrastructure
- **Key Rotation** — Agents can re-key without control plane involvement (local only)
### Pull-Only Deployment Model
- **No Outbound Initiations** — Server never initiates connections to agents or targets
- **Agent Polling** — Agents poll `GET /api/v1/agents/{id}/work` every 30 seconds
- **Proxy Agent Pattern** — For network appliances (F5, Palo Alto) or agentless targets (Windows servers), a "proxy agent" in the same network zone executes deployments via the target's API
- **Credential Scope** — Proxy agent credentials limited to its zone; control plane never stores target credentials directly
- **Firewall-Friendly** — Control plane can be completely locked down; no inbound rules needed for agents
### Sub-CA Capability
- **Enterprise Integration** — Local CA can operate as subordinate CA under enterprise root (e.g., ADCS)
- **Disk-Based Cert+Key** — `CERTCTL_CA_CERT_PATH` + `CERTCTL_CA_KEY_PATH` load pre-signed CA cert and key
- **Chain Validation** — Issued certs chain to enterprise root; full trust hierarchy
- **Self-Signed Fallback** — Default mode generates self-signed root if paths not set (development/demo)
- **Key Formats** — RSA, ECDSA, PKCS#8 support with auto-detection
### API Authentication
- **SHA-256 Hashing** — API keys hashed with SHA-256 before storage
- **Constant-Time Comparison** — Prevents timing attacks during key validation
- **Bearer Token** — `Authorization: Bearer {api_key}` header on all authenticated endpoints
- **Configurable** — `CERTCTL_AUTH_TYPE=api-key` (default) enforced; "none" requires explicit opt-in with log warning
### Rate Limiting
- **Token Bucket** — Smooth rate limiting with burst capacity
- **RPS + Burst** — Configurable `CERTCTL_RATE_LIMIT_RPS` (default 50) and `CERTCTL_RATE_LIMIT_BURST` (default 100)
- **429 Responses** — Rate limit exceeded responses include `Retry-After` header
- **Per-Client** — Implemented per IP (future: per API key)
### Audit & Compliance
- **Immutable Audit Trail** — Append-only table; no UPDATE/DELETE operations
- **API Audit Middleware** — Every call logged with method, path, actor, body hash, status, latency
- **Event Timestamps** — RFC3339 format with second precision
- **Actor Tracking** — API key ID or username extracted from auth context
- **Compliance Export** — CSV/JSON export of audit events with filtering
---
## Infrastructure
### Deployment Architecture
- **Server** — Go HTTP server (net/http stdlib) on `:8080` (default) or `:8443` (Docker)
- **Database** — PostgreSQL 16 with 18+ tables, TEXT primary keys (human-readable prefixed IDs)
- **Agent** — Lightweight Go binary on target infrastructure
- **Dashboard** — React SPA served from `/web/dist/` (Vite build)
### Docker Compose Deployment
- **Services** — PostgreSQL 16, certctl server, agent
- **Health Checks** — On all services (server health check, database readiness)
- **Seed Data** — Demo dataset with 15 certs, 5 agents, 5 targets, policies, audit events
- **Credentials** — Environment variables in `.env` file; app.key for API key
### PostgreSQL Schema
- **18+ Tables** — Certificates, agents, jobs, targets, issuers, policies, profiles, teams, owners, agent groups, audit events, notifications, revocations, versions, etc.
- **TEXT Primary Keys** — Human-readable prefixed IDs: mc-*, t-*, a-*, j-*, p-*, etc.
- **Indexes** — 5+ performance indexes on foreign keys, timestamps, status fields
- **Migrations** — Idempotent migrations with `IF NOT EXISTS`, `ON CONFLICT`, numbered sequentially
- **Max Connections** — Configurable via `CERTCTL_DATABASE_MAX_CONNS` (default 25)
### CI/CD Pipeline
- **GitHub Actions** — `.github/workflows/ci.yml`
- **Parallel Jobs** — Go (build, vet, test+coverage, gates) and Frontend (tsc, vitest, vite build)
- **Coverage Gates** — Service layer ≥30%, handler layer ≥50%
- **Release Workflow** — Tag push → build → publish Docker images to `ghcr.io`
- **Docker Tags** — `:latest`, `:v{version}` (ghcr.io/shankar0123/certctl)
### Test Suite
- **Unit Tests** — 625+ 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** — 860+ tests (Go + frontend combined)
### Licensing
- **License** — Business Source License 1.1 (BSL 1.1)
- **Conversion** — Automatic conversion to Apache 2.0 on March 23, 2033 (7-year term)
- **Source-Available** — Code available for inspection; copying/modification restricted until conversion
---
## Configuration Reference
### Environment Variables (All `CERTCTL_` Prefixed)
#### Server
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_SERVER_HOST` | string | 127.0.0.1 | Bind address |
| `CERTCTL_SERVER_PORT` | int | 8080 | Listen port |
#### Database
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_DATABASE_URL` | string | postgres://localhost/certctl | PostgreSQL connection string |
| `CERTCTL_DATABASE_MAX_CONNS` | int | 25 | Max connection pool size |
| `CERTCTL_DATABASE_MIGRATIONS_PATH` | string | ./migrations | Migration file directory |
#### Scheduler
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_SCHEDULER_RENEWAL_CHECK_INTERVAL` | duration | 1h | Renewal checker loop interval |
| `CERTCTL_SCHEDULER_JOB_PROCESSOR_INTERVAL` | duration | 30s | Job processor loop interval |
| `CERTCTL_SCHEDULER_AGENT_HEALTH_CHECK_INTERVAL` | duration | 2m | Agent health checker loop interval |
| `CERTCTL_SCHEDULER_NOTIFICATION_PROCESS_INTERVAL` | duration | 1m | Notification processor loop interval |
#### Logging
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_LOG_LEVEL` | string | info | debug, info, warn, error |
| `CERTCTL_LOG_FORMAT` | string | json | json or text |
#### Authentication
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_AUTH_TYPE` | string | api-key | api-key, jwt, or none |
| `CERTCTL_AUTH_SECRET` | string | (required) | API key or JWT secret |
#### Rate Limiting
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_RATE_LIMIT_ENABLED` | bool | true | Enable/disable rate limiting |
| `CERTCTL_RATE_LIMIT_RPS` | float | 50 | Requests per second |
| `CERTCTL_RATE_LIMIT_BURST` | int | 100 | Max burst size |
#### CORS
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_CORS_ORIGINS` | string | (empty) | Comma-separated origins or * for all |
#### Key Generation
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_KEYGEN_MODE` | string | agent | agent or server |
#### Local CA Sub-CA Mode
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_CA_CERT_PATH` | string | (empty) | Path to PEM-encoded CA cert (sub-CA mode) |
| `CERTCTL_CA_KEY_PATH` | string | (empty) | Path to PEM-encoded CA key (sub-CA mode) |
#### ACME Issuer
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_ACME_DIRECTORY_URL` | string | (empty) | ACME server directory URL |
| `CERTCTL_ACME_EMAIL` | string | (empty) | Account email for ACME registration |
| `CERTCTL_ACME_CHALLENGE_TYPE` | string | http-01 | http-01 or dns-01 |
| `CERTCTL_ACME_DNS_PRESENT_SCRIPT` | string | (empty) | Script path for DNS-01 present hook |
| `CERTCTL_ACME_DNS_CLEANUP_SCRIPT` | string | (empty) | Script path for DNS-01 cleanup hook |
#### step-ca Issuer
| 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) |
#### OpenSSL/Custom CA Issuer
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_OPENSSL_SIGN_SCRIPT` | string | (empty) | Path to sign script (CSR → cert) |
| `CERTCTL_OPENSSL_REVOKE_SCRIPT` | string | (empty) | Path to revoke script (serial+reason) |
| `CERTCTL_OPENSSL_CRL_SCRIPT` | string | (empty) | Path to CRL generation script |
| `CERTCTL_OPENSSL_TIMEOUT_SECONDS` | int | 30 | Script timeout in seconds |
#### Notifiers
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_SLACK_WEBHOOK_URL` | string | (empty) | Slack incoming webhook URL |
| `CERTCTL_SLACK_CHANNEL` | string | (empty) | Slack channel override |
| `CERTCTL_SLACK_USERNAME` | string | certctl | Slack username override |
| `CERTCTL_TEAMS_WEBHOOK_URL` | string | (empty) | Microsoft Teams webhook URL |
| `CERTCTL_PAGERDUTY_ROUTING_KEY` | string | (empty) | PagerDuty Events API routing key |
| `CERTCTL_PAGERDUTY_SEVERITY` | string | warning | PagerDuty event severity |
| `CERTCTL_OPSGENIE_API_KEY` | string | (empty) | OpsGenie API key |
| `CERTCTL_OPSGENIE_PRIORITY` | string | P3 | OpsGenie alert priority |
#### Agent
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_AGENT_NAME` | string | (generated) | Agent display name |
| `CERTCTL_KEY_DIR` | string | /var/lib/certctl/keys | Local private key storage directory |
| `CERTCTL_AGENT_ID` | string | (env or generated) | Agent unique ID (mc-xxx prefix) |
#### MCP Server
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CERTCTL_SERVER_URL` | string | http://localhost:8080 | Base URL of certctl server |
| `CERTCTL_API_KEY` | string | (required) | API key for authentication |
---
## Feature Matrix: V2 Free vs. V3 Paid (Roadmap)
| Feature | V2 | V3 (Paid) | Status |
|---------|----|-----------|-|
| Certificate lifecycle (create/renew/revoke) | ✓ | ✓ | Shipped v1.0+ |
| 4 issuer connectors (Local CA, ACME, step-ca, OpenSSL) | ✓ | ✓ | Shipped |
| 3 target connectors (NGINX, Apache, HAProxy) | ✓ | ✓ | Shipped |
| 6 notifier channels (Email, Webhook, Slack, Teams, PagerDuty, OpsGenie) | ✓ | ✓ | Shipped |
| Agent fleet + metadata | ✓ | ✓ | Shipped |
| Agent groups (dynamic + manual) | ✓ | ✓ | Shipped |
| Policies + violations | ✓ | ✓ | Shipped |
| Profiles + crypto constraints | ✓ | ✓ | Shipped |
| Revocation (RFC 5280, CRL, OCSP) | ✓ | ✓ | Shipped |
| Dashboard + 19 pages | ✓ | ✓ | Shipped |
| Observability (charts, metrics, stats) | ✓ | ✓ | Shipped |
| REST API (77 endpoints) | ✓ | ✓ | Shipped |
| MCP server (76 tools) | ✓ | ✓ | Shipped v2.1 |
| CLI tool (10 subcommands) | ✓ | ✓ | Shipped |
| **OIDC/SSO auth** | ✗ | ✓ | Planned V3 |
| **RBAC (role-based access control)** | ✗ | ✓ | Planned V3 |
| **F5 BIG-IP implementation** | Stub | ✓ | Stub in V2 |
| **IIS implementation** | Stub | ✓ | Stub in V2 |
| **NATS event bus** | ✗ | ✓ | Planned V3 |
| **Real-time updates (SSE/WebSocket)** | ✗ | ✓ | Planned V3 |
| **Advanced search DSL** | ✗ | ✓ | Planned V3 |
| **Bulk operations** | ✓ | ✓ | M13 (free) |
| **Bulk revocation** | ✗ | ✓ | Planned V3 (paid) |
| **Certificate health scores** | ✗ | ✓ | Planned V3 |
| **Compliance scoring** | ✗ | ✓ | Planned V3 |
| **DigiCert issuer** | ✗ | ✓ | Planned V3 |
| **CT Log monitoring** | ✗ | ✓ | Planned V3 |
---
## Summary Statistics
| Category | Count |
|----------|-------|
| **API Endpoints** | 84 (under /api/v1/) |
| **Dashboard Pages** | 19 |
| **Issuer Connectors** | 4 (Local CA, ACME, step-ca, OpenSSL) |
| **Target Connectors** | 5 (3 impl: NGINX, Apache, HAProxy; 2 stubs: F5, IIS) |
| **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) |
| **Policy Rule Types** | 5 (AllowedIssuers, AllowedDomains, RequiredMetadata, AllowedEnvironments, RenewalLeadTime) |
| **Certificate States** | 8 (Pending, Active, Expiring, Expired, RenewalInProgress, Failed, Revoked, Archived) |
| **Revocation Reason Codes** | 8 (RFC 5280 compliant) |
| **Discovery Statuses** | 3 (Unmanaged, Managed, Dismissed) |
| **MCP Tools** | 83 (17 resource domains) |
| **CLI Subcommands** | 10 |
| **Database Tables** | 20+ |
| **Test Suite** | 881+ tests |
| **Environment Variables** | 41+ configuration options |