Service Mesh (ASM) allows you to conduct trial runs for an authorization policy to ensure that the effect of the authorization policy meets expectations. This topic describes how to run an ASM authorization policy in trial mode and shows the effect of this trial mode.

Prerequisites

Background information

ASM allows you to configure authorization policies to implement access control for all workloads or only specific workloads in a namespace. Authorization policies control access traffic. If they are not configured properly, access requests may be allowed or denied unexpectedly. In this case, ASM administrators face great challenges. For example, some normal access requests are denied, whereas the access requests that should be denied are allowed. To solve this problem, ASM provides a trial mode for authorization policies. In trial mode, authorization policies are executed, but they do not allow or block traffic. Only execution logs are recorded. ASM administrators can check whether the effect of authorization policies meets expectations based on these logs. If not, they can adjust authorization policies until the effect meets expectations and then disable the trial mode to make the authorization policies take effect.

In this example, two applications, sleep and httpbin, are deployed to test this function. Test process: Access the httpbin application by using a curl command in the pod where the sleep application resides, verify the connectivity, configure an authorization policy for the ASM instance to deny specific requests and enable the trial mode, and then initiate a request that meets the denial conditions of the authorization policy. In trial mode, the request is not denied and the sidecar generates the execution logs of the authorization policy. After you confirm that the effect of the authorization policy meets your expectations, disable the trial mode to make the authorization policy take effect.

Step 1: Deploy the sleep and httpbin applications and test the connectivity

  1. Create a sleep.yaml file that contains the following content and run the kubectl apply -f sleep.yaml command to deploy the sleep application.
    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. Create a httpbin.yaml file that contains the following content to deploy the httpbin application.
    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
  3. Run the following command by using kubeconfig of the Container Service for Kubernetes (ACK) cluster:
    $ 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
                            
    The following output shows that when you access the httpbin application 20 times by using a curl command in the pod where the sleep application resides, the status code returned is always 200:
    200
    200
    200
    ...

Step 2: Create an authorization policy and enable the trial mode

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management, and then click the name of the instance on which you want to create an authorization policy to go to the instance details page.
  3. In the left-side navigation pane, choose Mesh Security Center > AuthorizationPolicy, and then click Create.
  4. On the page that appears, set the following parameters and click Create.
    Create an authorization policy

Step 3: Observe the effect of the authorization policy

  1. Run the following command again to access the httpbin application in the pod where the sleep application resides:
    $ 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
    The following output shows that the access request is still allowed because the authorization policy is running in trial mode:
    200
    200
    200
    ...
  2. Run the following command to adjust the role-based access control (RBAC) log level of the sidecar of the httpbin application to Debug:
    $ 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
    The following result is returned:
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0active loggers:
      ...
      rbac: debug
      ...
    100  1028    0  1028    0     0  1003k      0 --:--:-- --:--:-- --:--:-- 1003k
  3. Run the following command to filter the trial run logs of the authorization policy from the sidecar of the httpbin application:
    $ kubectl logs "$(kubectl -n foo -l app=httpbin get pods -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo | grep "shadow denied"
    The following output shows blocking logs:
    2021-11-19T20:20:48.733099Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
    2021-11-19T20:21:45.502199Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
    2021-11-19T20:22:33.065348Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]

Step 4: Disable the trial mode

  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.
  3. On the AuthorizationPolicy page, find the authorization policy that you created in Step 2, turn off the switch in the Commissioning mode column, and then click OK in the Submit message to disable the trial mode.
  4. Run the following command to initiate the access request again:
    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
    The following output shows that the access request is denied and 403 is returned because the authorization policy takes effect:
    403
    403
    403
    ...
  5. Run the following command to restore the RBAC log level of the sidecar 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
    The following result is returned:
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0active loggers:
      ...
      rbac: warning
      ...
    100  1028    0  1028    0     0  1003k      0 --:--:-- --:--:-- --:--:-- 1003k