mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 17:22:07 +00:00
c153361bbc
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>
315 lines
11 KiB
Markdown
315 lines
11 KiB
Markdown
# certctl — Open-Source Certificate 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)
|
|
[](https://goreportcard.com/report/github.com/shankar0123/certctl)
|
|

|
|
|
|
## 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** (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.
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph "Control Plane"
|
|
API["REST API + Dashboard\n:8443"]
|
|
PG[("PostgreSQL")]
|
|
end
|
|
|
|
subgraph "Your Infrastructure"
|
|
A1["Agent"] --> T1["NGINX"]
|
|
A2["Agent"] --> T2["F5 BIG-IP"]
|
|
A3["Agent"] --> T3["IIS"]
|
|
end
|
|
|
|
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
|
|
|
|
### Docker Compose (Recommended)
|
|
|
|
```bash
|
|
git clone https://github.com/shankar0123/certctl.git
|
|
cd certctl
|
|
docker compose -f deploy/docker-compose.yml up -d
|
|
```
|
|
|
|
Wait ~30 seconds, then open **http://localhost:8443** in your browser.
|
|
|
|
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.
|
|
|
|
Verify the API:
|
|
```bash
|
|
curl http://localhost:8443/health
|
|
# {"status":"healthy"}
|
|
|
|
curl -s http://localhost:8443/api/v1/certificates | jq '.total'
|
|
# 14
|
|
```
|
|
|
|
### Manual Build
|
|
|
|
```bash
|
|
# Prerequisites: Go 1.22+, PostgreSQL 16+
|
|
go mod download
|
|
make build
|
|
|
|
# Set up database
|
|
export CERTCTL_DATABASE_URL="postgres://certctl:certctl@localhost:5432/certctl?sslmode=disable"
|
|
export CERTCTL_AUTH_TYPE=none
|
|
make migrate-up
|
|
|
|
# Start server
|
|
./bin/server
|
|
|
|
# Start agent (separate terminal)
|
|
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
|
|
|
|
```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")]
|
|
end
|
|
|
|
subgraph "Agents"
|
|
AG["certctl-agent\nKey generation · CSR · Deployment"]
|
|
end
|
|
|
|
DASH --> API
|
|
API --> SVC --> REPO --> PG
|
|
SCHED --> SVC
|
|
AG -->|"Heartbeat + CSR"| API
|
|
API -->|"Cert + Chain"| AG
|
|
```
|
|
|
|
### Key Design Decisions
|
|
|
|
- **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.
|
|
- **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.
|
|
- **Handler → Service → Repository layering.** Handlers define their own service interfaces for clean dependency inversion. No global service singletons.
|
|
- **Idempotent migrations.** All schema uses `IF NOT EXISTS` and seed data uses `ON CONFLICT (id) DO NOTHING`, safe for repeated execution.
|
|
|
|
### Database Schema
|
|
|
|
| Table | Purpose |
|
|
|-------|---------|
|
|
| `managed_certificates` | Certificate records with metadata, status, expiry, tags |
|
|
| `certificate_versions` | Historical versions with PEM chains and CSRs |
|
|
| `renewal_policies` | Renewal window, auto-renew settings, retry config |
|
|
| `issuers` | CA configurations (Local CA, ACME, etc.) |
|
|
| `deployment_targets` | Target systems (NGINX, F5, IIS) with agent assignments |
|
|
| `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
|
|
|
|
All server environment variables use the `CERTCTL_` prefix:
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `CERTCTL_SERVER_HOST` | `127.0.0.1` | Server bind address |
|
|
| `CERTCTL_SERVER_PORT` | `8080` | Server listen port |
|
|
| `CERTCTL_DATABASE_URL` | `postgres://localhost/certctl` | PostgreSQL connection string |
|
|
| `CERTCTL_DATABASE_MAX_CONNS` | `25` | Connection pool size |
|
|
| `CERTCTL_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
|
| `CERTCTL_LOG_FORMAT` | `json` | Log format: `json` or `text` |
|
|
| `CERTCTL_AUTH_TYPE` | `api-key` | Auth mode: `api-key`, `jwt`, or `none` |
|
|
| `CERTCTL_AUTH_SECRET` | — | Required for `api-key` and `jwt` auth types |
|
|
|
|
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
|
|
|
|
All endpoints are under `/api/v1/` and return JSON. List endpoints support pagination (`?page=1&per_page=50`).
|
|
|
|
### Certificates
|
|
```
|
|
GET /api/v1/certificates List (filter: status, environment, owner_id, team_id)
|
|
POST /api/v1/certificates Create
|
|
GET /api/v1/certificates/{id} Get
|
|
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
|
|
```
|
|
GET /api/v1/agents List
|
|
POST /api/v1/agents Register
|
|
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
|
|
```
|
|
|
|
### Infrastructure
|
|
```
|
|
GET /api/v1/issuers List issuers
|
|
POST /api/v1/issuers Create
|
|
GET /api/v1/issuers/{id} Get
|
|
POST /api/v1/issuers/{id}/test Test connectivity
|
|
|
|
GET /api/v1/targets List deployment targets
|
|
POST /api/v1/targets Create
|
|
GET /api/v1/targets/{id} Get
|
|
```
|
|
|
|
### Organization
|
|
```
|
|
GET /api/v1/teams List teams
|
|
POST /api/v1/teams Create
|
|
GET /api/v1/owners List owners
|
|
POST /api/v1/owners Create
|
|
```
|
|
|
|
### Operations
|
|
```
|
|
GET /api/v1/jobs List (filter: status, type)
|
|
GET /api/v1/jobs/{id} Get
|
|
POST /api/v1/jobs/{id}/cancel Cancel
|
|
|
|
GET /api/v1/policies List policy rules
|
|
POST /api/v1/policies Create
|
|
GET /api/v1/policies/{id}/violations List violations for rule
|
|
|
|
GET /api/v1/audit Query audit trail
|
|
GET /api/v1/notifications List notifications
|
|
```
|
|
|
|
### Health
|
|
```
|
|
GET /health Server health check
|
|
GET /ready Readiness check
|
|
```
|
|
|
|
## Supported Integrations
|
|
|
|
### Certificate Issuers
|
|
| Issuer | Status | Type |
|
|
|--------|--------|------|
|
|
| Local CA (self-signed) | Implemented | `GenericCA` |
|
|
| ACME v2 (Let's Encrypt, Sectigo) | In progress | `ACME` |
|
|
| Vault PKI | Planned | — |
|
|
| DigiCert | Planned | — |
|
|
|
|
### Deployment Targets
|
|
| Target | Status | Type |
|
|
|--------|--------|------|
|
|
| NGINX | Implemented | `NGINX` |
|
|
| F5 BIG-IP | Implemented | `F5` |
|
|
| Microsoft IIS | Implemented | `IIS` |
|
|
| Kubernetes Secrets | Planned | — |
|
|
|
|
### Notifiers
|
|
| Notifier | Status | Type |
|
|
|----------|--------|------|
|
|
| Email (SMTP) | Implemented | `Email` |
|
|
| Webhooks | Implemented | `Webhook` |
|
|
| Slack | Planned | — |
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Install dev tools (golangci-lint, migrate CLI, air)
|
|
make install-tools
|
|
|
|
# Run tests
|
|
make test
|
|
|
|
# Run with coverage
|
|
make test-coverage
|
|
|
|
# Lint
|
|
make lint
|
|
|
|
# Format
|
|
make fmt
|
|
```
|
|
|
|
### Docker Compose
|
|
|
|
```bash
|
|
make docker-up # Start stack (server + postgres + agent)
|
|
make docker-down # Stop stack
|
|
make docker-logs-server # Server logs
|
|
make docker-logs-agent # Agent logs
|
|
make docker-clean # Stop + remove volumes
|
|
```
|
|
|
|
## Security
|
|
|
|
### Private Key Management
|
|
- Private keys are generated exclusively on agents, never sent to the control plane
|
|
- Keys stored with file permissions 0600
|
|
- Old keys deleted after successful certificate renewal
|
|
|
|
### Authentication
|
|
- Agent-to-server: API key (registered at agent creation)
|
|
- API key and JWT auth types supported; `none` for demo/development
|
|
- Auth type and secret configured via `CERTCTL_AUTH_TYPE` and `CERTCTL_AUTH_SECRET`
|
|
|
|
### Audit Trail
|
|
- Immutable append-only log in PostgreSQL (`audit_events` table)
|
|
- Every action attributed to an actor with timestamp and resource reference
|
|
- No update or delete operations on audit records
|
|
|
|
## Roadmap
|
|
|
|
Summary:
|
|
|
|
- **V1 (current)**: Dashboard, inventory, alerting, Local CA + ACME issuers, NGINX/F5/IIS targets, agents, REST API, policies, audit trail, Docker Compose
|
|
- **V2**: Charts/trends, bulk import, OIDC/SSO, deployment rollback, CLI, Slack/Teams
|
|
- **V3**: Certificate discovery, network scanning, unknown cert detection
|
|
- **V4+**: Kubernetes CRD, Terraform provider, multi-region, HA control plane, HSM support
|
|
|
|
## License
|
|
|
|
Certctl is licensed under the [Apache License 2.0](LICENSE). See LICENSE file for details.
|