All Products
Search
Document Center

Alibaba Cloud Service Mesh:Use an ASM security policy to access an external OPA engine

Last Updated:Mar 11, 2026

When you need fine-grained access control for services in your mesh, Open Policy Agent (OPA) lets you define custom Rego policies that evaluate each request. By default, Service Mesh (ASM) deploys OPA as a sidecar inside each application pod, but you can also run OPA as a standalone service (centralized mode) to reduce resource overhead and avoid pod restarts. This guide walks through deploying a centralized OPA engine and connecting it to an ASM security policy.

Sidecar mode vs. centralized mode

In sidecar mode, ASM injects an OPA container into each application pod. The Istio proxy communicates with OPA within the same pod, keeping latency low. This makes sidecar mode a good fit for latency-sensitive services. However, it has trade-offs:

  • Higher resource usage: Every pod runs its own OPA container.

  • Pod restarts required: Injecting OPA requires restarting the application pod.

  • Less flexible routing: All requests to the pod are subject to OPA evaluation.

Centralized mode addresses these limitations by deploying OPA as a standalone service:

  • Lower resource footprint: A single OPA instance serves multiple workloads.

  • No pod restarts: Deploy or update OPA without disrupting application pods.

  • Selective enforcement: Apply OPA policies to specific request paths only.

OPA deployment modes

Prerequisites

Before you begin, make sure that you have:

Step 1: Deploy OPA

  1. Create a file named asm-opa.yaml with the following content. This manifest creates three resources:

    Note

    The username is extracted from the Authorization header in the format Authorization: Basic <Base64-encoded username:password>.

    Note

    Replace the region ID cn-hangzhou in the image path with the region where your cluster is deployed.

    ResourceDescription
    ServiceExposes OPA on port 9191 (gRPC) and port 8181 (HTTP).
    DeploymentRuns the OPA container with the Envoy external authorization gRPC plugin enabled. Decision logging is turned on by default (--set=decision_logs.console=true) to help with debugging.
    SecretStores a Rego policy that allows requests matching any of these conditions: the path is health, the HTTP method is HEAD, or the username is alice.

    View the content of asm-opa.yaml

       apiVersion: v1
       kind: Service
       metadata:
         name: asm-opa
         labels:
           app: opa
       spec:
         ports:
           - name: grpc
             port: 9191
             targetPort: 9191
             protocol: TCP
           - name: http
             port: 8181
             targetPort: 8181
             protocol: TCP
         selector:
           app: opa
       ---
       kind: Deployment
       apiVersion: apps/v1
       metadata:
         name: opa
         labels:
           app: opa
       spec:
         replicas: 1
         selector:
           matchLabels:
             app: opa
         template:
           metadata:
             labels:
               app: opa
             annotations:
               sidecar.istio.io/inject: "false"
           spec:
             containers:
               - name: opa
                 image: registry-vpc.cn-hangzhou.aliyuncs.com/acs/opa:0.46.1-istio-3-static
                 securityContext:
                   runAsUser: 1111
                 volumeMounts:
                   - readOnly: true
                     mountPath: /policy
                     name: opa-policy
                 args:
                   - "run"
                   - "--server"
                   - "--addr=0.0.0.0:8181"
                   - "--diagnostic-addr=0.0.0.0:8282"
                   - "--set=plugins.envoy_ext_authz_grpc.addr=:9191"
                   - "--set=plugins.envoy_ext_authz_grpc.path=asm/authz/allow"
                   - "--set=decision_logs.console=true"
                   - "--ignore=.*"
                   - "/policy/policy.rego"
                 ports:
                   - containerPort: 9191
                     protocol: TCP
                 resources:
                   limits:
                     cpu: "0"
                     memory: "0"
             volumes:
               - name: opa-policy
                 secret:
                   secretName: opa-policy
       ---
       apiVersion: v1
       kind: Secret
       metadata:
         name: opa-policy
       type: Opaque
       stringData:
         policy.rego: |
           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 == "alice"
           }
    
           user_name := parsed if {
             [_, encoded] := split(http_request.headers.authorization, " ")
             [parsed, _] := split(base64url.decode(encoded), ":")
           }
  2. Connect to your Container Service for Kubernetes (ACK) cluster and deploy OPA:

       kubectl apply -f asm-opa.yaml

Step 2: Associate an ASM security policy with OPA

  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 your ASM instance. In the left-side navigation pane, choose Mesh Security Center > ASMSecurityPolicy.

  3. Click Create. In the Create ASMSecurityPolicy dialog box, select the Custom Authorization Service card and click OK.

  4. Configure the custom authorization service: After the security policy is created, the console displays the policy details:

    1. On the CreateCustom Authorization Service page, enter the OPA service details from Step 1, then click Next. Create custom authorization service

    2. In the Workload and Match Rules step, click Add Workload Group. In the New Workload Group dialog box, set a Workload Group Name and click Add Workload.

    3. In the Add Workload dialog box, select Workload Scope, set Namespace to default and Workload Type to Service. Select httpbin in the Select workloads section, click the add icon icon, and click OK. Add workload

    4. In the Match Rule List section of the New Workload Group dialog box, set Match Mode to The selected request must be authenticated and Matching Rules to Custom Matching Rules. Turn on the Path switch, enter /status/*, and click OK. New workload group

    5. In the Workload and Match Rules step, click submit.

    ASM security policy created

Step 3: Verify access control

Replace <IP-address-of-ASM-gateway> in the following commands with the actual IP address of your ASM ingress gateway.

  1. Send a request to the root path / (no authentication required): Expected output: The 200 OK status confirms that the root path does not require authentication because the OPA policy match rule targets only /status/*.

       curl <IP-address-of-ASM-gateway>/ -I -X GET
       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: 2
  2. Send a request to /status/201 without credentials: Expected output: The 403 Forbidden status confirms that unauthenticated requests to /status/* are rejected.

       curl <IP-address-of-ASM-gateway>/status/201 -I -X GET
       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: 1
  3. Send a request to /status/201 with valid credentials: Expected output: The 201 Created status confirms that the request from user alice is allowed by the OPA policy.

       curl <IP-address-of-ASM-gateway>/status/201 -I -X GET --user alice:testpassword
       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: 3

Step 4: Update the OPA policy at runtime

Use the OPA HTTP API to update policies without redeploying. The following example changes the allowed user from alice to bob.

  1. Push the updated policy through the OPA REST API:

       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), ":")
       }'
  2. Verify that user bob is now allowed: Expected output:

       curl <IP-address-of-ASM-gateway>/status/201 -I -X GET --user bob:testpassword
       HTTP/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: 3
  3. Verify that user alice is now denied: Expected output: The 403 Forbidden status confirms that user alice is no longer authorized after the policy update.

       curl <IP-address-of-ASM-gateway>/status/201 -I -X GET --user alice:testpassword
       HTTP/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