Some checks failed
CI / Lint & Format (push) Failing after 16s
CI / Unit Tests (push) Has been skipped
CI / Memory Leak Check (push) Has been skipped
CI / SBOM Generation (push) Has been skipped
CI / Security Scan (push) Failing after 22s
CI / Security Tests (push) Has been skipped
- README: update test count from 283 to 337 - pki.md: fix environment variable names (PKI_CA_PASSWORD) - pki.md: correct CLI usage examples (config via env/file) - pki.md: update pki status output format - pki.md: clarify revocation is API-only (no CLI command)
196 lines
4.7 KiB
Markdown
196 lines
4.7 KiB
Markdown
# PKI Guide
|
|
|
|
FlaskPaste includes a built-in Public Key Infrastructure (PKI) for client certificate authentication.
|
|
|
|
## Overview
|
|
|
|
The PKI system provides:
|
|
- Self-contained Certificate Authority (CA)
|
|
- Client certificate issuance
|
|
- Certificate revocation
|
|
- mTLS authentication via reverse proxy
|
|
|
|
## Quick Start with CLI
|
|
|
|
### 1. Register and Get a Certificate
|
|
|
|
```bash
|
|
# Download CLI
|
|
curl -o fpaste https://paste.example.com/client && chmod +x fpaste
|
|
|
|
# Configure server (environment or config file)
|
|
export FLASKPASTE_SERVER="https://paste.example.com"
|
|
# Or: echo "server = https://paste.example.com" >> ~/.config/fpaste/config
|
|
|
|
# Register and auto-configure
|
|
./fpaste register --configure
|
|
|
|
# Creates ~/.config/fpaste/{client.key, client.crt, client.p12} and updates config
|
|
```
|
|
|
|
### 2. Use Authenticated Requests
|
|
|
|
```bash
|
|
# Create paste (now authenticated)
|
|
echo "secret data" | ./fpaste create
|
|
|
|
# List your pastes
|
|
./fpaste list
|
|
|
|
# Delete a paste
|
|
./fpaste delete <id>
|
|
```
|
|
|
|
## Server Setup
|
|
|
|
### Enable PKI
|
|
|
|
```bash
|
|
# Enable PKI and set CA password (required for certificate operations)
|
|
export FLASKPASTE_PKI_ENABLED=1
|
|
export FLASKPASTE_PKI_CA_PASSWORD="your-secure-password"
|
|
|
|
# Optional: set certificate validity period (default: 365 days)
|
|
export FLASKPASTE_PKI_CERT_DAYS=365
|
|
|
|
# Start server
|
|
python run.py
|
|
```
|
|
|
|
### Initialize CA
|
|
|
|
The CA is auto-generated on first certificate request, or manually:
|
|
|
|
```bash
|
|
curl -X POST https://paste.example.com/pki/ca \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"common_name": "My Paste CA"}'
|
|
```
|
|
|
|
## CLI Certificate Management
|
|
|
|
### Check PKI Status
|
|
|
|
```bash
|
|
./fpaste pki status
|
|
```
|
|
|
|
Output:
|
|
```
|
|
pki enabled: True
|
|
ca exists: True
|
|
common name: FlaskPaste CA
|
|
fingerprint: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
|
|
created: 2024-12-25T10:30:00Z
|
|
expires: 2034-12-25T10:30:00Z
|
|
download: https://paste.example.com/pki/ca.crt
|
|
```
|
|
|
|
### Download CA Certificate
|
|
|
|
```bash
|
|
# Save and configure
|
|
./fpaste pki download -o ~/.config/fpaste/ca.crt --configure
|
|
|
|
# Or just view
|
|
./fpaste pki download
|
|
```
|
|
|
|
### Issue Certificate (Admin)
|
|
|
|
```bash
|
|
# Requires admin privileges (first registered user)
|
|
./fpaste pki issue -n "alice" -o ./alice-certs/ --configure
|
|
```
|
|
|
|
### Revoke Certificate (API)
|
|
|
|
Certificate revocation is done via the API:
|
|
|
|
```bash
|
|
# Get certificate serial from /pki/certs
|
|
curl -H "X-SSL-Client-SHA1: <your-fingerprint>" https://paste.example.com/pki/certs
|
|
|
|
# Revoke by serial number
|
|
curl -X POST -H "X-SSL-Client-SHA1: <your-fingerprint>" \
|
|
https://paste.example.com/pki/revoke/<serial>
|
|
```
|
|
|
|
## Self-Signed Certificate (Offline)
|
|
|
|
Generate a certificate without server interaction:
|
|
|
|
```bash
|
|
./fpaste cert -o ~/.config/fpaste/ --configure
|
|
|
|
# With custom options
|
|
./fpaste cert -n "my-client" -a ec -c secp384r1 -d 365
|
|
```
|
|
|
|
## Reverse Proxy Configuration
|
|
|
|
### nginx with mTLS
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name paste.example.com;
|
|
|
|
# Server certificate
|
|
ssl_certificate /etc/ssl/certs/paste.example.com.crt;
|
|
ssl_certificate_key /etc/ssl/private/paste.example.com.key;
|
|
|
|
# Client certificate verification
|
|
ssl_client_certificate /etc/ssl/certs/flaskpaste-ca.crt;
|
|
ssl_verify_client optional;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:5000;
|
|
proxy_set_header X-SSL-Client-SHA1 $ssl_client_fingerprint;
|
|
proxy_set_header X-Proxy-Secret "your-shared-secret";
|
|
}
|
|
}
|
|
```
|
|
|
|
### HAProxy with mTLS
|
|
|
|
```haproxy
|
|
frontend https
|
|
bind *:443 ssl crt /etc/ssl/paste.pem ca-file /etc/ssl/flaskpaste-ca.crt verify optional
|
|
http-request set-header X-SSL-Client-SHA1 %{+Q}[ssl_c_sha1]
|
|
http-request set-header X-Proxy-Secret your-shared-secret
|
|
default_backend flaskpaste
|
|
|
|
backend flaskpaste
|
|
server app 127.0.0.1:5000
|
|
```
|
|
|
|
## Trust Levels
|
|
|
|
| Level | Source | Expiry | Limits |
|
|
|-------|--------|--------|--------|
|
|
| Anonymous | No auth | 1 day | 3 MiB |
|
|
| Untrusted | Self-signed cert | 7 days | 50 MiB |
|
|
| Trusted | PKI-issued cert | 30 days | 50 MiB |
|
|
| Admin | First PKI user | 30 days | 50 MiB + admin ops |
|
|
|
|
## Security Considerations
|
|
|
|
- Store `FLASKPASTE_PKI_CA_PASSWORD` securely (environment variable, secrets manager)
|
|
- CA private key is encrypted with AES-256-GCM using the password
|
|
- Use strong `FLASKPASTE_PROXY_SECRET` for header trust validation
|
|
- Revoke compromised certificates promptly via the API
|
|
- Monitor audit logs for `AUTH_FAILURE` events (revoked/expired certificates)
|
|
|
|
## API Reference
|
|
|
|
See [api.md](api.md) for detailed PKI endpoint documentation:
|
|
- `GET /pki` - PKI status
|
|
- `POST /pki/ca` - Generate CA
|
|
- `GET /pki/ca.crt` - Download CA certificate
|
|
- `POST /pki/issue` - Issue client certificate
|
|
- `GET /pki/certs` - List issued certificates
|
|
- `POST /pki/revoke/{serial}` - Revoke certificate
|
|
- `GET /register/challenge` - Get registration PoW challenge
|
|
- `POST /register` - Register for certificate
|