Service Mesh (ASM) supports external authorization through the Envoy ext_authz filter. Instead of embedding authorization logic in each microservice, you delegate access decisions to a centralized external authorization service. This decouples authorization from application code and lets you enforce consistent access control across your mesh.
This tutorial walks through the full setup: deploy a sample external authorization service, register it with ASM, create an authorization policy, and verify the end-to-end behavior. The sample service approves only requests that include the x-ext-authz: allow header.
How it works
When a client sends a request to a protected service, the Envoy sidecar intercepts the request and forwards it to the external authorization service. The authorization service inspects request attributes -- headers, path, and method -- and returns an allow or deny decision. Envoy then either forwards the request to the upstream service or returns an error to the caller.
Client --> Envoy sidecar --> ext-authz service
| |
|<-- allow/deny -------+
|
allow --> upstream service
deny --> 403 Forbidden to callerBehavior details:
Authorization checks trigger only for requests that match the rules in the authorization policy. For example, you can limit checks to specific paths.
Requests that do not match any rule pass through without authorization checks.
If the external authorization service is unavailable, ASM denies all matching requests by default (fail-closed). You can configure fail-open behavior if needed.
Prerequisites
Before you begin, make sure that you have:
A Container Service for Kubernetes (ACK) cluster added to your ASM instance. For more information, see The cluster is added to the ASM instance.
kubectl connected to the ACK cluster. For more information, see Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster
Step 1: Deploy the external authorization service
Deploy the ext-authz service in the ACK cluster. This service complies with the Istio external authorization API specification and supports both HTTP and gRPC.
You can use the following sample service or build your own based on the source code on GitHub.
Create a file named
ext-authz.yamlwith the following content:Apply the manifest:
kubectl apply -f ext-authz.yamlVerify that the Pod is running: Expected output:
kubectl get pod -l app=ext-authzNAME READY STATUS RESTARTS AGE ext-authz-6b5db88f86-2m7c6 2/2 Running 0 79mConfirm that the authorization service started successfully: Expected output:
kubectl logs "$(kubectl get pod -l app=ext-authz -n default -o jsonpath={.items..metadata.name})" -n default -c ext-authz2023/12/20 08:15:39 Starting gRPC server at [::]:9000 2023/12/20 08:15:39 Starting HTTP server at [::]:8000Note the HTTP endpoint:
ext-authz.default.svc.cluster.local:8000. You need this value when registering the service with ASM in the next step. To confirm the port, go to the ACK console. Navigate to Clusters > *your cluster* > Network > Services, click ext-authz, and check the Endpoint section.
Step 2: Deploy sample applications
Deploy the httpbin and sleep applications to test authorization behavior.
Create a file named
httpbin.yamlwith the following content:Apply the manifest:
kubectl apply -f httpbin.yamlCreate a file named
sleep.yamlwith the following content:Apply the manifest:
kubectl apply -f sleep.yaml
Step 3: Register the authorization service with ASM
Register the ext-authz service so that ASM can route authorization checks to it.
Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.
Click the name of your ASM instance. In the left-side navigation pane, choose Mesh Security Center > Custom Authorization Service, then click Define Custom Authorization Service.
On the Register Custom Authorization Service page, click the Custom authorization service (HTTP or gRPC protocol) implemented based on envoy.ext_authz tab. Configure the following parameters and click Create.
Required parameters
| Parameter | Value for this tutorial | Description |
|---|---|---|
| Protocol | HTTP | The protocol used by the authorization service. |
| Name | test4http | A name to identify the authorization service in ASM. |
| Service Address | ext-authz.default.svc.cluster.local | The fully qualified domain name of the authorization service. Format: <Service name>.<Namespace>.svc.<Cluster domain>. |
| Port(1 - 65535) | 8000 | The HTTP port of the authorization service. |
| Timeout(second) | 10 | Maximum time in seconds for the authorization service to respond. Requests that exceed this timeout are treated as failures. |
Optional parameters
| Parameter | Description |
|---|---|
| Skip authentication while authorization service is unavailable | Controls fail-open or fail-closed behavior. When turned on, ASM allows requests if the authorization service is unreachable (fail-open). When turned off (default), ASM denies requests (fail-closed). Evaluate the security implications before enabling fail-open in production. |
| Error code returned by asm proxy while Auth-Service is not available | A custom HTTP error code to return when the authorization service is unavailable. Available only when Skip authentication while authorization service is unavailable is turned off. |
| Carry origin header within auth request | Forward specified client request headers to the authorization service. Specify one or more header keys. ASM includes matching headers from the client request in the authorization check. HTTP protocol only. |
| Add a header in the authentication request | Attach additional headers (key-value pairs) to the authorization request. If a header key already exists in the client request, ASM overwrites the original value. HTTP protocol only. |
| Overwrite Header when authentication passes | After a successful authorization check, overwrite specified headers in the client request with headers from the authorization response before forwarding to the upstream service. HTTP protocol only. |
| Overwrite Header when authentication fails | After a failed authorization check, overwrite specified headers in the response sent to the caller with headers from the authorization response. HTTP protocol only. |
| Carry origin request body within auth request | Include the client request body in the authorization request, up to a specified maximum length. If Allow send incomplete message to Auth-Service is also enabled, ASM truncates the body to the specified length. |
Configuration for this tutorial
Configure the following optional parameters for this tutorial. Leave all other optional parameters turned off.
Carry origin header within auth request: Turn on and add
x-ext-authz.NoteThe
x-ext-authzheader is forwarded to the authorization service so it can inspect the value and make an allow or deny decision.
Overwrite Header when authentication passes: Turn on and add
x-ext-authz-check-result.
Overwrite Header when authentication fails: Turn on and add
x-ext-authz-check-result.
Step 4: Create an authorization policy
Create an authorization policy that defines which requests require authorization checks.
In the ASM console, navigate to your ASM instance and choose Mesh Security Center > AuthorizationPolicy. Click Create.
Configure the following parameters and click Create.
Parameter Value for this tutorial Description Name test1A name to identify the authorization policy. Policy Type Custom Authorization Service Delegates authorization to the external authorization service registered in Step 3. Custom Authorization Service httpextauth-test4http(HTTP) The authorization service registered in Step 3. Namespace defaultOn the Workload Scope tab, select the namespace where the target workload runs. Effective Scope Service Apply the policy at the service level. Workload httpbinThe workload to protect with authorization checks. Request Matching Rules Paths: /headersUnder Add Request Target, turn on Paths and set the value to /headers. Only requests to this path trigger authorization.
Step 5: Verify the authorization behavior
Run three test cases from the sleep Pod to confirm that authorization works as expected.
Test 1: Request to a non-protected path
kubectl exec "$(kubectl get pod -l app=sleep -n default -o jsonpath={.items..metadata.name})" \
-c sleep -n default -- \
curl "http://httpbin.default:8000/ip" -s -o /dev/null -w "%{http_code}\n"Expected result: 200
The /ip path does not match the /headers rule in the authorization policy, so the request passes through without an authorization check.
Test 2: Request to a protected path with a deny header
kubectl exec "$(kubectl get pod -l app=sleep -n default -o jsonpath={.items..metadata.name})" \
-c sleep -n default -- \
curl "http://httpbin.default:8000/headers" -H "x-ext-authz: deny" -s -iExpected result: 403 Forbidden
HTTP/1.1 403 Forbidden
x-ext-authz-check-result: denied
...
denied by ext_authz for not found header `x-ext-authz: allow` in the requestThe /headers path matches the authorization policy, so the request is forwarded to the ext-authz service. Because the header value is deny instead of allow, authorization fails. The x-ext-authz-check-result: denied header confirms the denial, as configured in Step 3.
Test 3: Request to a protected path with an allow header
kubectl exec "$(kubectl get pod -l app=sleep -n default -o jsonpath={.items..metadata.name})" \
-c sleep -n default -- \
curl "http://httpbin.default:8000/headers" -H "x-ext-authz: allow" -sExpected result: 200 with a JSON response
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.default:8000",
"User-Agent": "curl/8.5.0",
"X-Ext-Authz": "allow",
"X-Ext-Authz-Check-Result": "allowed",
...
}
}The authorization check succeeds. The X-Ext-Authz-Check-Result: allowed header confirms that the ext-authz service approved the request.
Security and operational considerations
Fail-open vs. fail-closed: By default, ASM denies requests when the authorization service is unavailable (fail-closed). To switch to fail-open mode, enable Skip authentication while authorization service is unavailable in the authorization service configuration. Evaluate the security impact before enabling fail-open in production -- a fail-open configuration allows unauthenticated requests when the authorization service is down.
Filter ordering: Place authorization checks early in the request processing pipeline. If other filters (such as Lua filters) modify routing after the authorization check, requests could bypass authorization. For more information about this risk, see the Envoy ext_authz documentation.
Timeout tuning: Set the authorization timeout based on the expected latency of your authorization service. A timeout that is too short may cause false denials under load.
Clean up
Remove the resources created in this tutorial:
kubectl delete -f ext-authz.yaml
kubectl delete -f httpbin.yaml
kubectl delete -f sleep.yamlAlso delete the authorization service and policy from the ASM console:
Navigate to Mesh Security Center > AuthorizationPolicy, select the
test1policy, and delete it.Navigate to Mesh Security Center > Custom Authorization Service, select
test4http, and delete it.
What's next
Develop an HTTP-based custom authorization service: Build a production-grade authorization service tailored to your business logic.
Develop a gRPC-based custom authorization service: Use gRPC instead of HTTP for lower-latency authorization checks.
Implement custom authorization by using the gRPC protocol: Configure ASM to use a gRPC-based external authorization service.
Use an authorization policy to control access traffic from services in an ASM instance to an external website: Manage outbound traffic from services in your ASM instance to external websites.
Use an authorization policy to control access traffic from services in an ASM instance to an external database: Manage outbound traffic from services in your ASM instance to external databases.
Use the KubeAPI operation audit feature in ASM: Record and trace daily operations of different users in your ASM instance.
Configure audit alerts for ASM resource operations: Monitor and alert on changes to ASM configurations.