Files
flaskpaste/README.md

226 lines
6.5 KiB
Markdown

# FlaskPaste
A lightweight, secure pastebin REST API built with Flask.
## Features
- **Simple REST API** - Create, retrieve, and delete pastes via HTTP
- **Binary support** - Upload text, images, archives, and other binary content
- **Automatic MIME detection** - Magic byte detection for common formats (PNG, JPEG, GIF, WebP, ZIP, PDF, GZIP)
- **Client certificate authentication** - Optional auth via `X-SSL-Client-SHA1` header
- **Automatic expiry** - Pastes expire after configurable period of inactivity
- **Size limits** - Configurable limits for anonymous and authenticated users
- **Abuse prevention** - Content-hash deduplication throttles repeated identical submissions
- **Proof-of-work** - Configurable computational puzzle prevents automated spam
- **Security headers** - HSTS, CSP, X-Frame-Options, Cache-Control, and more
- **CLI client** - Standalone `fpaste` command-line tool included
- **Request tracing** - X-Request-ID support for log correlation
- **Proxy trust validation** - Optional shared secret for defense-in-depth
- **Minimal dependencies** - Flask only, SQLite built-in
## Quick Start
```bash
# Clone and setup
git clone <repository>
cd flaskpaste
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Run development server
python run.py
```
## API Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET /` | API information and usage |
| `GET /health` | Health check (returns DB status) |
| `GET /challenge` | Get proof-of-work challenge |
| `POST /` | Create a new paste |
| `GET /<id>` | Retrieve paste metadata |
| `HEAD /<id>` | Retrieve paste metadata (headers only) |
| `GET /<id>/raw` | Retrieve raw paste content |
| `HEAD /<id>/raw` | Retrieve paste headers (no body) |
| `DELETE /<id>` | Delete paste (requires auth) |
## Usage Examples
### Create a paste (raw text)
```bash
curl --data-binary @file.txt http://localhost:5000/
```
### Create a paste (piped input)
```bash
echo "Hello, World!" | curl --data-binary @- http://localhost:5000/
```
### Create a paste (JSON)
```bash
curl -H "Content-Type: application/json" \
-d '{"content":"Hello from JSON!"}' \
http://localhost:5000/
```
### Retrieve paste metadata
```bash
curl http://localhost:5000/abc12345
```
### Retrieve raw content
```bash
curl http://localhost:5000/abc12345/raw
```
### Delete a paste (requires authentication)
```bash
curl -X DELETE \
-H "X-SSL-Client-SHA1: <your-cert-fingerprint>" \
http://localhost:5000/abc12345
```
## CLI Client
A standalone command-line client `fpaste` is included (no external dependencies).
### Basic Usage
```bash
# Create paste from file
./fpaste create file.txt
# Create paste from stdin
echo "Hello" | ./fpaste
# Get paste content
./fpaste get abc12345
# Get paste metadata
./fpaste get -m abc12345
# Delete paste (requires auth)
./fpaste delete abc12345
# Show server info
./fpaste info
```
### Configuration
Set server URL and authentication via environment or config file:
```bash
# Environment variables
export FLASKPASTE_SERVER="https://paste.example.com"
export FLASKPASTE_CERT_SHA1="your-cert-fingerprint"
# Or config file (~/.config/fpaste/config)
server = https://paste.example.com
cert_sha1 = your-cert-fingerprint
```
## Configuration
Configuration via environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `FLASK_ENV` | `development` | Environment (`development`, `production`, `testing`) |
| `FLASKPASTE_DB` | `./data/pastes.db` | SQLite database path |
| `FLASKPASTE_ID_LENGTH` | `12` | Paste ID length (hex characters) |
| `FLASKPASTE_MAX_ANON` | `3145728` (3 MiB) | Max paste size for anonymous users |
| `FLASKPASTE_MAX_AUTH` | `52428800` (50 MiB) | Max paste size for authenticated users |
| `FLASKPASTE_EXPIRY` | `432000` (5 days) | Paste expiry in seconds |
| `FLASKPASTE_DEDUP_WINDOW` | `3600` (1 hour) | Dedup throttle window in seconds |
| `FLASKPASTE_DEDUP_MAX` | `3` | Max identical submissions per window |
| `FLASKPASTE_PROXY_SECRET` | (empty) | Shared secret for proxy trust validation |
| `FLASKPASTE_POW_DIFFICULTY` | `20` | PoW difficulty (leading zero bits, 0=disabled) |
| `FLASKPASTE_POW_TTL` | `300` (5 min) | PoW challenge validity period |
| `FLASKPASTE_POW_SECRET` | (auto) | Secret for signing PoW challenges |
## Authentication
FlaskPaste uses client certificate authentication. When deployed behind a reverse proxy (nginx, Apache), configure the proxy to:
1. Terminate TLS and validate client certificates
2. Extract the certificate SHA1 fingerprint
3. Pass it via the `X-SSL-Client-SHA1` header
Example nginx configuration:
```nginx
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header X-SSL-Client-SHA1 $ssl_client_fingerprint;
}
```
Authenticated users can:
- Upload larger pastes (50 MiB vs 3 MiB)
- Delete their own pastes
## Production Deployment
### Using Gunicorn
```bash
pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:5000 wsgi:app
```
### Using Podman/Docker
```bash
podman build -t flaskpaste .
podman run -d -p 5000:5000 -v flaskpaste-data:/app/data flaskpaste
```
See `Containerfile` for container build configuration.
## Development
### Running Tests
```bash
pip install pytest pytest-cov
pytest tests/ -v
```
### Test Coverage
```bash
pytest tests/ --cov=app --cov-report=term-missing
```
### Project Structure
```
flaskpaste/
├── app/
│ ├── __init__.py # Flask app factory
│ ├── config.py # Configuration classes
│ ├── database.py # SQLite management
│ └── api/
│ ├── __init__.py # Blueprint setup
│ └── routes.py # API endpoints
├── tests/ # Test suite
├── data/ # SQLite database
├── run.py # Development server
├── wsgi.py # Production WSGI entry
├── Containerfile # Podman/Docker build
└── requirements.txt # Dependencies
```
## Security Considerations
- **Input validation** - Paste IDs are hex-only, auth headers validated
- **MIME sanitization** - Content-Type headers are sanitized
- **SQL injection protection** - Parameterized queries throughout
- **Ownership enforcement** - Only owners can delete their pastes
- **Size limits** - Prevents resource exhaustion attacks
- **Abuse prevention** - Content-hash deduplication prevents spam flooding
- **Security headers** - HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Cache-Control
- **Request tracing** - X-Request-ID for log correlation and debugging
- **Proxy trust** - Optional `X-Proxy-Secret` validation to prevent header spoofing
## License
MIT