全部产品
Search
文档中心

服务网格 ASM:在ASM中强化应用服务安全性

更新时间:Jun 05, 2023

微服务通过纯文本HTTP进行通信,但是它们之间的所有交互并不安全。一旦内部的某个服务被攻陷,边界安全手段就如马奇诺防线,攻击者能够以该机器为跳板来攻击内网。零信任是指任何地方都需要显式认证,并使用最小权限原则来限制对资源的访问。本文介绍在ASM中使用工作负载身份、对等身份认证和请求身份认证等资源建立零信任安全体系,强化应用服务安全。

背景信息

微服务提供了诸多价值,包括可伸缩性、敏捷性、独立扩展、业务逻辑隔离、独立生命周期管理和更容易的分布式开发。然而,这些分布众多的微服务也会增加安全的挑战,每个微服务都是一个被攻击的目标。一旦内部的某个服务被攻陷,攻击者能够以该机器为跳板来攻击内网。

ASM能够减小云原生环境中的被攻击面积,并提供零信任应用网络所需的基础框架。服务网格ASM提供了对等身份和请求身份认证能力、Istio授权策略以及更为精细化管理的基于OPA的策略控制能力。通过ASM管理服务到服务的安全性,可以确保服务的端到端加密、服务级别身份认证和细粒度授权策略,实现所有访问都经过强身份验证、基于上下文授权等安全目标。

相比传统的在应用程序代码中构建安全机制,ASM零信任安全体系具有以下优势:

  • ASM Sidecar代理的策略生命周期与应用程序保持独立,因此可以更轻松地管理这些Sidecar代理。

  • ASM支持动态配置策略,更新策略变得更加容易,更新立即生效而无需重新部署应用程序。

  • ASM提供了对附加到请求的终端用户凭据进行身份验证的能力,例如JWT。

  • ASM的集中控制架构使企业的安全团队可以构建、管理和部署适用于整个企业的安全策略,从而默认情况下就能确保应用开发人员构建的业务应用的安全。无需额外的工作即可立即使用这些安全策略。

  • 使用服务网格体系结构,可以将身份验证和授权系统作为服务部署在网格中。如同网格中的其他服务一样,这些安全系统从网格中本身也可以得到安全保证,包括传输中的加密、身份识别、策略执行点、终端用户凭据的身份验证和授权等。

查看工作负载身份

当应用程序在服务网格环境中运行时,服务网格会为每个服务提供一个唯一标识。连接到服务网格中运行的其他微服务时,将会使用该标识。对等身份认证、请求身份认证和授权策略都会使用到服务标识,用于验证是否允许服务间的访问。

当使用服务网格ASM管理运行在Kubernetes上的工作负载或者基于工作负载条目定义虚拟机工作负载时,ASM也会基于工作负载的服务令牌为每个工作负载提供服务身份。

ASM中的服务身份符合SPIFFE标准,身份的格式为spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>

以下为您介绍如何查看基于Kubernetes集群接入的服务和基于工作负载条目定义的虚拟机的工作负载身份。

  1. 登录ASM控制台

  2. 在左侧导航栏,选择服务网格 > 网格管理

  3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理

  4. 在网格详情页面左侧导航栏,选择网格安全中心 > 工作负载身份

  5. 工作负载身份页面查看工作负载身份。

    • 工作负载身份页面顶部设置数据面为工作负载条目,然后选择命名空间,可以查看基于工作负载条目定义的虚拟机的工作负载身份。

    • 工作负载身份页面顶部设置数据面为集群ID,然后选择命名空间,可以查看Kubernetes集群接入服务网格的服务的工作负载身份。

使用对等身份认证实现双向TLS加密

当两个微服务进行交互时,您可以使用对等身份认证对服务之间的通信进行双向TLS加密。

  1. 部署应用,具体操作,请参见部署应用到ASM实例

  2. 执行以下命令,使用纯文本访问details服务。

    kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null -s -w '%{http_code}\n'

    预期输出:

    200

    默认情况下,服务支持TLS和纯文本访问。使用纯文本访问Productpage Pod,返回200,说明访问成功。

  3. 对details服务的通信进行双向TLS加密。

    1. 登录ASM控制台

    2. 在左侧导航栏,选择服务网格 > 网格管理

    3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理

    4. 在网格详情页面左侧导航栏,选择网格安全中心 > 对等身份认证,然后在右侧页面,单击创建双向mTLS模式

    5. 设置双向mTLS模式参数,然后单击创建

      参数

      说明

      命名空间

      设置命名空间名称。

      名称

      设置对等身份认证名称。

      mTLS模式

      设置mTLS模式为STRICT-严格遵循双向TLS认证

      工作负载标签

      打开工作负载标签选择,单击新增匹配标签,设置名称为app,为details。

  4. 执行以下命令,再次使用纯文本访问details服务。

    kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null -s -w '%{http_code}\n'

    预期输出:

    000
    command terminated with exit code 56

    返回以上结果,使用纯文本访问服务失败。对等身份认证要求每个请求都需要TLS证书认证,否则访问失败。

使用请求身份认证实现JWT身份验证

当请求微服务时,您可以创建请求身份验证策略,对服务的请求执行JWT身份验证。请求身份验证会对带有JWT Token的请求进行JWT身份验证,只有正确的JWT Token才能访问服务成功。请求身份验证对不带有JWT Token的请求不会进行JWT身份验证,不带有JWT Token的请求不受限制可以正常访问服务。

说明

您可以使用授权策略和请求身份认证,实现只有正确的JWT Token才能访问服务,无效的JWT Token或者不带有JWT Token的请求都将访问失败。

  1. 部署被请求的应用,具体操作,请参见部署应用到ASM实例

  2. 部署发起请求的应用。

    1. 获取集群KubeConfig并通过kubectl工具连接集群

    2. 使用以下内容,创建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
      ---
    3. 执行以下命令,部署sleep应用。

      kubectl apply -f sleep.yaml -n default 
  3. 登录ASM控制台

  4. 在左侧导航栏,选择服务网格 > 网格管理

  5. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理

  6. 在网格详情页面左侧导航栏,选择网格安全中心 > 请求身份认证,然后在右侧页面,单击创建

  7. 新建面板设置参数,然后单击创建

    参数

    说明

    命名空间

    设置命名空间,本文以default为例。

    名称

    自定义请求身份认证名称。

    匹配标签

    匹配标签用于匹配请求身份认证生效的服务。本文以details服务为例。

    单击新增匹配标签,设置名称为app,为details。

    jwt规则集

    单击jwt规则集右侧的添加,设置JWT规则:

    • issuer:JWT的颁发者,本文设置为testing@secure.istio.io。

    • audiences:JWT受众列表。设置哪些服务可以使用JWT Token访问目标服务。本文设置为空,表示对访问的服务不受限制。

    • jwks:设置JWT请求信息,以下为本文设置的JWT请求信息。

      { "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}
  8. 使用JWT工具将JWT请求信息编码成JWT Token。

    { "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}

    预期编码成以下令牌:

    eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
  9. 验证请求身份认证是否生效。

    1. 使用上文编码的JWT Token访问details服务

      export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
      kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer $TOKEN" -s -w '%{http_code}\n'        

      预期输出:

      200

      返回200,说明访问成功。

    2. 使用无效的JWT Token访问details服务

      kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer badtoken" -s -w '%{http_code}\n'
                                      

      预期输出:

      403

      返回403,说明访问失败。

    3. 不带有JWT Token访问details服务

      kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null  -s -w '%{http_code}\n'

      预期输出:

      200

      返回200,说明访问成功。

    根据以上结果,可以看到使用正确的JWT Token访问服务成功,使用无效的JWT Token访问服务失败,不带有JWT Token的请求访问成功。说明请求身份认证生效了。

使用授权策略实现请求来源认证

当请求微服务时,您可以使用授权策略对请求的端口、IP、来源等进行限制,只有符合要求的请求才能访问服务。以下授权策略对请求来源进行限制,限制请求中必须带有固定签发者版发的JWT Token才能访问服务。

  1. 部署被请求的应用,具体操作,请参见部署应用到ASM实例

  2. 部署发起请求的应用。

    1. 获取集群KubeConfig并通过kubectl工具连接集群

    2. 使用以下内容,创建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
      ---
    3. 执行以下命令,部署sleep应用。

      kubectl apply -f sleep.yaml -n default 
  3. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理
  4. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择网格安全中心 > 授权策略,然后单击创建
  5. 设置授权策略参数,然后单击创建

    参数

    说明

    名称

    自定义授权策略名称。

    策略类型

    设置策略类型,本文设置为允许

    命名空间

    工作负载生效页签,设置命名空间,本文以default为例。

    生效范围

    设置生效范围Service

    工作负载

    设置工作负载details

    请求身份(Principals)

    添加请求来源区域,打开请求身份(Principals)开关,设置值为testing@secure.istio.io/testing@secure.istio.io

  6. 执行以下命令,不使用JWT Token访问details服务。

     kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null  -s -w '%{http_code}\n'

    预期输出:

    403

    不使用JWT Token访问details服务访问失败,说明授权策略生效了。授权策略限制了所有请求必须带有testing@secure.istio.io颁发的JWT Token才能访问服务成功。

使用OPA策略实现细粒度访问控制

开放策略代理(OPA)是一个策略引擎,可用于为您的应用程序实现细粒度的访问控制。OPA作为通用策略引擎,可以与微服务一起部署为独立服务。为了保护应用程序,必须先授权对微服务的每个请求,然后才能对其进行处理。为了检查授权,微服务对OPA进行API调用,以确定请求是否被授权。

服务网格ASM集成了开放策略代理(OPA)插件,通过OPA定义访问控制策略,可以使您的应用实现细粒度的访问控制。具体操作,请参见在ASM中使用OPA实现细粒度访问控制