When services in a mesh communicate, you often need authorization logic that goes beyond simple allow/deny rules -- checking custom headers, validating tokens, or enforcing business-specific policies. Alibaba Cloud Service Mesh (ASM) supports custom authorization through the Envoy ext_authz filter, which lets you deploy an external gRPC service that evaluates every request before it reaches your workloads.
This tutorial walks through deploying a sample gRPC authorization service, registering it in ASM, creating an authorization policy, and verifying that only authorized requests pass through.
How it works
When a request arrives at a service protected by custom authorization:
The sidecar proxy intercepts the request and sends an authorization check to the external authorization service over gRPC.
The authorization service evaluates request attributes (headers, path, body) against its policy logic.
If the authorization service approves the request, the proxy forwards it to the target service. Otherwise, the proxy rejects the request immediately.
This architecture decouples authorization logic from application code, enabling consistent access control across all services in the mesh.
Prerequisites
Before you begin, ensure that you have:
An ASM instance with a Container Service for Kubernetes (ACK) cluster added. For more information, see Add a cluster to an ASM instance
kubectl configured to connect to the ACK cluster. For more information, see Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster
Deploy a custom authorization service
Deploy an external authorization service in the ACK cluster. The service must comply with Istio's API specifications for custom authorization and support both HTTP and gRPC protocols.
The sample authorization service only approves requests that contain the x-ext-authz: allow header. To build your own authorization logic, see the source code on GitHub.
Create a file named ext-authz.yaml with the following content:
The manifest creates a Deployment running the
istio/ext-authz:0.6image and a Service that exposes HTTP on port 8000 and gRPC on port 9000.Deploy the service:
kubectl apply -f ext-authz.yamlExpected output:
service/ext-authz created deployment.apps/ext-authz createdVerify that the authorization service started successfully:
kubectl logs "$(kubectl get pod -l app=ext-authz -n default -o jsonpath={.items..metadata.name})" -n default -c ext-authzExpected output:
2023/12/20 08:15:39 Starting gRPC server at [::]:9000 2023/12/20 08:15:39 Starting HTTP server at [::]:8000Both the gRPC and HTTP servers should be running.
Note the gRPC port of the ext-authz service (9000 in this example). To confirm in the console:
Log on to the ACK console. In the left-side navigation pane, click Clusters.
On the Clusters page, find the cluster and click its name. In the left-side pane, choose Network > Services.
On the Services page, click ext-authz. The Endpoint section displays the gRPC port.
Deploy sample applications
Deploy the httpbin and sleep applications. httpbin serves as the target service that requires authorization. sleep acts as a client that sends test requests.
Create a file named httpbin.yaml with the following content:
Deploy the httpbin application:
kubectl apply -f httpbin.yamlCreate a file named sleep.yaml with the following content:
Deploy the sleep application:
kubectl apply -f sleep.yaml
Register the authorization service in ASM
Register the ext-authz service in your ASM instance so the mesh can route authorization requests to it over gRPC.
Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Mesh Security Center > Custom Authorization Service. 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 parameters as described in the following table, and then click Create.
Required parameters
Parameter Description Example value Protocol The protocol used by the authorization service. GRPC Name A name for the authorization service registration. testService Address The service endpoint in the format <Service name>.<Namespace>.svc.<Cluster domain>.ext-authz.default.svc.cluster.localPort(1 - 65535) The gRPC port of the authorization service. 9000Timeout(second) Maximum seconds to wait for an authorization response. If the service does not respond within this period, the service is considered unavailable. 10Optional parameters
Parameter Description Skip authentication while authorization service is unavailable When enabled, requests are allowed through if the authorization service is unreachable. When disabled, requests are denied. Error code returned by asm proxy while Auth-Service is not available The HTTP error code returned to callers when the authorization service is unavailable. Available only when Skip authentication while authorization service is unavailable is turned off. Carry origin request body within auth request When enabled, the request body is included in authorization requests sent to the authorization service. Specify a maximum body length. If Allow send incomplete message to Auth-Service is also enabled, bodies exceeding the maximum length are truncated before forwarding.
Create an authorization policy
Define which requests require authorization by creating an authorization policy that routes matching requests through the ext-authz service.
Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Mesh Security Center > AuthorizationPolicy. Click Create.
On the Create page, configure the parameters as described in the following table, and then click Create.
Parameter Description Example value Name A name for the authorization policy. test1Policy Type The type of policy. Select Custom Authorization Service to use the ext-authz service registered in the previous step. Custom Authorization Service Custom Authorization Service The registered authorization service. grpcextauth-test(GRPC) Namespace The namespace where the policy applies. Set on the Workload Scope tab. defaultEffective Scope Whether the policy applies to a specific service or the entire namespace. Service Workload The workload to protect. httpbinRequest Matching Rules The request paths that trigger authorization. In the Add Request Target section, turn on Paths and specify the path. /headersWith this configuration, only requests to the
/headerspath of the httpbin service are sent to the authorization service for evaluation. Requests to other paths bypass authorization.
Verify the authorization setup
Run three tests to confirm that the authorization policy works as expected.
Test 1: Request to a path without authorization
Send a request to /ip, which is not covered by the authorization policy:
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 output: 200
The request succeeds because the /ip path does not match the authorization policy.
Test 2: Request denied by the authorization service
Send a request to /headers with the header x-ext-authz: deny:
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" -sExpected output:
denied by ext_authz for not found header `x-ext-authz: allow` in the requestThe authorization service rejects the request because the required x-ext-authz: allow header is missing.
Test 3: Request approved by the authorization service
Send a request to /headers with the header x-ext-authz: allow:
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 output:
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.default:8000",
"User-Agent": "curl/8.5.0",
"X-Envoy-Attempt-Count": "1",
"X-Ext-Authz": "allow",
"X-Ext-Authz-Check-Result": "allowed",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=c3e5364e87add0f4f69e6b0d029f5961b404c8f209bf9004b3d21a82cf67****;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep"
}
}The X-Ext-Authz-Check-Result: allowed header confirms that the authorization service approved the request. The response also includes the SPIFFE identity of both the client (sleep) and the server (httpbin), verifying mutual TLS between services.
These three tests confirm:
Requests to unprotected paths pass through without authorization checks.
Requests to protected paths without the required header are denied.
Requests to protected paths with the correct header are approved.
Production considerations
When deploying custom authorization in a production environment, keep the following in mind:
| Area | Recommendation |
|---|---|
| Failure mode | Decide whether to allow or deny requests when the authorization service is unavailable. Allowing requests (fail-open) maintains availability but reduces security. Denying requests (fail-closed) is more secure but can cause outages if the authorization service goes down. |
| Timeout | Set the timeout value based on your authorization service's response latency. A value that is too low causes false denials; a value that is too high increases request latency. |
| High availability | Run multiple replicas of the authorization service and configure appropriate resource requests and limits. |
| Scope | Apply authorization policies to specific paths and workloads rather than entire namespaces to minimize performance overhead. |
| Monitoring | Monitor authorization service logs and latency to detect issues before they affect traffic. |
Clean up
Remove the resources created in this tutorial:
kubectl delete -f ext-authz.yaml
kubectl delete -f httpbin.yaml
kubectl delete -f sleep.yamlDelete the authorization policy and custom authorization service registration from the ASM console:
In the ASM console, choose Mesh Security Center > AuthorizationPolicy. Delete the
test1policy.Choose Mesh Security Center > Custom Authorization Service. Delete the
testauthorization service.