Certificore - Certificate Lifecycle Platform
Overview
Enterprise-grade certificate lifecycle management platform. Unified API for managing certificates across multiple Certificate Authorities (Vault PKI, ADCS, ACME/Let’s Encrypt, DigiCert).
Inspiration: Swagger/OpenAPI learning project with real-world enterprise applicability.
Problem Statement
Certificate management pain points:
-
Certificates scattered across multiple CAs
-
No unified inventory or expiry tracking
-
Manual renewal processes prone to outages
-
Compliance reporting requires manual aggregation
-
No visibility into where certificates are deployed
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Certificore API │
│ (FastAPI + OpenAPI) │
├─────────────────────────────────────────────────────────────┤
│ /authorities /certificates /policies /deployments │
└───────────────────────┬─────────────────────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Vault PKI │ │ ADCS │ │ Let's Encrypt│
│ (DOMUS) │ │ (Legacy) │ │ (ACME) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└───────────────┴───────────────┘
│
▼
┌──────────────────┐
│ PostgreSQL │
│ (Source of │
│ Truth) │
└──────────────────┘
Database Schema
-- Certificate Authorities
CREATE TABLE ca_authorities (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL UNIQUE,
type VARCHAR(50) NOT NULL, -- vault, adcs, acme, digicert
endpoint VARCHAR(512),
config JSONB,
enabled BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Certificates
CREATE TABLE certificates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
ca_id UUID REFERENCES ca_authorities(id),
common_name VARCHAR(255) NOT NULL,
sans TEXT[], -- Subject Alternative Names
serial_number VARCHAR(255),
fingerprint_sha256 VARCHAR(64),
not_before TIMESTAMPTZ,
not_after TIMESTAMPTZ,
key_type VARCHAR(20), -- rsa, ecdsa, ed25519
key_size INTEGER,
status VARCHAR(20) DEFAULT 'active', -- active, revoked, expired
pem_certificate TEXT,
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Policies
CREATE TABLE policies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL UNIQUE,
description TEXT,
min_key_size INTEGER DEFAULT 2048,
max_ttl_days INTEGER DEFAULT 365,
allowed_key_types TEXT[] DEFAULT ARRAY['rsa', 'ecdsa'],
allowed_domains TEXT[],
require_san BOOLEAN DEFAULT true,
auto_renew_days INTEGER DEFAULT 30,
enabled BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Deployments (where certs are installed)
CREATE TABLE deployments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
certificate_id UUID REFERENCES certificates(id),
target_type VARCHAR(50), -- server, loadbalancer, ise, keycloak
target_host VARCHAR(255),
target_path VARCHAR(512),
deployment_method VARCHAR(50), -- manual, ssh, api, kubernetes
last_deployed TIMESTAMPTZ,
status VARCHAR(20) DEFAULT 'pending',
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Audit Log
CREATE TABLE audit_log (
id BIGSERIAL PRIMARY KEY,
action VARCHAR(50) NOT NULL,
entity_type VARCHAR(50),
entity_id UUID,
actor VARCHAR(255),
details JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Indexes
CREATE INDEX idx_certificates_expiry ON certificates(not_after);
CREATE INDEX idx_certificates_cn ON certificates(common_name);
CREATE INDEX idx_deployments_cert ON deployments(certificate_id);
CREATE INDEX idx_audit_entity ON audit_log(entity_type, entity_id);
API Endpoints (OpenAPI)
Authorities
| Method | Endpoint | Description |
|---|---|---|
GET |
|
List all certificate authorities |
POST |
|
Register new CA |
GET |
|
Get CA details |
POST |
|
Sync certificates from CA |
Certificates
| Method | Endpoint | Description |
|---|---|---|
GET |
|
List all certificates (paginated) |
POST |
|
Issue new certificate |
GET |
|
Get certificate details |
POST |
|
Renew certificate |
DELETE |
|
Revoke certificate |
GET |
|
List expiring certs (?days=30) |
GET |
|
Search by CN, SAN, fingerprint |
Policies
| Method | Endpoint | Description |
|---|---|---|
GET |
|
List all policies |
POST |
|
Create policy |
GET |
|
Evaluate cert against policy |
Tech Stack
| Component | Technology |
|---|---|
Language |
Python 3.11+ |
Framework |
FastAPI (auto OpenAPI generation) |
Database |
PostgreSQL 15+ |
ORM |
SQLAlchemy 2.0 + Alembic (migrations) |
Validation |
Pydantic v2 |
Auth |
OAuth2 / API Keys |
Async |
asyncio + asyncpg |
Testing |
pytest + httpx |
Docs |
Swagger UI + ReDoc (built into FastAPI) |
MVP Milestones
Phase 1: Foundation (2 weeks)
-
PostgreSQL schema + migrations
-
FastAPI project structure
-
CRUD for authorities, certificates, policies
-
OpenAPI spec auto-generation
-
Basic auth (API keys)
Phase 2: Vault Integration (1 week)
-
Vault PKI provider adapter
-
Issue certificates via API
-
Sync existing certs from Vault
-
Certificate renewal workflow
Scale Considerations
Integration Points
| System | Integration |
|---|---|
HashiCorp Vault |
PKI secrets engine API |
Microsoft ADCS |
DCOM/WMI or certreq CLI |
Let’s Encrypt |
ACME protocol (certbot library) |
Kubernetes |
cert-manager CRDs |
ISE |
ERS API for cert deployment |
Keycloak |
Admin API for cert updates |
ServiceNow |
Incident creation for expiring certs |
Slack/Teams |
Webhook notifications |
Repository Structure
certificore/
├── alembic/ # Database migrations
│ └── versions/
├── app/
│ ├── api/
│ │ ├── v1/
│ │ │ ├── authorities.py
│ │ │ ├── certificates.py
│ │ │ ├── policies.py
│ │ │ └── deployments.py
│ │ └── deps.py # Dependencies (auth, db)
│ ├── core/
│ │ ├── config.py
│ │ └── security.py
│ ├── db/
│ │ ├── models.py
│ │ └── session.py
│ ├── providers/ # CA adapters
│ │ ├── base.py
│ │ ├── vault.py
│ │ ├── adcs.py
│ │ └── acme.py
│ ├── schemas/ # Pydantic models
│ │ ├── authority.py
│ │ ├── certificate.py
│ │ └── policy.py
│ └── main.py
├── tests/
├── docker-compose.yml
├── Dockerfile
├── pyproject.toml
└── README.md