Skip to content

feat: admin dashboard for key & upload status#20

Open
ServerSideHannes wants to merge 5 commits intomainfrom
feat/admin-dashboard
Open

feat: admin dashboard for key & upload status#20
ServerSideHannes wants to merge 5 commits intomainfrom
feat/admin-dashboard

Conversation

@ServerSideHannes
Copy link
Owner

Summary

  • Adds a lightweight web dashboard at /admin for monitoring encryption key status, active multipart uploads, memory/concurrency health, and request statistics
  • Disabled by default (S3PROXY_ADMIN_UI=true to enable), protected by HTTP Basic Auth (uses AWS credentials or custom S3PROXY_ADMIN_USERNAME/S3PROXY_ADMIN_PASSWORD)
  • Server-rendered HTML with dark theme, auto-refresh every 10s via fetch(), zero new dependencies

Details

New files:

  • s3proxy/admin/ package: auth, collectors, router, templates
  • tests/unit/test_admin.py: 22 tests covering auth, HTML, JSON API, route priority, collectors, security (no key leakage)

Modified files:

  • s3proxy/config.py: 4 new settings (admin_ui, admin_path, admin_username, admin_password)
  • s3proxy/app.py: Split route registration to mount admin before catch-all; pass through non-S3 exceptions with custom headers
  • s3proxy/state/storage.py: Added list_keys() to StateStore, MemoryStateStore, RedisStateStore
  • s3proxy/state/manager.py: Added list_active_uploads() (safe summaries, no DEKs exposed)
  • pyproject.toml: E501 ignore for HTML template file

Security

  • KEK fingerprint is sha256(kek)[:16] — one-way hash, safe to display
  • DEKs, raw encryption keys, and AWS secret keys are never exposed
  • Tests explicitly verify no sensitive data appears in HTML or JSON responses

Test plan

  • 22 new unit tests pass (auth, HTML, JSON API, route priority, collectors, key safety)
  • Full unit test suite passes (323 tests, 0 regressions)
  • Lint clean (ruff check + ruff format)

Closes #19

Lightweight web UI served at /admin (disabled by default, enable with
S3PROXY_ADMIN_UI=true) showing KEK fingerprint, active multipart uploads,
memory/concurrency health, and request statistics. Server-rendered HTML
with auto-refresh via fetch() every 10s, protected by HTTP Basic Auth.

Closes #19
@ServerSideHannes ServerSideHannes self-assigned this Feb 13, 2026
Port-forward s3proxy admin dashboard automatically when the e2e cluster
starts, so operators can go straight to http://localhost:4433/admin/
without running a separate command.
Replace static implementation details with actionable operator metrics:
- Pod identity banner (pod name, uptime, KEK fingerprint, storage backend)
- Per-minute rates via sliding window RateTracker (requests, encrypt, decrypt, errors)
- Multi-pod grid cards via Redis metrics publishing (30s TTL per pod)
- Error rate breakdown (4xx/5xx/503 per minute with visual indicators)
- Stale upload detection (>30 min warning markers)
- X-Served-By response header for pod identification
- 3-second auto-refresh with spinner animation
…tory

- RateTracker window extended to 10 min with new history() method
- Canvas sparklines under each throughput card (requests, encrypt, decrypt)
- Full-width bandwidth section with encrypt/decrypt byte rate sparklines
- Retina-aware canvas rendering with devicePixelRatio support
- Green (#3fb950) for encrypt, blue (#58a6ff) for decrypt
- Add RequestLog ring buffer recording every S3 proxy request
- Hook into request_handler.py finally block (method, path, op, status, latency, size)
- Live Feed table: scrolling last 50 requests with color-coded methods, statuses,
  latency warnings, and ENC/DEC crypto badges
- Replace verbose pod cards with compact inline badges in header
- Remove redundant Bandwidth and Active Uploads sections
- Switch from green-on-dark to white-on-dark (#f0f6fc on #0f1117) modern style
- New row fade-in animation for realtime feel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web dashboard for key & upload status

1 participant