All Products
Search
Document Center

Alibaba Cloud Service Mesh:Connect an external OPA by using an ASM security policy

Last Updated:Aug 27, 2026

Service Mesh (ASM) simplifies one-stop configuration of common security scenarios by providing the ASM security policy feature, which abstracts Istio native security resources. ASM integrates the Open Policy Agent (OPA) plug-in, so you can define access control policies and apply fine-grained access control to your applications.

How it works

By default, ASM deploys OPA in sidecar mode. This tutorial uses a centralized OPA authorization service instead, which you deploy in your cluster and then connect to your application through an ASM security policy.

  • Sidecar mode (default) — After you enable OPA and restart the application Pod, ASM injects an OPA container into the Pod. The OPA sidecar then validates all requests from the application container. Sidecar mode keeps all access inside the Pod, which delivers lower latency and suits latency-sensitive workloads. The trade-offs are resource consumption, a Pod restart for each application, and limited flexibility.

  • Centralized mode (used in this tutorial) — A centralized OPA complements sidecar mode in these aspects: it consumes fewer resources, connects applications without a restart, and lets you decide which requests to the application are evaluated against OPA policies.

    OPA deployment modes

Prerequisites

Step 1: Deploy OPA

Deploy a centralized OPA authorization service in the cluster that you added to your ASM instance.

  1. Create the asm-opa.yaml file with the following content. The YAML file deploys an OPA Service, an OPA Deployment, and a Secret.

    Replace cn-hangzhou in the image registry-vpc.cn-hangzhou.aliyuncs.com/acs/opa:0.46.1-istio-3-static with the region of your cluster before you deploy the file.

    The OPA engine in the Deployment enables logging by default (--set=decision_logs.console=true) to simplify debugging.

    The Secret defines the OPA policy, which allows a request in any of the following cases:

    • The request path is health.

    • The request method is HEAD.

    • The username is alice.

      Note

      The username comes from the Authorization header of the request, in the format Authorization: Basic ${Base64 encoding of the username:password string}.

    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), ":")
        }
    Note

    The resources.limits values in this example are placeholders. Set cpu and memory to values that suit your environment.

  2. Use the kubeconfig file of the Container Service for Kubernetes (ACK) cluster to run the following command to deploy OPA.

    kubectl apply -f asm-opa.yaml
  3. Confirm that the OPA authorization service is available before you continue. The opa Deployment must be ready, and the asm-opa Service must expose port 9191 for gRPC and port 8181 for HTTP.

Step 2: Connect to OPA by using an ASM security policy

Create an ASM security policy that sends selected requests to the OPA authorization service for authorization.

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

  3. On the ASMSecurityPolicy page, click Create. In the Create ASMSecurityPolicy dialog box, click the Custom Authorization Service card, and then click OK.

  4. Configure the Custom Authorization Service:

    1. On the Create Custom Authorization Service page, configure the information of the OPA authorization service that you deployed in Step 1.

      Set the parameters as follows: set ASM Security Policy Name to opa, select GRPC for Protocol, enter asm-opa.default.svc.cluster.local for Service Address, enter 9191 for Service Port, and enter 10 seconds for Timeout. Then, click Next.

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

    3. In the Add Workload dialog box, select Workload Scope, set Namespaces to default, and set Workload Type to Service. In the Select workloads area, select httpbin, click the Add to selected workloads icon, and then click OK.

    4. In the New Workload Group dialog box, go to the Match Rule List area. Set Match Mode to The selected request must be authenticated, set Matching Rules to Custom Matching Rules, turn on the Path switch and set it to /status/*, and then click OK.

      This workload group is named httpbin, and its workload list contains the Sidecar-type httpbin Service with the app:httpbin label.

    5. In the Workload and Match Rules wizard, click Submit.

      After you submit the configuration, the page displays The ASM security policy is created and shows the Istio resources that are created. The resource names are grpcextauth-asmsecuritypolicy-opa for ASMExtensionProvider and opa-ap-wg-httpbin-default-service-httpbin for AuthorizationPolicy. You can click View YAML to view the resource details, and then click Done.

Step 3: Test httpbin access

In the following commands, ${ASM_GATEWAY_IP} is the IP address of the ASM ingress gateway that exposes httpbin. Each command uses -I to return only the response headers and -X GET to force the GET method, because the OPA policy allows every HEAD request. These tests exercise the username rule of the OPA policy.

  1. Run the following command to access the / path.

    curl ${ASM_GATEWAY_IP}/ -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
    200 OK response shows that the request is allowed. The / path does not match the /status/* matching rule that you configured in Step 2, so the request is not sent to OPA for authorization.

  2. Run the following command to access the /status/201 path without valid credentials.

    curl ${ASM_GATEWAY_IP}/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
    403 Forbidden response indicates that the request is denied because it carries no valid credentials.

  3. Run the following command to access the /status/201 path with valid credentials.

    curl ${ASM_GATEWAY_IP}/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
    201 Created response confirms that the request is allowed because it carries valid credentials for the alice user. If this request also returns 403 Forbidden, review the OPA deployment in Step 1 and the ASM security policy configuration in Step 2.

Step 4: Update the OPA policy and retest access

Call the HTTP API of the OPA engine to update the OPA policy at runtime. The opa-policy Secret that you created in Step 1 is not modified and still contains the original policy.

  1. Run the following command to update the policy so that only the bob user is allowed to access the application and the previous alice user is denied.

    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. Run the following command to access httpbin as the bob user.

    curl ${ASM_GATEWAY_IP}/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
    201 Created response shows that the bob user accesses the application successfully under the updated policy.

  3. Run the following command to access httpbin as the alice user.

    curl ${ASM_GATEWAY_IP}/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
    403 Forbidden response shows that access from the alice user is denied.