Kubernetes集群中的NetworkPolicy能够控制某些外部网站允许或禁止被某些命名空间下的服务访问,但是NetworkPolicy的方式对网络隔离比较粗粒度,对应用安全、业务安全的保护不够到位。您可以使用ASM零安全体系,动态配置授权策略,实现对命名空间下服务访问外部网站进行授权控制,从而降低风险。本文以demo-frontend命名空间和aliyun.com网站为例,介绍如何限制demo-frontend命名空间下的全部服务去访问外部网站aliyun.com 。

前提条件

已添加集群到ASM实例。具体操作,请参见添加集群到ASM实例

步骤一:注入Sidecar代理

为命名空间注入Sidecar代理,便于对该命名空间下的服务进行授权管理。

  1. 新建demo-frontend命名空间。
    1. 登录ASM控制台
    2. 在左侧导航栏,选择服务网格 > 网格管理
    3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
    4. 在网格详情页面左侧导航栏,选择网格实例 > 全局命名空间,然后在右侧页面,单击新建
    5. 新建命名空间面板设置名称为demo-frontend,然后单击确定
  2. 为demo-frontend命名空间注入Sidecar代理。
    1. 全局命名空间页面单击demo-frontend命名空间右侧自动注入列下的启用Sidecar自动注入
    2. 确认对话框单击确定

步骤二:创建测试服务

在demo-frontend命名空间下创建sleep服务。

  1. 获取集群KubeConfig并通过kubectl工具连接集群
  2. 在demo-frontend命名空间下创建sleep服务。
    1. 使用以下内容,创建sleep.yaml
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: sleep
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: sleep
        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. 执行以下命令,创建sleep服务。
      kubectl apply -f sleep.yaml -n demo-frontend
  3. 验证测试服务是否注入Sidecar成功。
    1. 登录容器服务管理控制台
    2. 在控制台左侧导航栏,单击集群
    3. 集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情
    4. 在集群管理页左侧导航栏,选择工作负载 > 容器组
    5. 容器组页面单击sleep服务的容器组名称。
      容器页签下可以看到istio-proxy,说明sleep服务注入Sidecar成功。

步骤三:创建出口网关

服务网格内的服务访问网格外的网站时,可以通过出口网关管控流量。配置出口网关的授权策略后,还可以设置条件来控制是否允许访问外部网站。

  1. 登录ASM控制台
  2. 在左侧导航栏,选择服务网格 > 网格管理
  3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
  4. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择ASM网关 > 出口网关
  5. 出口网关页面,单击创建。输入出口网关的名称,选择部署集群,设置网关类型南北向-出口,然后单击创建。本文设置出口网关的名称为egressgateway。

步骤四:创建对等身份认证

创建对等身份认证,便于授权策略使用TLS对服务进行授权。

  1. 登录ASM控制台
  2. 在左侧导航栏,选择服务网格 > 网格管理
  3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
  4. 在网格详情页面左侧导航栏,选择网格安全中心 > 对等身份认证
  5. 对等身份认证页面单击创建双向mTLS模式
  6. 设置命名空间为demo-frontend,输入名称,设置mTLS模式为STRICT模式,然后单击创建

步骤五:设置外部服务的访问策略

默认对外部服务的访问策略为允许访问全部外部服务。为了实现对特定的外部网站进行访问控制,您需要设置外部服务访问策略为REGISTRY_ONLY,未注册为ServiceEntry的外部服务将无法被服务网格中的服务访问。

  1. 设置外部服务的访问策略。
    1. 登录ASM控制台
    2. 在左侧导航栏,选择服务网格 > 网格管理
    3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
    4. 在网格详情页面左侧导航栏,选择Sidecar管理(数据面) > Sidecar代理配置
    5. 全局页签下单击外部服务访问策略,配置对外部服务的访问策略OutboundTrafficPolicyREGISTEY_ONLY,然后单击更新设置
  2. 将外部服务注册到ServiceEntry中。
    1. 在网格详情页面左侧导航栏,选择集群与工作负载管理 > 集群外服务(ServiceEntry),然后在右侧页面,单击使用YAML创建
    2. 设置命名空间istio-system,将以下内容复制到文本框中,单击创建
      apiVersion: networking.istio.io/v1beta1
      kind: ServiceEntry
      metadata:
        name: aliyuncom-ext
        namespace: istio-system
      spec:
        hosts:
          - www.aliyun.com  
        location: MESH_EXTERNAL
        ports:
          - name: http
            number: 80
            protocol: HTTP
          - name: tls
            number: 443
            protocol: TLS
        resolution: DNS

步骤六:创建流量策略

创建网关规则、目标规则和虚拟服务,使demo-frontend命名空间下的流量路由到出口网关,再由出口网关路由到外部网站。

  1. 创建网关规则。
    1. 登录ASM控制台
    2. 在左侧导航栏,选择服务网格 > 网格管理
    3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
    4. 在网格详情页面左侧导航栏,选择ASM网关 > 网关规则,然后在右侧页面,单击使用YAML创建
    5. 设置命名空间为istio-system,将以下内容复制到文本框,然后单击创建
      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: istio-egressgateway
        namespace: istio-system
      spec:
        selector:
          istio: egressgateway
        servers:
          - port:
              number: 80
              name: http
              protocol: HTTPS
            tls:
              mode: ISTIO_MUTUAL
            hosts:
              - '*'

      mode:设置为ISTIO_MUTUAL,表示启用双向TLS服务认证,即网格内服务访问外部网站需要TLS服务认证。

  2. 创建目标规则。
    1. 在网格详情页面左侧导航栏,选择流量管理中心 > 目标规则,然后在右侧页面,单击使用YAML创建
    2. 设置命名空间为demo-frontend,将以下内容复制到文本框,然后单击创建
      apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      metadata:
        name: target-egress-gateway
        namespace: demo-frontend
      spec:
        host: istio-egressgateway.istio-system.svc.cluster.local
        subsets:
          - name: target-egress-gateway-mTLS
            trafficPolicy:
              loadBalancer:
                simple: ROUND_ROBIN
              tls:
                mode: ISTIO_MUTUAL

      mode:设置为ISTIO_MUTUAL,表示启用双向TLS服务认证,即外部网站访问网格内服务需要TLS服务认证。

  3. 创建虚拟服务。
    1. 在网格详情页面左侧导航栏,选择流量管理中心 > 虚拟服务,然后在右侧页面,单击使用YAML创建
    2. 设置命名空间为demo-frontend,将以下内容复制到文本框,然后单击创建
      apiVersion: networking.istio.io/v1beta1
      kind: VirtualService
      metadata:
        name: example-com-through-egress-gateway
        namespace: demo-frontend
      spec:
        exportTo:
          - istio-system
          - demo-frontend
        gateways:
          - mesh
          - istio-system/istio-egressgateway
        hosts:
          - www.aliyun.com
        http:
          - match:
              - gateways:
                  - mesh
                port: 80
            route:
              - destination:
                  host: istio-egressgateway.istio-system.svc.cluster.local
                  port:
                    number: 80
                  subset: target-egress-gateway-mTLS
                weight: 100
          - match:
              - gateways:
                  - istio-system/istio-egressgateway
                port: 80
            route:
              - destination:
                  host: www.aliyun.com
                  port:
                    number: 80
                weight: 100

      http设置了2条匹配规则,第一条设置gatewaysmesh,表示作用范围为demo-frontend命名空间下的Sidecar代理,将demo-frontend命名空间下的流量路由到出口网关。第二条设置为gatewaysistio-system/istio-egressgateway,将出口网关的流量路由到注册的外部服务。

步骤七:创建授权策略

在demo-frontend命名空间下创建授权策略,作用在出口网关egressgateway上,拒绝来自demo-frontend命名空间的访问。

  1. 登录ASM控制台
  2. 在左侧导航栏,选择服务网格 > 网格管理
  3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
  4. 在网格详情页面左侧导航栏,选择网格安全中心 > 授权策略,然后在右侧页面,单击创建
  5. 设置授权策略参数,然后单击创建
    参数说明
    名称输入授权策略的名称。
    策略类型设置策略类型拒绝
    ASM网关网关生效页签,设置ASM网关egressgateway
    添加请求来源添加请求来源区域,打开命名空间(Namespaces)开关,设置值为demo-frontend

步骤八:验证限制demo-frontend命名空间中的服务访问外部网站是否成功

  1. 登录容器服务管理控制台
  2. 在控制台左侧导航栏,单击集群
  3. 集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情
  4. 在集群管理页左侧导航栏,选择工作负载 > 容器组
  5. 容器组页面单击sleep容器右侧操作列下的终端,单击容器:sleep
  6. 执行以下命令,访问外部网站aliyun.com。
    curl -I http://www.aliyun.com
    预期输出:
    HTTP/1.1 403 Foribidden
    ......
    RBAC: access denied
    提示RBAC access denied 403错误,说明demo-frontend命名空间下的服务访问外部网站aliyun.com失败。限制demo-frontend命名空间中的服务访问外部网站成功。