This guide walks you through the first validation from an empty state to a verifiable, countersigned WAF++ PASS certificate.

There is no user account to create. Access to the validation service is managed through API tokens, which will soon be available for purchase on the Shop page.


What you need

Before you start, make sure you have:

  1. A WAF++ PASS run produced by the wafpass CLI (wafpass check --output json).
  2. A wafpass-server instance that can receive the run and attest it with its own Ed25519 key.
  3. An API token to authenticate submissions to the gateway. (Purchase flow coming soon — the Shop will be enabled shortly.)

The gateway itself never sees your private keys. It only verifies public keys, certificates, and signatures.


The validation process

┌─────────────────────────────────────────────────────────────────────────────┐
│  1. Run WAF++ checks locally                                                │
│     wafpass check ./infra --output json                                     │
│                              │                                              │
│                              ▼                                              │
│  2. Sign the run locally with your organisation Ed25519 key                 │
│     → local attestation (public key + signature)                            │
│                              │                                              │
│                              ▼                                              │
│  3. Send the run to your wafpass-server                                     │
│     Server verifies the local attestation                                   │
│     Server signs the canonical run hash with its Ed25519 key                │
│                              │                                              │
│                              ▼                                              │
│  4. Server submits to the WAF++ validation gateway                         │
│     Gateway verifies the server sub-CA certificate                          │
│     Gateway verifies both attestations                                      │
│     Gateway countersigns the validation                                     │
│                              │                                              │
│                              ▼                                              │
│  5. You receive a validation ID, badge, and permanent verify URL           │
└─────────────────────────────────────────────────────────────────────────────┘

Verify a server certificate from the browser

If you already have a gateway-issued server certificate, you can verify it independently of any backend:

  1. Open the Server Cert page.
  2. Paste the PEM content of server.crt into the form.
  3. Click Verify certificate.

The page calls the public, unauthenticated endpoint POST /api/v1/validations/server/verify and shows:

Field Meaning
valid Cryptographically signed by the gateway root CA and still within its validity window.
registered The gateway database knows this server certificate.
revoked Whether the certificate has been revoked by an administrator.
fingerprint_sha256 SHA-256 fingerprint of the certificate for audit logs.

The same endpoint can be used from CI or the command line:

curl -X POST https://waf.lew-app.de/api/v1/validations/server/verify \
  -H "Content-Type: application/json" \
  -d '{"server_certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n"}'

Step 1 — Obtain an API token

API tokens are not tied to a user account. Each token is a prepaid credit bundle that lets a wafpass-server submit validation runs to the gateway.

Coming soon: the Shop page will let you buy tokens directly. Until then, contact the gateway operator to receive an initial token.

A token looks like this:

wafpass_abcdefghijklmnopqrstuvwxyz0123456789ABCD

Keep it secret. It is shown only once when created.


Step 2 — Register your wafpass-server

Your server needs a sub-CA certificate issued by the gateway. A gateway administrator creates it in the Admin UI:

  1. Log in to the admin UI.
  2. Open the Server Certificates panel.
  3. Enter a unique server_id and paste the server’s Ed25519 public key or certificate.
  4. Click Issue certificate.

The gateway returns a PEM certificate chain. Store the certificate on the server as server.crt. The matching private key (server.key) never leaves the server.


Step 3 — Run the WAF++ checks

From your local development or CI environment:

wafpass check ./infra \
  --output json \
  --project my-project \
  --branch main

This produces a run JSON file containing every control check and its status.


Step 4 — Sign locally

Your organisation key signs the canonical hash of the run JSON. This proves that the run came from your environment and has not been modified since.

from hashlib import sha256
import canonicaljson

canonical_hash = sha256(canonicaljson.dumps(run).encode("utf-8")).hexdigest()
signature = ed25519_sign(canonical_hash, org_private_key)

The server receives the run, the public key, and the signature as the local attestation bundle.


Step 5 — Server attestation and submission

The wafpass-server:

  1. Verifies the local attestation against the run JSON.
  2. Signs the canonical hash with its own Ed25519 attestation key.
  3. POSTs the bundle to the gateway:
curl -X POST https://waf.lew-app.de/api/v1/validations \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: wafpass_..." \
  -d @submit-payload.json

The request body contains:

Field What it is
server_certificate The gateway-issued sub-CA certificate for this server.
local_attestation The organisation’s public key, signature, and optional certificate.
run The canonical WAF++ PASS run JSON.

See the full edge-to-edge example for a complete, copy-pasteable payload.


Step 6 — Receive the official validation

On success the gateway returns 201 Created:

{
  "validation_id": "waf-ex-12345678-1234-1234-1234-123456789abc",
  "status": "official",
  "canonical_hash": "7184231525be8173ccb7eb0b5fc804630e37c49c2ec3c511b3c47b8d875a54a6",
  "server_signature": "...",
  "gateway_signature": "...",
  "certificate_chain": ["-----BEGIN CERTIFICATE-----\n..."],
  "badge_url": "https://waf.lew-app.de/api/v1/validations/waf-ex-12345678-.../badge.svg",
  "verify_url": "https://waf.lew-app.de/api/v1/validations/waf-ex-12345678-.../verify",
  "certificate_url": "https://waf.lew-app.de/api/v1/validations/waf-ex-12345678-.../certificate.pdf"
}

Share the verify_url or embed the badge_url in documentation, pull requests, or compliance reports. Anyone can verify it without trusting your server.


Step 7 — Verify publicly

Anyone can check the current status:

curl https://waf.lew-app.de/api/v1/validations/waf-ex-12345678-1234-1234-1234-123456789abc/verify

The gateway walks the certificate chain, checks the signatures, and reports valid or revoked.


Next steps