Policies

WAFPolicy, rule sets and how Inkwall validates them before they are saved.

The operator validates these objects today. Enforcing them on the engines, through signed policy bundles, is being built. The API is waf.inkwall.dev/v1alpha1 and will change.

WAFPolicy

A WAFPolicy protects routes in its namespace:

apiVersion: waf.inkwall.dev/v1alpha1
kind: WAFPolicy
metadata:
  name: demo
  namespace: inkwall-demo
spec:
  targetRefs:
  - kind: Ingress
    name: demo
  mode: Block               # Detect (the default) logs; Block rejects
  timeout: 250ms            # inspection deadline per request, at most 1s
  skip:
    paths: ["/health"]      # never inspected
  ruleSets:
  - ref: {kind: ClusterWAFRuleSet, name: owasp-crs-v4}
    paranoiaLevel: 1
    inboundAnomalyThreshold: 5
  - ref: {kind: WAFRuleSet, name: shop-custom}
  exclusions:               # turn a rule off where it causes false positives
  - ruleIDs: [942100]
    when: {path: "/search", argument: q}
  body:
    maxBytes: 65536
FieldWhat it does
targetRefsThe routes to protect: Ingress objects. The API also accepts a Gateway API HTTPRoute, but the operator doesn’t resolve those yet and reports TargetUnsupported
modeDetect (log, let through) or Block (reject)
failureModeWhat happens when a request can’t be inspected in time: Closed (503) or Open. Unset: closed in block mode, open in detect mode
timeoutInspection deadline per request, more than 0 and at most 1s
skip.paths, skip.bodyPathsPaths never inspected, or whose body isn’t; exact (/healthz) or prefix (/static/*)
ruleSetsThe rules to run, in order; with no entry, the Core Rule Set with its defaults
exclusionsRule IDs to turn off, everywhere or for a path, an argument or both
bodyWhether bodies are inspected, how much of them, and what happens to larger ones

Rule sets

A ClusterWAFRuleSet can be used from any namespace, a WAFRuleSet from its own. The rules come from exactly one source:

apiVersion: waf.inkwall.dev/v1alpha1
kind: WAFRuleSet
metadata:
  name: shop-custom
  namespace: inkwall-demo
spec:
  source:
    seclang: |
      SecRule REQUEST_HEADERS:User-Agent "@contains sqlmap" "id:100001,phase:1,deny,status:403"
    # or: builtin: crs-v4
    # or: configMapRef: {name: my-rules, key: rules.conf}

Validation before saving

Mistakes are caught when you save, not when traffic arrives:

  • The CRD schema rejects malformed objects: unknown modes, timeouts over 1s, relative or encoded paths, a target listed twice.
  • The operator’s webhook compiles rule sets with the engine’s own Coraza version, loaded after the Core Rule Set as the engine loads them, and names the line of the first error:
$ kubectl apply -f bad-rules.yaml
The WAFRuleSet "bad" is invalid: spec.source.seclang: Invalid value: line 2:
failed to compile the directive "secrule": operator nosuchop not found

Rule sets may only use directives that add, remove or change rules (SecRule, SecAction, SecMarker, SecRuleRemoveBy*, SecRuleUpdate*). Settings that change the whole engine, such as SecRuleEngine, or that write files, such as SecAuditLog, are rejected: rule sets are written by application teams, and those settings belong to the platform.

Status

Each policy will report how far it got, as conditions that work with kubectl wait and Argo CD: Accepted (valid, references resolve), Programmed (the proxy sends traffic to Inkwall), Enforced (every engine runs it) and Ready (all three).

Edit this page on GitHub