Skip to main content

WAF++ PASS – API server for persisting and querying scan results

Project description

wafpass-server

REST API for persisting and querying WAF++ PASS scan results. Part of the WAF++ framework monorepo.

Component Role
pass/ · wafpass-core Compliance engine, CLI, IaC parsers ← produces results
wafpass-server/ · this package FastAPI + PostgreSQL · stores results, exposes APIs
wafpass-dashboard/ · React SPA Consumes this API · visualises compliance posture

Quick start

Docker Compose (recommended)

From the repo root:

cp .env.example .env        # fill in passwords
docker compose up --build
  • API: http://localhost:8000
  • Swagger UI: http://localhost:8000/api/docs
  • Dashboard: http://localhost:3000

Local development

# Prerequisites: PostgreSQL running locally
pip install -e ".[dev]"

# Copy and edit the environment file
cp .env.example .env
# Edit .env — at minimum set DATABASE_URL to point at your local PostgreSQL instance

# Export variables into your shell (or use direnv)
export $(grep -v '^#' .env | xargs)

# Apply database migrations
alembic upgrade head

# Start server with auto-reload
uvicorn wafpass_server.main:app --reload --port 8000

Environment variables

Copy .env.example to .env for local development — it contains all variables with documented defaults.

Variable Default Description
DATABASE_URL PostgreSQL async DSN, e.g. postgresql+asyncpg://user:pass@host:5432/db
WAFPASS_ENV local Environment tag (local, staging, production)
CORS_ORIGINS http://localhost:3000 Comma-separated allowed CORS origins
WAFPASS_CONTROLS_DIR controls Path to WAF++ control YAML files (used by Sandbox endpoint)

Local dev tip: When running the dashboard dev server alongside the API, add http://localhost:5173 to CORS_ORIGINS so Vite's dev server can reach the API without CORS errors.


API reference

Health

Method Path Description
GET /health Liveness check → {"status": "ok"}

Runs

Ingest and retrieve compliance scan results produced by wafpass check --output json.

Method Path Description
POST /runs Ingest a wafpass-result.json payload
GET /runs List runs (limit, offset, project)
GET /runs/{id} Full run with findings, controls metadata, secret findings
GET /runs/{id}/controls Controls metadata for a run
GET /runs/{id}/findings Filtered findings (severity, pillar, status)

Push a result from CI:

wafpass check ./infra --output json | \
  curl -s -X POST http://localhost:8000/runs \
       -H "Content-Type: application/json" \
       -d @-

Set metadata before posting:

import json, httpx

result = json.loads(open("wafpass-result.json").read())
result.update({"project": "my-infra", "branch": "main", "git_sha": "abc1234"})
httpx.post("http://localhost:8000/runs", json=result)

Controls catalogue

Browse and manage WAF++ controls independently of scan runs.

Method Path Description
POST /controls Upsert a control (returns {data, meta} envelope)
GET /controls List controls (pillar, severity, page, per_page)
GET /controls/{id} Get a single control
DELETE /controls/{id} Delete a control

Waivers

Team-shared waiver records. Suppresses a control from failing in the dashboard, shared across all team members.

Method Path Description
GET /waivers List waivers (project filter — returns global + project-specific)
PUT /waivers/{id} Upsert a waiver (idempotent — create or update by control ID)
DELETE /waivers/{id} Delete a waiver
{
  "reason": "Covered by external quarterly IAM review — SEC-1234",
  "owner": "platform-team",
  "expires": "2026-09-30",
  "project": ""
}

Risk acceptances

Formally accepted residual risks with approver sign-off, RFC, and traceability links.

Method Path Description
GET /risks List risk acceptances
PUT /risks/{id} Upsert a risk acceptance
DELETE /risks/{id} Delete a risk acceptance
{
  "reason": "Legacy system — migration planned Q3 2026",
  "approver": "Jane Smith",
  "owner": "platform-team",
  "rfc": "RFC-0042",
  "jira_link": "https://jira.example.com/browse/SEC-100",
  "risk_level": "high",
  "residual_risk": "medium",
  "expires": "2026-09-30",
  "accepted_at": "2026-01-15T09:00:00Z",
  "project": ""
}

Architect Sandbox

Run the real WAF++ engine against arbitrary HCL snippets in-process. Requires wafpass-core and a populated WAFPASS_CONTROLS_DIR.

Method Path Description
POST /sandbox Evaluate HCL against all loaded controls
GET /sandbox/status Check engine availability
# Check if engine is ready
curl http://localhost:8000/sandbox/status

# Run HCL snippet
curl -X POST http://localhost:8000/sandbox \
  -H "Content-Type: application/json" \
  -d '{"hcl": "resource \"aws_s3_bucket\" \"b\" {}", "iac": "terraform"}'

Without wafpass-core, the server starts normally and all other endpoints remain available. Sandbox returns 503 with a descriptive message.


Database migrations

Migrations use Alembic.

alembic upgrade head                           # apply all migrations
alembic downgrade -1                           # roll back one step
alembic revision --autogenerate -m "my change" # generate migration after editing models.py
alembic current                                # show applied revision

Migration history:

Revision Change
0001_create_runs Initial runs table
0002_add_run_metadata path, controls_loaded, controls_run, regions, source_paths
0003_add_controls_meta controls_meta JSONB
0004_add_plan_changes plan_changes JSONB
0005_add_controls controls catalogue table
0006_add_secret_findings secret_findings JSONB
0007_add_waivers_risks waivers and risk_acceptances tables

Docker

The build context is the monorepo root because the Dockerfile copies pass/ first to install wafpass-core:

# From repo root
docker build -t wafpass-server -f wafpass-server/Dockerfile .

docker run \
  -e DATABASE_URL=postgresql+asyncpg://wafpass:wafpass@host.docker.internal/wafpass \
  -e CORS_ORIGINS=http://localhost:3000 \
  -e WAFPASS_CONTROLS_DIR=/app/controls \
  -p 8000:8000 \
  wafpass-server

The entrypoint (entrypoint.sh) runs alembic upgrade head automatically before starting uvicorn — no manual migration step needed in production.

Custom controls directory:

# docker-compose.yml — wafpass-server service
volumes:
  - ./my-controls:/app/controls:ro
environment:
  WAFPASS_CONTROLS_DIR: /app/controls

Interactive docs

URL Description
http://localhost:8000/api/docs Swagger UI — try requests in browser
http://localhost:8000/api/redoc ReDoc — read-only reference

Development

pip install -e ".[dev]"
pytest

See TECH.md for architecture details, database schema, and contribution guidance.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wafpass_server-0.4.2.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wafpass_server-0.4.2-py3-none-any.whl (20.7 kB view details)

Uploaded Python 3

File details

Details for the file wafpass_server-0.4.2.tar.gz.

File metadata

  • Download URL: wafpass_server-0.4.2.tar.gz
  • Upload date:
  • Size: 24.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wafpass_server-0.4.2.tar.gz
Algorithm Hash digest
SHA256 3dd5adefd818bee0ede672be35d170ef1cc37d7e9adc54fc04631546609fd109
MD5 594333f9ac2b67d5c526b4d88e3cc290
BLAKE2b-256 5b8d311add4d24300ca8cc0ae3fafd124a598ce35451a7f304cd2d9fc78e8249

See more details on using hashes here.

Provenance

The following attestation bundles were made for wafpass_server-0.4.2.tar.gz:

Publisher: release.yml on WAF2p/wafpass-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wafpass_server-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: wafpass_server-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 20.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wafpass_server-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 dcd7539e81cd97c4ef12c12da3935596bfbe9cd487cdd0f612195d6d57e04b49
MD5 443671fa1ad70d73cecc9b4e5a0260f7
BLAKE2b-256 534b9bab2932da09a8ada7e970be3f932bc243b0e097ba9481a649c100b86b98

See more details on using hashes here.

Provenance

The following attestation bundles were made for wafpass_server-0.4.2-py3-none-any.whl:

Publisher: release.yml on WAF2p/wafpass-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page