All Products
Search
Document Center

Alibaba Cloud Service Mesh:Run an ASM authorization policy in trial mode

Last Updated:Mar 11, 2026

A misconfigured authorization policy can silently break production traffic -- blocking legitimate requests or allowing unauthorized access. Trial mode lets you validate an authorization policy against live traffic without enforcing it. Confirm the policy behaves as expected before it starts rejecting requests.

How trial mode works

When you enable trial mode on an authorization policy, Service Mesh (ASM) evaluates every request against the policy and logs the decision, but does not allow or deny traffic based on the result. This lets you:

  • Verify that the policy matches the intended requests.

  • Identify false positives (legitimate requests that would be denied) or false negatives (unauthorized requests that would be allowed).

  • Fine-tune policy rules before enforcement.

After the logs confirm correct behavior, disable trial mode to start enforcement.

We recommend enabling trial mode for every new authorization policy before enforcing it in production. Deploying a policy directly without validation can deny legitimate traffic or allow unauthorized access, with no warning until users report issues.

Prerequisites

Before you begin, make sure that you have:

Step 1: Deploy sample applications and verify connectivity

This walkthrough uses two applications -- sleep (a curl client) and httpbin (an HTTP echo server) -- to demonstrate trial mode end to end.

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

    sleep.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
      namespace: foo
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      namespace: foo
      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
  2. Connect to your cluster with kubectl and deploy the sleep application in the foo namespace. For connection instructions, see Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.

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

    httpbin.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
      namespace: foo
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      namespace: foo
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
      namespace: foo
    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
  4. Deploy the httpbin application in the foo namespace:

    kubectl apply -f httpbin.yaml -n foo
  5. Send 20 requests from the sleep pod to httpbin to confirm connectivity:

    for i in {1..20}; do kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl http://httpbin.foo:8000/headers -s -o /dev/null -w "%{http_code}\n"; done

    Expected output:

    200
    200
    200
    ...

    Every request returns 200, confirming that the sleep pod can reach httpbin over the mesh.

Step 2: Create an authorization policy with trial mode enabled

  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 > AuthorizationPolicy. Click Create.

  3. Configure the authorization policy to deny the target requests, enable trial mode (the Commissioning mode toggle), and click Create.

    Create an authorization policy with trial mode enabled

Step 3: Verify trial mode results

With trial mode enabled, the authorization policy logs its decisions without blocking traffic. Verify results through proxy logs.

Check proxy logs

  1. Send the same 20 requests from the sleep pod to httpbin:

    for i in {1..20}; do kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl http://httpbin.foo:8000/headers -s -o /dev/null -w "%{http_code}\n"; done

    Expected output:

    200
    200
    200
    ...

    All requests still return 200 because the policy is in trial mode -- it evaluates each request but does not enforce the deny action.

  2. Set the RBAC log level of the httpbin sidecar proxy to debug to surface trial mode decisions:

    kubectl exec "$(kubectl get pod -l app=httpbin -n foo -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo -- curl -X POST 127.0.0.1:15000/logging?rbac=debug

    Verify that the output includes rbac: debug:

    active loggers:
      ...
      rbac: debug
      ...
  3. Filter the sidecar proxy logs for shadow denied entries -- requests that *would* have been denied if the policy were enforced:

    kubectl logs "$(kubectl -n foo -l app=httpbin get pods -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo | grep "shadow denied"

    Example output:

    2023-12-20T03:58:47.107915Z  debug  envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:130  shadow denied, matched policy ns[foo]-policy[test]-rule[0]  thread=32
    2023-12-20T03:58:48.800098Z  debug  envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:130  shadow denied, matched policy ns[foo]-policy[test]-rule[0]  thread=33
    2023-12-20T03:58:50.420179Z  debug  envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:130  shadow denied, matched policy ns[foo]-policy[test]-rule[0]  thread=32

    Each shadow denied log entry confirms that the authorization policy matched the request and would have denied it. Review these entries to make sure the policy targets only the intended traffic.

We recommend keeping trial mode enabled for an extended period to test the policy against a representative sample of production traffic before enforcing it.

Step 4: Disable trial mode to enforce the policy

After the logs confirm that the authorization policy matches only the intended requests, disable trial mode to start enforcement.

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

  3. Find the authorization policy created in Step 2. Turn off the switch in the Commissioning mode column, then click OK in the Submit dialog.

  4. Send 20 requests again to verify that the policy now rejects traffic:

    for i in {1..20}; do kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl http://httpbin.foo:8000/headers -s -o /dev/null -w "%{http_code}\n"; done

    Expected output:

    403
    403
    403
    ...

    Every request now returns 403, confirming that the authorization policy is active.

  5. Restore the sidecar proxy RBAC log level to warning:

    kubectl exec "$(kubectl get pod -l app=httpbin -n foo -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo -- curl -X POST 127.0.0.1:15000/logging?rbac=warning

    Verify that the output includes rbac: warning:

    active loggers:
      ...
      rbac: warning
      ...

See also