Skip to content

PATTERN Cited by 1 source

Ingress-layer authorization offload

Problem

Application services repeatedly re-implement authorization in application code: JWT parsing, scope / role / permission checks, audit logging, metric emission. Every team does it slightly differently. Every team now owns authorization runbooks, bugs, and migrations. Authorization-related incidents become per-app, not centrally manageable.

Solution

Move the authorization enforcement point into the ingress / edge proxy. Every incoming request passes through the proxy; the proxy evaluates policy against the request payload and returns allow / deny / custom response before the request reaches the app. Application services become authorization-free on the incoming direction — they accept what the proxy passed through.

Shape

  • The ingress proxy exposes an authorization filter (e.g., an opaAuthorizeRequest Skipper filter, an ext-authz Envoy filter, a Kong plugin, an AWS API Gateway Lambda authorizer).
  • Routes are annotated / configured to invoke the filter with a policy / bundle identifier.
  • The proxy hosts (or calls) the policy engine; the developer contract is the annotation, nothing else.
  • Observability (decision count, latency, decision IDs for audit) is emitted by the proxy, not by the app.

Developer-facing contract

A single Ingress / route annotation:

metadata:
  annotations:
    zalando.org/skipper-filter: |
      opaAuthorizeRequest("my-application")

That is the entire opt-in. The app team does not:

  • Deploy a sidecar.
  • Configure a bundle fetcher.
  • Wire authorization metrics.
  • Implement allow/deny in application code.

The app team does need to:

  • Maintain a Rego policy bundle named after the application ID.
  • Keep the policy bundle valid (CI lint / publish pipeline).

Why this shape works

  • One authorization implementation, not N. Every team gets the same engine, same observability, same blast-radius envelope.
  • Zero app-code entanglement. Apps never import an authz SDK, never version-skew with its upgrades.
  • Centralised migration surface. Upgrading the engine, adding a capability (decision streaming, attribute-based), rolling out a new bundle format — all done at the platform layer.
  • Audit trail is uniform. Every decision is emitted from the same place; decision IDs are platform-generated.

Trade-offs

  • Authorization logic that depends on application state is hard at ingress. If "may this user modify this document?" requires looking up document-ownership in the app's database, the ingress can't answer. Solutions: pass data into the policy via data.json, fetch via OPA's external-data capabilities, or split authz into a coarse ingress layer + a fine app-data-dependent layer.
  • Centralised enforcement point = centralised blast radius. A bad policy rollout affects every app using the filter. Mitigate with canary / staged bundle rollout.
  • Platform team now owns an always-on critical path. The SLO obligation is permanent.

Seen in

Last updated · 550 distilled / 1,221 read