Files
flaskpaste/documentation/pki.md
Username 14c8d0d83d
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
docs: update test count and fix pki.md inaccuracies
- 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)
2025-12-25 19:24:17 +01:00

4.7 KiB

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

# 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

# Create paste (now authenticated)
echo "secret data" | ./fpaste create

# List your pastes
./fpaste list

# Delete a paste
./fpaste delete <id>

Server Setup

Enable PKI

# 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:

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

./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

# Save and configure
./fpaste pki download -o ~/.config/fpaste/ca.crt --configure

# Or just view
./fpaste pki download

Issue Certificate (Admin)

# 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:

# 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:

./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

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

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 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