When an ingress gateway receives external traffic, fine-grained access control often requires more than simple allow/deny rules. Open Policy Agent (OPA) lets you write custom authorization policies in Rego and enforce them at the gateway level -- without modifying application code.
This topic covers deploying an OPA engine alongside a Service Mesh (ASM) ingress gateway, connecting them through Envoy's external authorization mechanism, and testing the setup with the HTTPBin application.
How it works
The ASM ingress gateway uses Envoy as its data plane proxy. Envoy supports an external authorization filter (ext_authz) that delegates authorization decisions to an external service.
When OPA is integrated as the external authorization service:
A request arrives at the ingress gateway.
Envoy sends the request metadata (method, path, headers) to the OPA engine over gRPC.
OPA evaluates the request against the loaded Rego policy.
OPA returns an allow or deny decision. Envoy either forwards the request upstream or returns
403 Forbidden.
Because OPA runs as a separate pod within the cluster, policy evaluation is local -- no external network hop is required. Policies can be updated at runtime through the OPA HTTP API without redeploying any workloads.
Prerequisites
Before you begin, make sure that you have:
An ASM instance (v1.15.3.25 or later) with a Kubernetes managed cluster added. For more information, see Add a cluster to an ASM instance and Update an ASM instance
The HTTPBin application deployed and accessible through the ingress gateway. For more information, see Deploy the HTTPBin application
Automatic sidecar proxy injection enabled for the
defaultnamespace. For more information, see Configure sidecar proxy injection policies
Step 1: Deploy an OPA engine
Create a file named asm-opa.yaml with the following content. This manifest defines three Kubernetes resources:
| Resource | Purpose |
|---|---|
| Service | Exposes the OPA engine on port 9191 (gRPC) and port 8181 (HTTP) |
| Deployment | Runs the OPA container with the Envoy external authorization gRPC plugin enabled |
| Secret | Stores the default Rego policy that OPA loads at startup |
Replace the region ID cn-hangzhou in the container image path with the region where your cluster is deployed. For example, if your cluster is in the China (Shanghai) region, use registry-vpc.cn-shanghai.aliyuncs.com/acs/opa:0.46.1-istio-3-static.
Key configuration fields
The Deployment args configure how the OPA engine operates:
| Field | Value | Description |
|---|---|---|
--addr | 0.0.0.0:8181 | HTTP API listening address for policy management and health checks. |
--diagnostic-addr | 0.0.0.0:8282 | Diagnostic endpoint for readiness and liveness probes. |
plugins.envoy_ext_authz_grpc.addr | :9191 | gRPC listening address for the Envoy external authorization plugin. Must match the Service port. |
plugins.envoy_ext_authz_grpc.path | asm/authz/allow | The Rego policy decision path. OPA evaluates data.asm.authz.allow for each request. |
decision_logs.console | true | Prints decision logs to stdout for debugging. |
Default policy rules
The Rego policy in the Secret defines three authorization rules. A request is allowed if any rule evaluates to true:
| Rule | Condition | Example |
|---|---|---|
| Health check bypass | Request path starts with health | GET /health |
| HEAD method bypass | HTTP method is HEAD | HEAD /any-path |
| User authorization | Username in the Authorization header is alice | Authorization: Basic YWxpY2U6dGVzdHBhc3N3b3Jk (alice:testpassword, Base64-encoded) |
All other requests are denied (default allow := false).
Deploy
Run the following command to deploy OPA to the Container Service for Kubernetes (ACK) cluster:
kubectl apply -f asm-opa.yamlStep 2: Configure the ingress gateway to use OPA
Connect the OPA engine to the ingress gateway as a custom authorization service through the ASM console.
Log on to the ASM console. In the left-side navigation pane, choose .
On the Mesh Management page, click the name of the target ASM instance. In the left-side navigation pane, choose .
On the Ingress Gateway page, click Gateway security next to the ingress gateway that you want to configure.
In the left-side navigation pane, choose .
In the Custom Authorization Service Configuration step, configure the OPA engine as the custom authorization service for the ingress gateway, and then click Next.

In the Matching Rules step, specify which requests require OPA authorization, and then click Submit.

After the configuration is saved, the custom authorization service appears on the page:

Step 3: Verify OPA authorization
Test the three authorization rules by sending requests to the HTTPBin application through the ingress gateway.
Replace <gateway-ip> in the following commands with the IP address of your ASM ingress gateway.
Test 1: Access a path not covered by matching rules
Send a GET request to the root path (/). If the matching rules configured in Step 2 do not cover this path, the request bypasses OPA and reaches the upstream service directly.
curl <gateway-ip>/ -I -X GETExpected output:
HTTP/1.1 200 OK
server: istio-envoy
date: Tue, 25 Jul 2023 08:30:58 GMT
content-type: text/html; charset=utf-8
content-length: 9593
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 2A 200 OK response confirms that requests to this path are not intercepted by OPA.
Test 2: Access a protected path without credentials
Send a GET request to /status/201 without an Authorization header:
curl <gateway-ip>/status/201 -I -X GETExpected output:
HTTP/1.1 403 Forbidden
date: Tue, 25 Jul 2023 08:31:18 GMT
server: istio-envoy
content-length: 0
x-envoy-upstream-service-time: 1A 403 Forbidden response confirms that OPA denies requests that do not match any allow rule.
Test 3: Access a protected path with valid credentials
Send a GET request to /status/201 with the authorized username alice:
curl <gateway-ip>/status/201 -I -X GET --user alice:testpasswordExpected output:
HTTP/1.1 201 Created
server: istio-envoy
date: Tue, 25 Jul 2023 08:31:38 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 3A 201 Created response confirms that OPA authorizes requests from the user alice.
Step 4: Update the OPA policy at runtime
OPA exposes an HTTP API for policy management. Use this API to update policies without redeploying the OPA pod.
The following example changes the authorized user from alice to bob:
kubectl exec deployment/httpbin -c istio-proxy -- curl asm-opa:8181/v1/policies/policy/policy.rego -XPUT --data-binary 'package asm.authz
import future.keywords
import input.attributes.request.http as http_request
import input.parsed_path
default allow := false
allow if {
parsed_path[0] == "health"
}
allow if {
http_request.method == "HEAD"
}
allow if {
user_name == "bob"
}
user_name := parsed if {
[_, encoded] := split(http_request.headers.authorization, " ")
[parsed, _] := split(base64url.decode(encoded), ":")
}'This command runs curl from the istio-proxy container of the httpbin pod because the OPA service (asm-opa:8181) is accessible only within the cluster. The HTTP PUT method replaces the existing policy at the specified path.
Verify the updated policy
Send a request as
bob. Expect a201 Createdresponse: Expected output:curl <gateway-ip>/status/201 -I -X GET --user bob:testpasswordHTTP/1.1 201 Created server: istio-envoy date: Tue, 25 Jul 2023 08:32:16 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 3Send a request as
alice. Expect a403 Forbiddenresponse: Expected output:curl <gateway-ip>/status/201 -I -X GET --user alice:testpasswordHTTP/1.1 403 Forbidden date: Tue, 25 Jul 2023 08:32:49 GMT server: istio-envoy content-length: 0 x-envoy-upstream-service-time: 1
These results confirm that the updated policy takes effect immediately: bob is authorized while alice is now denied.