mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-12 18:38:52 +00:00
Rewrite README and .env.example to match actual implementation
README.md:
- Replace ASCII architecture diagram with Mermaid
- Fix all database table names (managed_certificates, audit_events, etc.)
- Fix env var names to use CERTCTL_ prefix matching config.go
- Fix API endpoint paths ({id} not :id, /audit not /audit/logs)
- Add all missing endpoints (renew, deploy, CSR, heartbeat, policies, notifications)
- Add dashboard as primary feature (was completely missing)
- Link to all new docs (concepts, advanced demo, architecture, connectors)
- Fix integration status (Local CA implemented, ACME in progress)
- Fix security section (API key auth, not mTLS)
- Remove broken links to non-existent docs (api.md, k8s-deployment.md, scaling.md)
- Remove placeholder Support & Community section
.env.example:
- Change all var names to CERTCTL_ prefix (CERTCTL_DATABASE_URL, etc.)
- Remove vars that don't exist in config.go (ACME_*, SMTP_*, feature flags)
- Add scheduler tuning vars as commented examples
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+23
-56
@@ -3,73 +3,40 @@
|
|||||||
# DO NOT commit .env with real secrets to version control
|
# DO NOT commit .env with real secrets to version control
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# PostgreSQL Database Configuration
|
# PostgreSQL (used by Docker Compose for the postgres container)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
POSTGRES_DB=certctl
|
POSTGRES_DB=certctl
|
||||||
POSTGRES_USER=certctl
|
POSTGRES_USER=certctl
|
||||||
POSTGRES_PASSWORD=change-me-in-production
|
POSTGRES_PASSWORD=change-me-in-production
|
||||||
POSTGRES_PORT=5432
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# Certctl Server Configuration
|
# Certctl Server
|
||||||
|
# All server vars use the CERTCTL_ prefix (see internal/config/config.go)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
SERVER_HOST=0.0.0.0
|
CERTCTL_DATABASE_URL=postgres://certctl:certctl@postgres:5432/certctl?sslmode=disable
|
||||||
SERVER_PORT=8443
|
CERTCTL_SERVER_HOST=0.0.0.0
|
||||||
LOG_LEVEL=info
|
CERTCTL_SERVER_PORT=8443
|
||||||
|
CERTCTL_LOG_LEVEL=info
|
||||||
|
CERTCTL_LOG_FORMAT=json
|
||||||
|
|
||||||
# Database connection string (alternative to individual vars)
|
# Auth type: "api-key", "jwt", or "none" (for demo/development)
|
||||||
# DB_URL=postgres://certctl:password@localhost:5432/certctl?sslmode=disable
|
CERTCTL_AUTH_TYPE=none
|
||||||
|
# Required when CERTCTL_AUTH_TYPE is "api-key" or "jwt"
|
||||||
|
# Generate with: openssl rand -base64 32
|
||||||
|
# CERTCTL_AUTH_SECRET=change-me-in-production
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# ACME Configuration
|
# Certctl Agent
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# For Let's Encrypt production, use: https://acme-v02.api.letsencrypt.org/directory
|
CERTCTL_SERVER_URL=http://localhost:8443
|
||||||
# For Let's Encrypt staging, use: https://acme-staging-v02.api.letsencrypt.org/directory
|
CERTCTL_API_KEY=change-me-in-production
|
||||||
ACME_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory
|
CERTCTL_AGENT_NAME=local-agent
|
||||||
ACME_EMAIL=admin@example.com
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# SMTP Configuration (for email notifications)
|
# Optional: Scheduler Tuning (defaults are usually fine)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
SMTP_HOST=smtp.example.com
|
# CERTCTL_SCHEDULER_RENEWAL_CHECK_INTERVAL=1h
|
||||||
SMTP_PORT=587
|
# CERTCTL_SCHEDULER_JOB_PROCESSOR_INTERVAL=30s
|
||||||
SMTP_USERNAME=your-smtp-user
|
# CERTCTL_SCHEDULER_AGENT_HEALTH_CHECK_INTERVAL=2m
|
||||||
SMTP_PASSWORD=your-smtp-password
|
# CERTCTL_SCHEDULER_NOTIFICATION_PROCESS_INTERVAL=1m
|
||||||
SMTP_FROM_ADDRESS=certctl@example.com
|
# CERTCTL_DATABASE_MAX_CONNS=25
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# Webhook Configuration (optional)
|
|
||||||
# ==============================================================================
|
|
||||||
WEBHOOK_URL=https://your-webhook-endpoint.example.com/notifications
|
|
||||||
WEBHOOK_SECRET=your-webhook-secret
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# Agent Configuration
|
|
||||||
# ==============================================================================
|
|
||||||
SERVER_URL=http://localhost:8443
|
|
||||||
AGENT_API_KEY=change-me-in-production
|
|
||||||
AGENT_NAME=local-agent
|
|
||||||
CHECK_INTERVAL=60s
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# PgAdmin Configuration (development only)
|
|
||||||
# ==============================================================================
|
|
||||||
PGADMIN_EMAIL=admin@example.com
|
|
||||||
PGADMIN_PASSWORD=admin
|
|
||||||
PGADMIN_PORT=5050
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# Security Settings
|
|
||||||
# ==============================================================================
|
|
||||||
# JWT secret for API authentication (generate with: openssl rand -base64 32)
|
|
||||||
JWT_SECRET=change-me-in-production
|
|
||||||
|
|
||||||
# Encryption key for sensitive data (generate with: openssl rand -base64 32)
|
|
||||||
ENCRYPTION_KEY=change-me-in-production
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# Feature Flags (optional)
|
|
||||||
# ==============================================================================
|
|
||||||
ENABLE_AUDIT_LOG=true
|
|
||||||
ENABLE_METRICS=true
|
|
||||||
ENABLE_TRACING=false
|
|
||||||
|
|||||||
@@ -1,383 +1,314 @@
|
|||||||
# Certctl — Open-Source Certificate Control Plane
|
# certctl — Open-Source Certificate Control Plane
|
||||||
|
|
||||||
A self-hosted, cloud-agnostic certificate management platform for teams. Manage issuance, deployment, and renewal of TLS certificates at scale with zero private key exposure in the control plane.
|
A self-hosted certificate lifecycle platform. Track, renew, and deploy TLS certificates across your infrastructure with a web dashboard, REST API, and agent-based architecture where private keys never leave your servers.
|
||||||
|
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
[](https://goreportcard.com/report/github.com/shankar0123/certctl)
|
[](https://goreportcard.com/report/github.com/shankar0123/certctl)
|
||||||

|

|
||||||
|
|
||||||
## Overview
|
## What It Does
|
||||||
|
|
||||||
Certctl decouples certificate management into a control plane and lightweight agents deployed across your infrastructure. The control plane orchestrates issuance and renewal via multiple ACME issuers, while agents securely request, deploy, and renew certificates on target systems—all without exposing private keys outside the edge.
|
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** (50+ endpoints) lets you automate everything. **Agents** deployed on your infrastructure handle key generation and certificate deployment without exposing private keys to the control plane.
|
||||||
|
|
||||||
### Why Certctl?
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph "Control Plane"
|
||||||
|
API["REST API + Dashboard\n:8443"]
|
||||||
|
PG[("PostgreSQL")]
|
||||||
|
end
|
||||||
|
|
||||||
- **Decoupled architecture**: Control plane + edge agents, no SSH or privileged access required
|
subgraph "Your Infrastructure"
|
||||||
- **Multi-issuer support**: ACME (Let's Encrypt, Sectigo, etc.), with extensible connector framework
|
A1["Agent"] --> T1["NGINX"]
|
||||||
- **Zero private key exposure**: Keys generated and managed on agents, never sent to control plane
|
A2["Agent"] --> T2["F5 BIG-IP"]
|
||||||
- **Audit-first design**: Every action logged with full traceability
|
A3["Agent"] --> T3["IIS"]
|
||||||
- **Connector ecosystem**: Extensible issuer, target, and notifier connectors
|
end
|
||||||
- **Self-hosted**: Run on Kubernetes, Docker Compose, or bare metal—no cloud lock-in
|
|
||||||
- **Production-ready**: Graceful error handling, observability, database-backed state
|
API --> PG
|
||||||
|
A1 & A2 & A3 -->|"CSR + status\n(no private keys)"| API
|
||||||
|
API -->|"Signed certs"| A1 & A2 & A3
|
||||||
|
API -->|"Issue/Renew"| CA["Certificate Authorities\nLocal CA · ACME"]
|
||||||
|
```
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### With Docker Compose (Recommended)
|
### Docker Compose (Recommended)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone the repo
|
|
||||||
git clone https://github.com/shankar0123/certctl.git
|
git clone https://github.com/shankar0123/certctl.git
|
||||||
cd certctl
|
cd certctl
|
||||||
|
docker compose -f deploy/docker-compose.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
# Copy example environment variables
|
Wait ~30 seconds, then open **http://localhost:8443** in your browser.
|
||||||
cp .env.example .env
|
|
||||||
|
|
||||||
# Start the stack
|
The dashboard comes pre-loaded with 14 demo certificates, 5 agents, policy rules, audit events, and notifications — a realistic snapshot of a certificate inventory so you can explore immediately.
|
||||||
make docker-up
|
|
||||||
|
|
||||||
# Check health
|
Verify the API:
|
||||||
|
```bash
|
||||||
curl http://localhost:8443/health
|
curl http://localhost:8443/health
|
||||||
|
# {"status":"healthy"}
|
||||||
|
|
||||||
|
curl -s http://localhost:8443/api/v1/certificates | jq '.total'
|
||||||
|
# 14
|
||||||
```
|
```
|
||||||
|
|
||||||
The stack includes PostgreSQL, certctl server, and a sample agent. Logs available via:
|
### Manual Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make docker-logs-server
|
# Prerequisites: Go 1.22+, PostgreSQL 16+
|
||||||
make docker-logs-agent
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Build & Run
|
|
||||||
|
|
||||||
#### Prerequisites
|
|
||||||
- Go 1.22+
|
|
||||||
- PostgreSQL 14+
|
|
||||||
- (Optional) Docker & Docker Compose
|
|
||||||
|
|
||||||
#### Build from Source
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install dependencies
|
|
||||||
go mod download
|
go mod download
|
||||||
|
|
||||||
# Build binaries
|
|
||||||
make build
|
make build
|
||||||
|
|
||||||
# Run migrations
|
# Set up database
|
||||||
export DB_URL="postgres://certctl:certctl@localhost:5432/certctl?sslmode=disable"
|
export CERTCTL_DATABASE_URL="postgres://certctl:certctl@localhost:5432/certctl?sslmode=disable"
|
||||||
|
export CERTCTL_AUTH_TYPE=none
|
||||||
make migrate-up
|
make migrate-up
|
||||||
|
|
||||||
# Start server (in one terminal)
|
# Start server
|
||||||
make run
|
./bin/server
|
||||||
|
|
||||||
# Start agent (in another terminal, with API key from server logs)
|
# Start agent (separate terminal)
|
||||||
API_KEY="<key-from-server>" SERVER_URL=http://localhost:8443 ./bin/agent
|
export CERTCTL_SERVER_URL=http://localhost:8443
|
||||||
|
export CERTCTL_API_KEY=change-me-in-production
|
||||||
|
export CERTCTL_AGENT_NAME=local-agent
|
||||||
|
./bin/agent
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 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 |
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
### System Components
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
subgraph "Control Plane (certctl-server)"
|
||||||
|
DASH["Web Dashboard\nReact SPA"]
|
||||||
|
API["REST API\nGo 1.22 net/http"]
|
||||||
|
SVC["Service Layer"]
|
||||||
|
REPO["Repository Layer\ndatabase/sql + lib/pq"]
|
||||||
|
SCHED["Scheduler\nRenewal · Jobs · Health · Notifications"]
|
||||||
|
end
|
||||||
|
|
||||||
```
|
subgraph "Data Store"
|
||||||
┌─────────────────────────────────────────────────────────┐
|
PG[("PostgreSQL 16\n14 tables · TEXT primary keys")]
|
||||||
│ CONTROL PLANE │
|
end
|
||||||
│ ┌──────────────────────────────────────────────────┐ │
|
|
||||||
│ │ API Server (8443) │ │
|
subgraph "Agents"
|
||||||
│ │ • Certificate management │ │
|
AG["certctl-agent\nKey generation · CSR · Deployment"]
|
||||||
│ │ • Issuance orchestration │ │
|
end
|
||||||
│ │ • Audit logging │ │
|
|
||||||
│ └──────────────────────────────────────────────────┘ │
|
DASH --> API
|
||||||
│ ┌──────────────────────────────────────────────────┐ │
|
API --> SVC --> REPO --> PG
|
||||||
│ │ PostgreSQL Database │ │
|
SCHED --> SVC
|
||||||
│ │ • Certificates, agents, targets, policies │ │
|
AG -->|"Heartbeat + CSR"| API
|
||||||
│ │ • Complete audit trail │ │
|
API -->|"Cert + Chain"| AG
|
||||||
│ └──────────────────────────────────────────────────┘ │
|
|
||||||
└─────────────────────────────────────────────────────────┘
|
|
||||||
│ │
|
|
||||||
│ (mTLS + API Key) │
|
|
||||||
│ │
|
|
||||||
┌────┴────┐ ┌────────┴────┐
|
|
||||||
│ │ │ │
|
|
||||||
┌───┴──┐ ┌──┴───┐ ┌─────┴──┐ ┌──────┴────┐
|
|
||||||
│Agent │ │Agent │ │ Agent │ │ Agent │
|
|
||||||
│ #1 │ │ #2 │ │ #3 │ │ #N │
|
|
||||||
└──────┘ └──────┘ └────────┘ └───────────┘
|
|
||||||
│ │ │ │
|
|
||||||
├────┬────┼────┬───┬──┴─────┬─────┴──┬───┐
|
|
||||||
│ │ │ │ │ │ │ │
|
|
||||||
┌──┴─┐┌─┴──┐┌───┴──┐│┌───────┐│┌──────┐│ │
|
|
||||||
│ACME││K8s ││F5 ││Vault│ │Webhook│
|
|
||||||
│ ││LB ││LB ││ │ │
|
|
||||||
└────┘└────┘└────┘└────┘└──────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Data Flow: Certificate Issuance
|
### Key Design Decisions
|
||||||
|
|
||||||
1. **Create Certificate** → Control plane stores managed certificate record
|
- **Private keys never touch the control plane.** Agents generate keys locally and submit CSRs (public key only). The control plane forwards CSRs to the CA and returns signed certificates. Even if the control plane database is compromised, no private keys are exposed.
|
||||||
2. **Generate CSR** → Agent creates private key (stays local) and CSR
|
- **TEXT primary keys, not UUIDs.** IDs are human-readable prefixed strings (`mc-api-prod`, `t-platform`, `o-alice`) so you can identify resource types at a glance in logs and queries.
|
||||||
3. **Request Certificate** → Agent sends CSR to control plane
|
- **Handler → Service → Repository layering.** Handlers define their own service interfaces for clean dependency inversion. No global service singletons.
|
||||||
4. **Issue via ACME** → Control plane submits to issuer (Let's Encrypt, etc.)
|
- **Idempotent migrations.** All schema uses `IF NOT EXISTS` and seed data uses `ON CONFLICT (id) DO NOTHING`, safe for repeated execution.
|
||||||
5. **Return Certificate** → Agent receives signed cert, stores locally
|
|
||||||
6. **Deploy** → Agent pushes certificate to targets (NGINX, F5, IIS, etc.)
|
|
||||||
7. **Notify** → Webhook or email notification sent on completion
|
|
||||||
|
|
||||||
### Database Schema Overview
|
### Database Schema
|
||||||
|
|
||||||
| Entity | Purpose |
|
| Table | Purpose |
|
||||||
|--------|---------|
|
|-------|---------|
|
||||||
| `certificates` | Managed certificate records with metadata |
|
| `managed_certificates` | Certificate records with metadata, status, expiry, tags |
|
||||||
| `agents` | Registered agents in the fleet |
|
| `certificate_versions` | Historical versions with PEM chains and CSRs |
|
||||||
| `targets` | Deployment targets (NGINX, F5, IIS, etc.) |
|
| `renewal_policies` | Renewal window, auto-renew settings, retry config |
|
||||||
| `issuers` | ACME issuer configurations |
|
| `issuers` | CA configurations (Local CA, ACME, etc.) |
|
||||||
| `jobs` | Issuance and deployment jobs |
|
| `deployment_targets` | Target systems (NGINX, F5, IIS) with agent assignments |
|
||||||
| `audit_logs` | Complete action trail |
|
| `agents` | Registered agents with heartbeat tracking |
|
||||||
|
| `jobs` | Issuance, renewal, deployment, and validation jobs |
|
||||||
|
| `teams` | Organizational groups for certificate ownership |
|
||||||
|
| `owners` | Individual owners with email for notifications |
|
||||||
|
| `policy_rules` | Enforcement rules (allowed issuers, environments, metadata) |
|
||||||
|
| `policy_violations` | Flagged non-compliance with severity levels |
|
||||||
|
| `audit_events` | Immutable action log (append-only, no update/delete) |
|
||||||
|
| `notification_events` | Email and webhook notification records |
|
||||||
|
| `certificate_target_mappings` | Many-to-many cert ↔ target relationships |
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### Environment Variables
|
All server environment variables use the `CERTCTL_` prefix:
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|----------|---------|-------------|
|
|----------|---------|-------------|
|
||||||
| `SERVER_HOST` | `0.0.0.0` | Server bind address |
|
| `CERTCTL_SERVER_HOST` | `127.0.0.1` | Server bind address |
|
||||||
| `SERVER_PORT` | `8443` | Server listen port |
|
| `CERTCTL_SERVER_PORT` | `8080` | Server listen port |
|
||||||
| `DB_HOST` | `localhost` | PostgreSQL host |
|
| `CERTCTL_DATABASE_URL` | `postgres://localhost/certctl` | PostgreSQL connection string |
|
||||||
| `DB_PORT` | `5432` | PostgreSQL port |
|
| `CERTCTL_DATABASE_MAX_CONNS` | `25` | Connection pool size |
|
||||||
| `DB_USER` | `certctl` | Database user |
|
| `CERTCTL_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
||||||
| `DB_PASSWORD` | — | Database password |
|
| `CERTCTL_LOG_FORMAT` | `json` | Log format: `json` or `text` |
|
||||||
| `DB_NAME` | `certctl` | Database name |
|
| `CERTCTL_AUTH_TYPE` | `api-key` | Auth mode: `api-key`, `jwt`, or `none` |
|
||||||
| `LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |
|
| `CERTCTL_AUTH_SECRET` | — | Required for `api-key` and `jwt` auth types |
|
||||||
| `ACME_DIRECTORY_URL` | staging | ACME directory URL |
|
|
||||||
| `ACME_EMAIL` | — | ACME registration email |
|
|
||||||
| `SMTP_HOST` | — | SMTP server for email notifications |
|
|
||||||
| `SMTP_PORT` | `587` | SMTP port |
|
|
||||||
| `SMTP_USERNAME` | — | SMTP username |
|
|
||||||
| `SMTP_PASSWORD` | — | SMTP password |
|
|
||||||
| `SMTP_FROM_ADDRESS` | — | Email from address |
|
|
||||||
|
|
||||||
See `.env.example` for complete reference.
|
Agent environment variables:
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `CERTCTL_SERVER_URL` | `http://localhost:8080` | Control plane URL |
|
||||||
|
| `CERTCTL_API_KEY` | — | Agent API key |
|
||||||
|
| `CERTCTL_AGENT_NAME` | `certctl-agent` | Agent display name |
|
||||||
|
|
||||||
|
Docker Compose overrides these for the demo stack (see `deploy/docker-compose.yml`): port `8443`, auth type `none`, database pointing to the postgres container.
|
||||||
|
|
||||||
## API Overview
|
## API Overview
|
||||||
|
|
||||||
### Key Endpoints
|
All endpoints are under `/api/v1/` and return JSON. List endpoints support pagination (`?page=1&per_page=50`).
|
||||||
|
|
||||||
#### Certificates
|
### Certificates
|
||||||
- `POST /api/v1/certificates` — Create managed certificate
|
```
|
||||||
- `GET /api/v1/certificates` — List certificates
|
GET /api/v1/certificates List (filter: status, environment, owner_id, team_id)
|
||||||
- `GET /api/v1/certificates/:id` — Get certificate details
|
POST /api/v1/certificates Create
|
||||||
- `PUT /api/v1/certificates/:id` — Update certificate
|
GET /api/v1/certificates/{id} Get
|
||||||
- `DELETE /api/v1/certificates/:id` — Archive certificate
|
PUT /api/v1/certificates/{id} Update
|
||||||
|
DELETE /api/v1/certificates/{id} Archive (soft delete)
|
||||||
|
GET /api/v1/certificates/{id}/versions Version history
|
||||||
|
POST /api/v1/certificates/{id}/renew Trigger renewal → 202 Accepted
|
||||||
|
POST /api/v1/certificates/{id}/deploy Trigger deployment → 202 Accepted
|
||||||
|
```
|
||||||
|
|
||||||
#### Agents
|
### Agents
|
||||||
- `POST /api/v1/agents` — Register new agent
|
```
|
||||||
- `GET /api/v1/agents` — List agents
|
GET /api/v1/agents List
|
||||||
- `GET /api/v1/agents/:id` — Get agent details
|
POST /api/v1/agents Register
|
||||||
- `PUT /api/v1/agents/:id` — Update agent
|
GET /api/v1/agents/{id} Get
|
||||||
|
POST /api/v1/agents/{id}/heartbeat Record heartbeat
|
||||||
|
POST /api/v1/agents/{id}/csr Submit CSR for issuance
|
||||||
|
GET /api/v1/agents/{id}/certificates/{certId} Retrieve signed certificate
|
||||||
|
```
|
||||||
|
|
||||||
#### Targets
|
### Infrastructure
|
||||||
- `POST /api/v1/targets` — Add deployment target
|
```
|
||||||
- `GET /api/v1/targets` — List targets
|
GET /api/v1/issuers List issuers
|
||||||
- `PUT /api/v1/targets/:id` — Update target
|
POST /api/v1/issuers Create
|
||||||
- `DELETE /api/v1/targets/:id` — Remove target
|
GET /api/v1/issuers/{id} Get
|
||||||
|
POST /api/v1/issuers/{id}/test Test connectivity
|
||||||
|
|
||||||
#### Issuers
|
GET /api/v1/targets List deployment targets
|
||||||
- `POST /api/v1/issuers` — Register ACME issuer
|
POST /api/v1/targets Create
|
||||||
- `GET /api/v1/issuers` — List issuers
|
GET /api/v1/targets/{id} Get
|
||||||
- `PUT /api/v1/issuers/:id` — Update issuer
|
```
|
||||||
|
|
||||||
#### Audit
|
### Organization
|
||||||
- `GET /api/v1/audit/logs` — Query audit trail
|
```
|
||||||
- `GET /api/v1/audit/logs/:id` — Get specific log entry
|
GET /api/v1/teams List teams
|
||||||
|
POST /api/v1/teams Create
|
||||||
|
GET /api/v1/owners List owners
|
||||||
|
POST /api/v1/owners Create
|
||||||
|
```
|
||||||
|
|
||||||
#### System
|
### Operations
|
||||||
- `GET /health` — Health check
|
```
|
||||||
|
GET /api/v1/jobs List (filter: status, type)
|
||||||
|
GET /api/v1/jobs/{id} Get
|
||||||
|
POST /api/v1/jobs/{id}/cancel Cancel
|
||||||
|
|
||||||
Full API docs: [docs/api.md](docs/api.md) (coming soon)
|
GET /api/v1/policies List policy rules
|
||||||
|
POST /api/v1/policies Create
|
||||||
|
GET /api/v1/policies/{id}/violations List violations for rule
|
||||||
|
|
||||||
## Agent Setup Guide
|
GET /api/v1/audit Query audit trail
|
||||||
|
GET /api/v1/notifications List notifications
|
||||||
|
```
|
||||||
|
|
||||||
### Installation
|
### Health
|
||||||
|
```
|
||||||
Agents can be deployed as:
|
GET /health Server health check
|
||||||
- **Docker container**: `docker pull certctl:agent`
|
GET /ready Readiness check
|
||||||
- **Systemd service**: `systemctl start certctl-agent`
|
|
||||||
- **Kubernetes DaemonSet**: See [docs/k8s-deployment.md](docs/k8s-deployment.md)
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
Agents require:
|
|
||||||
1. **Server URL**: Control plane address (e.g., `https://certctl.example.com:8443`)
|
|
||||||
2. **API Key**: Issued by control plane on agent registration
|
|
||||||
3. **Agent Name**: Unique identifier in fleet
|
|
||||||
|
|
||||||
Example systemd unit:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[Unit]
|
|
||||||
Description=Certctl Agent
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/opt/certctl-agent/agent
|
|
||||||
Environment="SERVER_URL=https://certctl.example.com:8443"
|
|
||||||
Environment="API_KEY=ey..."
|
|
||||||
Environment="AGENT_NAME=prod-web-01"
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=10s
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported Integrations
|
## Supported Integrations
|
||||||
|
|
||||||
### Certificate Issuers
|
### Certificate Issuers
|
||||||
| Issuer | Status | Connector |
|
| Issuer | Status | Type |
|
||||||
|--------|--------|-----------|
|
|--------|--------|------|
|
||||||
| Let's Encrypt (ACME v2) | ✓ Production | `acme` |
|
| Local CA (self-signed) | Implemented | `GenericCA` |
|
||||||
| Sectigo ACME | ✓ Tested | `acme` |
|
| ACME v2 (Let's Encrypt, Sectigo) | In progress | `ACME` |
|
||||||
| Vault PKI | ◐ Planned | `vault` |
|
| Vault PKI | Planned | — |
|
||||||
| DigiCert | ◐ Planned | `digicert` |
|
| DigiCert | Planned | — |
|
||||||
|
|
||||||
### Deployment Targets
|
### Deployment Targets
|
||||||
| Target | Status | Connector |
|
| Target | Status | Type |
|
||||||
|--------|--------|-----------|
|
|--------|--------|------|
|
||||||
| NGINX | ✓ Production | `nginx` |
|
| NGINX | Implemented | `NGINX` |
|
||||||
| F5 BIG-IP | ✓ Tested | `f5` |
|
| F5 BIG-IP | Implemented | `F5` |
|
||||||
| Microsoft IIS | ✓ Tested | `iis` |
|
| Microsoft IIS | Implemented | `IIS` |
|
||||||
| Kubernetes Secrets | ◐ Planned | `k8s` |
|
| Kubernetes Secrets | Planned | — |
|
||||||
| AWS CloudFront | ◐ Planned | `aws` |
|
|
||||||
|
|
||||||
### Notifiers
|
### Notifiers
|
||||||
| Notifier | Status | Connector |
|
| Notifier | Status | Type |
|
||||||
|----------|--------|-----------|
|
|----------|--------|------|
|
||||||
| Email (SMTP) | ✓ Production | `email` |
|
| Email (SMTP) | Implemented | `Email` |
|
||||||
| Webhooks | ✓ Production | `webhook` |
|
| Webhooks | Implemented | `Webhook` |
|
||||||
| Slack | ◐ Planned | `slack` |
|
| Slack | Planned | — |
|
||||||
| PagerDuty | ◐ Planned | `pagerduty` |
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
### Local Setup
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Install dev tools (golangci-lint, migrate CLI, air)
|
||||||
make install-tools
|
make install-tools
|
||||||
cp .env.example .env
|
|
||||||
make docker-up-dev
|
|
||||||
|
|
||||||
# Access PgAdmin at http://localhost:5050
|
# Run tests
|
||||||
# Server logs: make docker-logs-server
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run all tests
|
|
||||||
make test
|
make test
|
||||||
|
|
||||||
# Run with coverage
|
# Run with coverage
|
||||||
make test-coverage
|
make test-coverage
|
||||||
|
|
||||||
# Run specific package
|
# Lint
|
||||||
go test -v ./internal/service/...
|
make lint
|
||||||
|
|
||||||
|
# Format
|
||||||
|
make fmt
|
||||||
```
|
```
|
||||||
|
|
||||||
### Linting & Format
|
### Docker Compose
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make lint
|
make docker-up # Start stack (server + postgres + agent)
|
||||||
make fmt
|
make docker-down # Stop stack
|
||||||
make vet
|
make docker-logs-server # Server logs
|
||||||
|
make docker-logs-agent # Agent logs
|
||||||
|
make docker-clean # Stop + remove volumes
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building Connectors
|
|
||||||
|
|
||||||
See [docs/connectors.md](docs/connectors.md) for a step-by-step guide to building issuers, targets, and notifier connectors.
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
1. Fork the repository
|
|
||||||
2. Create a feature branch: `git checkout -b feature/my-feature`
|
|
||||||
3. Commit changes: `git commit -am 'Add feature'`
|
|
||||||
4. Push to branch: `git push origin feature/my-feature`
|
|
||||||
5. Open a pull request
|
|
||||||
|
|
||||||
### Code Standards
|
|
||||||
- Go 1.22+ with `go fmt`, `go vet`, `golangci-lint`
|
|
||||||
- Tests required for new features (>80% coverage)
|
|
||||||
- Clear commit messages
|
|
||||||
- Update relevant documentation
|
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
### Private Key Management
|
### Private Key Management
|
||||||
- Private keys **never** sent to control plane
|
- Private keys are generated exclusively on agents, never sent to the control plane
|
||||||
- Keys generated and managed exclusively on agents
|
- Keys stored with file permissions 0600
|
||||||
- Encrypted at rest on agent systems
|
- Old keys deleted after successful certificate renewal
|
||||||
- Cleared from memory after use
|
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
- Agent-to-server: mTLS + API key
|
- Agent-to-server: API key (registered at agent creation)
|
||||||
- API key rotation supported
|
- API key and JWT auth types supported; `none` for demo/development
|
||||||
- Audit logging of all authenticated actions
|
- Auth type and secret configured via `CERTCTL_AUTH_TYPE` and `CERTCTL_AUTH_SECRET`
|
||||||
|
|
||||||
### Audit Trail
|
### Audit Trail
|
||||||
- Complete action history in PostgreSQL
|
- Immutable append-only log in PostgreSQL (`audit_events` table)
|
||||||
- Immutable audit logs
|
- Every action attributed to an actor with timestamp and resource reference
|
||||||
- Queryable by resource, user, timestamp, action
|
- No update or delete operations on audit records
|
||||||
|
|
||||||
For security issues, email security@example.com (do not open public issues).
|
|
||||||
|
|
||||||
## Performance & Scaling
|
|
||||||
|
|
||||||
- **Agents**: Stateless, horizontal scaling via fleet management
|
|
||||||
- **Control Plane**: Single server handles 1000+ agents
|
|
||||||
- **Database**: PostgreSQL; vertical scaling recommended
|
|
||||||
- **Jobs**: Asynchronous processing; tunable concurrency
|
|
||||||
|
|
||||||
See [docs/scaling.md](docs/scaling.md) for deployment guidance.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Server Won't Start
|
|
||||||
```bash
|
|
||||||
# Check database connection
|
|
||||||
psql -h localhost -U certctl -d certctl
|
|
||||||
|
|
||||||
# Check logs
|
|
||||||
make docker-logs-server
|
|
||||||
|
|
||||||
# Verify environment variables
|
|
||||||
env | grep -E "DB_|SERVER_|ACME_"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Agent Can't Connect
|
|
||||||
```bash
|
|
||||||
# Check server health
|
|
||||||
curl -v https://certctl.example.com:8443/health
|
|
||||||
|
|
||||||
# Verify API key
|
|
||||||
echo $API_KEY
|
|
||||||
|
|
||||||
# Check agent logs
|
|
||||||
make docker-logs-agent
|
|
||||||
```
|
|
||||||
|
|
||||||
### Certificate Not Deploying
|
|
||||||
1. Check agent is registered: `curl http://localhost:8443/api/v1/agents`
|
|
||||||
2. Check target is reachable: `curl http://target-server:22` (SSH test)
|
|
||||||
3. Review audit log: `curl http://localhost:8443/api/v1/audit/logs`
|
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
- [ ] Kubernetes CRD for certificate management
|
Summary:
|
||||||
- [ ] Terraform provider
|
|
||||||
- [ ] Multi-region deployment
|
- **V1 (current)**: Dashboard, inventory, alerting, Local CA + ACME issuers, NGINX/F5/IIS targets, agents, REST API, policies, audit trail, Docker Compose
|
||||||
- [ ] HA control plane with etcd backend
|
- **V2**: Charts/trends, bulk import, OIDC/SSO, deployment rollback, CLI, Slack/Teams
|
||||||
- [ ] Advanced scheduling policies
|
- **V3**: Certificate discovery, network scanning, unknown cert detection
|
||||||
- [ ] Certificate pinning validation
|
- **V4+**: Kubernetes CRD, Terraform provider, multi-region, HA control plane, HSM support
|
||||||
- [ ] Hardware security module (HSM) support
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Certctl is licensed under the [Apache License 2.0](LICENSE). See LICENSE file for details.
|
Certctl is licensed under the [Apache License 2.0](LICENSE). See LICENSE file for details.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user