ASM提供安全策略试运行模式来帮助解决网格中安全策略配置可能出现失误的情况。本文将通过示例为您介绍如何使用ASM安全策略试运行模式并展示试运行模式的效果。

前提条件

背景信息

ASM授权策略支持为网格中的工作负载提供命名空间和工作负载级别的访问权限控制。由于安全策略属于流量管控能力,对安全策略的配置失误可能引起非预期的访问被拒绝或放行,这对网格管理人员的工作带来了很大挑战。一旦安全策略配置失误,可能导致正常业务访问被拒绝或应当被阻止的访问被放行。为此,ASM提供了安全策略试运行模式来解决此类问题。对安全策略启用试运行选项可以使安全策略在应用后并不实际阻止或放行流量,而是仅对策略的执行输出日志。网格管理人员可以通过该日志来判断对应策略的执行结果是否符合预期,并可以参考日志将策略调整至完全符合预期后,再关闭试运行模式,使安全策略真正生效。

本文示例将部署sleep和httpbin两个测试应用,整体流程如下:在sleep应用中通过curl访问httpbin应用,验证连通性后,在ASM中配置一个拒绝特定请求的安全策略并开启试运行模式,然后发起可以匹配安全策略拒绝条件的请求。此时因为已启用试运行模式,所以该请求不会被拒绝,同时Sidecar会输出试运行的执行日志,供网格管理人员确认该安全策略的执行情况。确认无误后,关闭该安全策略的试运行模式,使安全策略生效。

步骤一:部署测试应用sleep和httpbin并测试连通性

  1. 使用以下内容创建sleep.yaml文件,并通过命令kubectl apply -f sleep.yaml部署sleep应用。
    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. 使用以下内容创建httpbin.yaml文件,部署httpbin应用。
    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. 使用ACK集群kubeconfig执行以下命令。
    $ 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
                            
    执行结果如下,可以看到从sleep应用所在的Pod中执行curl命令访问httpbin应用20次,返回值均为200。
    200
    200
    200
    ...

步骤二:创建安全策略并启用试运行模式

  1. 登录ASM控制台
  2. 在左侧导航栏选择服务网格 > 网格管理,然后单击目标实例名称进入实例详情页。
  3. 在左侧导航栏选择网格安全中心 > 授权策略,然后单击创建
  4. 在当前页面,完成以下示例设置后,单击创建
    创建授权策略

步骤三:观察示例安全策略效果

  1. 执行以下命令,再次从sleep应用中访问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
    执行结果如下,可以看到由于安全策略启用了试运行模式,所以请求仍然可以成功。
    200
    200
    200
    ...
  2. 执行以下命令,将httpbin应用的Sidecar的RBAC日志级别调整为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
    执行结果如下。
      % 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. 执行以下命令,从httpbin应用的Sidecar中筛选安全策略输出的试运行日志。
    $ kubectl logs "$(kubectl -n foo -l app=httpbin get pods -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo | grep "shadow denied"
    可以看到输出的拦截日志如下。
    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]

步骤四:关闭试运行模式

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理
  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择网格安全中心 > 授权策略
  3. 授权策略页面,找到步骤二创建的安全策略,在试运行模式列下关闭开关,然后在确认对话框,单击确认,关闭试运行模式。
  4. 使用以下命令再次发起请求测试。
    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
    执行结果如下,可以看到因为安全策略已经生效,请求被拒绝,返回403代码。
    403
    403
    403
    ...
  5. 测试完毕后,使用以下命令恢复Sidecar的日志级别为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
    执行结果如下。
      % 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