Skip to main content
logoTetrate Service BridgeVersion: next

Gateway Authorization Rule Actions (ALLOW, DENY, AUDIT)

Gateway HTTP servers can carry local authorization rules under spec.http[].authorization.local.rules. Each rule decides whether a request may reach the backend, based on the caller's JWT claims, the request path and method, and other attributes of the request.

Every rule carries an action that says what happens when the rule matches: ALLOW, DENY or AUDIT. action defaults to ALLOW, so rules written before this field existed keep their previous behaviour.

note

Rule actions apply to local authorization rules on ingress, tier-1 and application gateway servers. Egress gateway authorization (spec.egressAuthorization) does not support rule actions.

Rule actions

ActionEffect when the rule matches
ALLOWThe request is permitted. ALLOW rules form an allow list: once a server has at least one ALLOW rule, any request that no ALLOW rule permits is refused. This is the default.
DENYThe request is refused, whatever the ALLOW rules say. Refusals are evaluated before the allow list.
AUDITThe request is recorded and the decision is left to the other rules. An AUDIT rule never permits or refuses anything, so naming a path in an audit rule does not make that path reachable.

A few consequences worth keeping in mind:

  • A server only becomes an allow list when it has an ALLOW rule of its own. A server whose rules are all AUDIT (or all DENY) keeps whatever access it would have had with no rules at all, so adding an audit rule never takes a server offline.
  • A rule that states none of from, to or when matches every request the server handles. That is how an AUDIT rule records a whole server, or a DENY rule closes one. An ALLOW rule must say what it permits.
  • DENY rules are evaluated before AUDIT rules, so a request that is refused by a DENY rule is still recorded by a matching AUDIT rule.

Matching conditions

Each rule matches on any combination of the following. All parts that are set must match.

FieldMatches
fromThe caller — for example a JWT iss, sub or claim.
to.paths / to.methodsThe request path and HTTP method. Paths support exact match, prefix match with a trailing * (/api*), suffix match with a leading * (*.js), and a single * for any path.
to.notPaths / to.notMethodsPaths and methods that must not match for the rule to apply. Same path matching as to.paths.
whenAn attribute of the request — see below.

A when condition has a key, naming the attribute, and values / notValues:

when:
- key: "request.auth.claims[group]" # holds when the claim is "eng" or "sre"
values: ["eng", "sre"]
- key: "request.headers[authorization]" # holds when the header is absent
notValues: ["*"]

Common keys include request.auth.claims[<name>], request.headers[<name>], connection.sni and source.ip. HTTP/2 pseudo-headers are addressable, so request.headers[:authority] and request.headers[:path] work; unlike to.paths, request.headers[:path] includes the query string. values uses the same exact / prefix / suffix / * matching as to.paths. A single * in values requires the attribute to be present; in notValues it requires the attribute to be absent.

when conditions are scoped to their server

Each rule is scoped to the server that declares it, by adding that server's host and port. A when condition can narrow a rule within its server but cannot widen it to other servers. This matters for conditions on request.headers[:authority] and destination.port: on a server with a specific hostname, a condition naming a different host never matches. On a server whose hostname is *, such a condition works as written.

Example

The following ingress gateway server permits engineering callers to /api, refuses contractors outright, and records every write that arrives without an Authorization header — without making those writes reachable.

apiVersion: gateway.tsb.tetrate.io/v2
kind: Gateway
metadata:
name: bookinfo-gw-ingress
group: bookinfo-gw
workspace: bookinfo-ws
tenant: tetrate
spec:
workloadSelector:
namespace: bookinfo
labels:
app: tsb-gateway-bookinfo
http:
- name: bookinfo
port: 8443
hostname: bookinfo.tetrate.com
tls:
mode: SIMPLE
secretName: bookinfo-certs
authentication:
jwt:
issuer: issuer1.example
audiences: ["tetrateapp"]
jwksUri: https://issuer1.example/.well-known/jwks.json
authorization:
local:
rules:
- name: eng-only # action defaults to ALLOW
from:
- jwt:
iss: issuer1.example
to:
- paths: ["/api*"]
when:
- key: "request.auth.claims[group]"
values: ["eng"]

- name: block-contractors
action: DENY
when:
- key: "request.auth.claims[employment]"
values: ["contractor"]

- name: audit-anonymous-writes
action: AUDIT
to:
- methods: ["POST", "PUT", "PATCH", "DELETE"]
notPaths: ["/health"]
when:
- key: "request.headers[authorization]"
notValues: ["*"]
routing:
rules:
- route:
serviceDestination:
host: 'bookinfo/productpage.bookinfo.svc.cluster.local'

Rule evaluation order

For a request that reaches the server, rules are evaluated in this order:

  1. DENY rules — if any matches, the request is refused.
  2. AUDIT rules — every matching rule records the request. No allow or deny decision is made here.
  3. ALLOW rules — if the server has any ALLOW rule, the request must match one of them or it is refused. If the server has no ALLOW rule, the request keeps the access it would have had with no rules.

Where AUDIT (and DENY) matches are recorded

An AUDIT rule takes no part in the allow/deny decision. Its only effect is to mark the request so that it is recorded.

For DENY and AUDIT rules, the gateway proxy reports the rule's name as the effective authorization policy ID. That name appears in the proxy's access log record for the request, so the record shows which rule matched. Give an AUDIT rule a name that describes what it watches (for example audit-anonymous-writes above), because that name is what you will search for in the logs.

Those access-log records are emitted by the gateway's Envoy proxy alongside its normal request access logs, and are forwarded to the TSB telemetry store where access logging to it is enabled.

note

Records for requests that a DENY rule refused are already surfaced as access denials. Distinct handling of AUDIT records for requests that were permitted is still being completed on the telemetry backend; until then, the marker and rule name are present in the raw access log record but are not yet a dedicated queryable field.

Rule name uniqueness

Rule names must be unique within a server. For DENY and AUDIT rules they must also be unique across servers that share a filter chain, among rules with the same action. Plaintext servers on the same port share a filter chain, because Istio serves them from one listener.