All Products
Search
Document Center

Alibaba Cloud Service Mesh:Implement custom authorization by using the gRPC protocol

Last Updated:Mar 10, 2026

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:

  1. The sidecar proxy intercepts the request and sends an authorization check to the external authorization service over gRPC.

  2. The authorization service evaluates request attributes (headers, path, body) against its policy logic.

  3. 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:

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.

Note

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.

  1. Create a file named ext-authz.yaml with the following content:

    ext-authz.yaml

    # Copyright Istio Authors
    #
    #   Licensed under the Apache License, Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing, software
    #   distributed under the License is distributed on an "AS IS" BASIS,
    #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.
    
    # Example configurations for deploying ext-authz server separately in the mesh.
    
    apiVersion: v1
    kind: Service
    metadata:
      name: ext-authz
      labels:
        app: ext-authz
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 8000
      - name: grpc
        port: 9000
        targetPort: 9000
      selector:
        app: ext-authz
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ext-authz
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: ext-authz
      template:
        metadata:
          labels:
            app: ext-authz
        spec:
          containers:
          - image: istio/ext-authz:0.6
            imagePullPolicy: IfNotPresent
            name: ext-authz
            ports:
            - containerPort: 8000
            - containerPort: 9000

    The manifest creates a Deployment running the istio/ext-authz:0.6 image and a Service that exposes HTTP on port 8000 and gRPC on port 9000.

  2. Deploy the service:

    kubectl apply -f ext-authz.yaml

    Expected output:

    service/ext-authz created
    deployment.apps/ext-authz created
  3. Verify 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-authz

    Expected output:

    2023/12/20 08:15:39 Starting gRPC server at [::]:9000
    2023/12/20 08:15:39 Starting HTTP server at [::]:8000

    Both the gRPC and HTTP servers should be running.

  4. Note the gRPC port of the ext-authz service (9000 in this example). To confirm in the console:

    1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

    2. On the Clusters page, find the cluster and click its name. In the left-side pane, choose Network > Services.

    3. 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.

  1. Create a file named httpbin.yaml with the following content:

    httpbin.yaml

    # Copyright Istio Authors
    #
    #   Licensed under the Apache License, Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing, software
    #   distributed under the License is distributed on an "AS IS" BASIS,
    #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.
    
    ##################################################################################################
    # httpbin service
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          serviceAccountName: httpbin
          containers:
          - image: docker.io/kennethreitz/httpbin
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
  2. Deploy the httpbin application:

    kubectl apply -f httpbin.yaml
  3. Create a file named sleep.yaml with the following content:

    sleep.yaml

    # Copyright Istio Authors
    #
    #   Licensed under the Apache License, Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing, software
    #   distributed under the License is distributed on an "AS IS" BASIS,
    #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.
    
    ##################################################################################################
    # Sleep service
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: curlimages/curl
            command: ["/bin/sleep", "3650d"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
  4. 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.

  1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. 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.

  3. 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

    ParameterDescriptionExample value
    ProtocolThe protocol used by the authorization service.GRPC
    NameA name for the authorization service registration.test
    Service AddressThe service endpoint in the format <Service name>.<Namespace>.svc.<Cluster domain>.ext-authz.default.svc.cluster.local
    Port(1 - 65535)The gRPC port of the authorization service.9000
    Timeout(second)Maximum seconds to wait for an authorization response. If the service does not respond within this period, the service is considered unavailable.10

    Optional parameters

    ParameterDescription
    Skip authentication while authorization service is unavailableWhen 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 availableThe 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 requestWhen 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.

  1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. 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.

  3. On the Create page, configure the parameters as described in the following table, and then click Create.

    ParameterDescriptionExample value
    NameA name for the authorization policy.test1
    Policy TypeThe type of policy. Select Custom Authorization Service to use the ext-authz service registered in the previous step.Custom Authorization Service
    Custom Authorization ServiceThe registered authorization service.grpcextauth-test(GRPC)
    NamespaceThe namespace where the policy applies. Set on the Workload Scope tab.default
    Effective ScopeWhether the policy applies to a specific service or the entire namespace.Service
    WorkloadThe workload to protect.httpbin
    Request Matching RulesThe request paths that trigger authorization. In the Add Request Target section, turn on Paths and specify the path./headers

    With this configuration, only requests to the /headers path 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" -s

Expected output:

denied by ext_authz for not found header `x-ext-authz: allow` in the request

The 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" -s

Expected 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:

AreaRecommendation
Failure modeDecide 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.
TimeoutSet 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 availabilityRun multiple replicas of the authorization service and configure appropriate resource requests and limits.
ScopeApply authorization policies to specific paths and workloads rather than entire namespaces to minimize performance overhead.
MonitoringMonitor 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.yaml

Delete the authorization policy and custom authorization service registration from the ASM console:

  1. In the ASM console, choose Mesh Security Center > AuthorizationPolicy. Delete the test1 policy.

  2. Choose Mesh Security Center > Custom Authorization Service. Delete the test authorization service.

See also