Envoy extension
Synapse implements the Envoy external authorization API natively and its behaviour can be configured either declratively or programmatically.
A typical Envoy configuration to use Synapse as the external authorization service is as follows.
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: AUTO
http_filters:
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
transport_api_version: V3
grpc_service:
envoy_grpc:
cluster_name: synapse
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
...
clusters:
- name: synapse
type: STATIC
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: synapse
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 3594
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: synapse.localhost
common_tls_context:
validation_context:
trust_chain_verification: ACCEPT_UNTRUSTED
Declarative mapping
Map Envoy Check requests to Cerbos CheckResources and back using CEL expressions.
extensions:
envoyExternalAuthz:
enabled: true (1)
mapping: (2)
request:
requestID: 'request.attributes.request.http.headers["x-request-id"]'
principal:
id: 'request.attributes.request.http.headers["x-user-id"]'
roles: '["user"]'
resource:
id: '"foo"'
kind: '"request"'
action: "request.attributes.request.http.method"
| 1 | Enable the Envoy Check endpoint on the server |
| 2 | Declarative mapping of request and response. See below for mapping reference. |
Mapping reference
Documentation about Cerbos request and response formats can be found at https://docs.cerbos.dev/cerbos/latest/api/#_request_and_response_formats. For Envoy Check request and response formats, refer to https://buf.build/envoyproxy/envoy/docs/main:envoy.service.auth.v3#envoy.service.auth.v3.CheckRequest.
|
-
request(required):-
requestID: a CEL expression returning a string. -
principal(required):-
id(required): a CEL expression returning a string. -
roles(required): a CEL expression returning a list of strings, or a list of CEL expressions each returning a string. -
attr: a CEL expression returning a map of strings to values, or a map of strings to CEL expressions each returning a value. -
policyVersion: a CEL expression returning a string. -
scope: a CEL expression returning a string.
-
-
resource(required):-
kind(required): a CEL expression returning a string. -
id(required): a CEL expression returning a string. -
attr: a CEL expression returning a map of strings to values, or a map of strings to CEL expressions each returning a value. -
policyVersion: a CEL expression returning a string. -
scope: a CEL expression returning a string.
-
-
action(required): a CEL expression returning a string. -
auxData:-
jwt: a single JWT. Mutually exclusive withjwts.-
token(required): a CEL expression returning a string. -
keySetID: a CEL expression returning a string.
-
-
jwts: a map of token names to JWTs, each with the sametokenandkeySetIDfields asjwt. Mutually exclusive withjwt.
-
-
-
response:-
status: a CEL expression returning an HTTP status code as an integer. Defaults to 200 when allowed and 403 when denied. -
headers: a CEL expression returning a map of strings to strings, or a map of strings to CEL expressions each returning a string. -
body: a CEL expression returning bytes or a string.
-
Use jwts to pass more than one token to the PDP. Policies read the claims of a named token as request.auxData.jwts.NAME.claims.CLAIM. Named JWTs require Cerbos PDP 0.55.0 or later. See Cerbos conditions for the expression syntax.
Request expressions have access to the incoming HTTP request in the CEL variable request, which has the following fields:
-
method: the request’s HTTP method as an uppercase string. -
header: map of HTTP request headers. Keys are header names in canonical form and values are strings (comma-separated when multiple headers with the same name are present in the request). -
headers: map of HTTP request headers. Keys are header names in canonical form and values are lists of strings. -
body: object with the following fields:-
bytes: the raw request body -
text: the request body as a string -
json: the JSON-decoded request body
-
Response expressions have access to the CheckResources result in the CEL variable check which has the following fields:
-
requestId,principal,resource, andaction: the inputs produced by the request expressions. -
cerbosCallId: the ID for audit logging as a string. -
allow: whether the action is allowed as a boolean. -
outputs: the output from the policy as a map of source (policy-id#rule-name) to value. -
validationErrors: errors encountered when validating the principal and resource against the corresponding schemas as a list ofcerbos.schema.v1.ValidationErrormessages.
Using the YAML scalar block syntax > for CEL expressions is recommended to avoid quoting issues. action: "view" would be interpreted as the CEL expression view (which would fail to compile because a variable named view is not defined), when the desired setting was the CEL expression "view" (which just returns the intended string literal).
extensions:
envoyExternalAuthz:
enabled: true
mapping:
request:
requestID: 'request.attributes.request.http.headers["x-request-id"]'
principal:
id: 'request.attributes.request.http.headers["x-user-id"]'
roles: '["user"]'
resource:
id: '"foo"'
kind: '"request"'
action: "request.attributes.request.http.method"
extensions:
envoyExternalAuthz:
enabled: true
mapping:
request:
requestID: 'request.attributes.request.http.headers["x-request-id"]'
principal:
id: 'request.attributes.request.http.headers["x-user-id"]'
roles: '["user"]'
resource:
id: '"foo"'
kind: '"request"'
action: "request.attributes.request.http.method"
response: >
check.allow ? {"status": {"code": google.rpc.Code.OK }} : {
"status": {"code": google.rpc.Code.OK },
"deniedResponse": {
"status": {"code": 401 },
"body": json.encode(check.outputs["resource.example.v1#route"].body)
}
}
extensions:
envoyExternalAuthz:
enabled: true
mapping:
request:
# ...
auxData:
jwts:
access: (1)
token: >
request.attributes.request.http.headers["authorization"].replace("Bearer ", "", 1)
id:
token: >
request.attributes.request.http.headers["x-id-token"]
| 1 | Token name. Policies read the claims of this token as request.auxData.jwts.access.claims. |
Programmatic mapping
extensions:
envoyExternalAuthz:
enabled: true (1)
extension:
extensionURL: /extensions/envoy.wasm (2)
configuration: (3)
environment: staging
| 1 | Enable the Envoy Check endpoint. |
| 2 | URL to fetch the extension from. See extension URL format for more information. |
| 3 | Configuration values needed by the extension. [Optional] |