Repository navigation
v0.2.0
OpenWAF Egress 0.2.0 adds a multi-tenant mode: the gateway can take its agents, targets and policies from
OpenWAF Cloud instead of config.json and report every refused request back. The
static config.json mode is unchanged.
OpenWAF Cloud data-plane mode
-control-plane <url> -node-id <id> -node-key <file>(orOPENWAF_CONTROL_PLANE,OPENWAF_NODE_ID,
OPENWAF_NODE_KEY;-poll-interval, 15 s by default).egress keygen -out node.keywrites a new ed25519
PKCS#8 key (mode 0600, never overwrites) and prints the public key the operator registers.- Every request to the control plane is signed with the node's own key (
openwaf-node-request/v1: timestamp,
single-use nonce, body hash). The configuration is polled withsince_serial(304 when unchanged). The last
good document stays in force while the control plane is unreachable, for at most-max-stale
(OPENWAF_MAX_STALE, 10 min by default); a 401/403 from the control plane (node revoked) withdraws it at once,
and an older serial is never applied. Without a valid document requests get503 policy_unavailableand
/healthanswers503 {"status":"starting"}(no tenant totals are published in this mode). Redirects from the
control plane are never followed. - Agents are identified by the SHA-256 of their token (constant-time comparison) and must call
/v1/agent/<their name>/proxy/<target>/…;X-OpenWAF-Agentis ignored and the caller'sAuthorizationis
never forwarded. - Provider keys: the gateway derives the KV v2 path itself (
<kv_mount>/data/tenants/<org>/egress/<target>,
keyapi_key); a path never comes from the document. A target without a stored key is refused
(502 credential_resolution_failed) instead of being called without one. - Block events (
injection_detected,data_leak_blocked,ssrf_blocked,egress_blocked,
body_too_large) of identified agents go to the control plane in batches of up to 1000, retried with the same
batch_id, from a bounded queue. They carry the detector ids or DLP match types, method, path without query and
caller address; never the request body. Method and path are normalized, and an event the control plane would
refuse is dropped alone, so one bad event never costs a batch. Protocol:
docs/control-plane.md.
Other changes
-
SSRF: the address actually dialed is checked too (DNS rebinding between the lookup and the connection gets
403 ssrf_blocked;::is refused like0.0.0.0), and neitherssrf_blockednor502 upstream_erroranswers
carry addresses or connection errors any more (they are logged on the gateway). -
token_sha256in an agent ofconfig.jsoninstead oftoken(the plain token is then not on disk); tokens
are compared in constant time. -
-trusted-proxies(OPENWAF_TRUSTED_PROXIES): behind a reverse proxy, itsX-Real-IPis the caller address of
block events. -
Go API:
Resolver(per-request policy lookup),EventSink/WithEventSink,WithTrustedProxies,
NewServerWithResolver, and thepkg/controlplaneclient. -
CI scans the whole history for secrets (gitleaks) before testing and publishing.
Install
docker pull ghcr.io/openwaf-dev/egress:0.2.0 # linux/amd64, linux/arm64
egress -versionApache-2.0. Vulnerabilities: security@openwaf.dev.