Anthos Service Mesh 示例:授权


在本教程中,您将了解什么是授权,以及如何在示例应用上为 Anthos Service Mesh 启用授权,继而了解如何为微服务启用授权政策。您将创建一个 AuthorizationPolicyDENY(拒绝)对微服务的访问,然后再创建一个 AuthorizationPolicyALLOW(允许)对微服务的特定访问。

什么是授权?

身份验证流程用于验证服务的身份,即服务是否具备自己声明的身份。授权流程则用于验证权限,即确定此服务是否有权执行某项操作。身份是这一概念的基础。使用 Anthos Service Mesh 时,可通过 AuthorizationPolicies 控制网格内工作负载之间的通信,以提高安全性和访问控制。

微服务架构需跨网络边界进行调用,因此基于 IP 的传统防火墙规则通常不足以保护工作负载之间的访问。使用 Anthos Service Mesh 时,您可以按如下方式设置授权规则:

  • 控制对网格内工作负载(无论是工作负载间还是最终用户到工作负载)的访问
  • 根据需要定制更宽泛或更精细的政策。如需深入了解如何配置政策以及实现相关最佳实践,请参阅 Anthos Service Mesh 中的授权

费用

本教程使用 Google Cloud 的以下收费组件:

  • GKE
  • Anthos Service Mesh
  • 完成本教程后,您可以删除所创建的资源以避免持续产生费用。如需了解详情,请参阅清理

    准备工作

    • 克隆代码库:

      git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
      cd anthos-service-mesh-samples
      

    部署入站流量网关:

    1. kubectl 的当前上下文设置为相应集群:

      gcloud container clusters get-credentials CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION
      
    2. 为入站流量网关创建命名空间:

      kubectl create namespace asm-ingress
      
    3. 启用用于注入的命名空间。所需步骤取决于您的 Anthos Service Mesh 类型(代管式或集群内):

      代管式

      asm-managed 修订版本标签应用于命名空间:

      kubectl label namespace asm-ingress \
        istio-injection- istio.io/rev=asm-managed --overwrite
      

      此标签对应于 Anthos Service Mesh 版本当前托管的 Anthos Service Mesh 发布版本

      集群内

      1. 使用以下命令查找 istiod 的修订版本标签:

        kubectl get deploy -n istio-system -l app=istiod -o \
          jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'
        
      2. 将修订版本标签应用于命名空间。在以下命令中,REVISION 是您在上一步中记下的 istiod 修订版本标签的值。

        kubectl label namespace asm-ingress \
          istio-injection- istio.io/rev=REVISION --overwrite
        
    4. anthos-service-mesh-samples 代码库中部署示例网关:

      kubectl apply -n asm-ingress \
      -f docs/shared/asm-ingress-gateway
      

      预期输出:

      serviceaccount/asm-ingressgateway configured
      service/asm-ingressgateway configured
      deployment.apps/asm-ingressgateway configured
      gateway.networking.istio.io/asm-ingressgateway configured
      

    部署 Online Boutique 示例应用

    1. kubectl 的当前上下文设置为相应集群(如果尚未设置):

      gcloud container clusters get-credentials CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION
      
    2. 为示例应用创建命名空间:

      kubectl create namespace onlineboutique
      
    3. onlineboutique 命名空间添加标签以自动注入 Envoy 代理。按照相关步骤启用自动边车注入

    4. 部署示例应用、前端的 VirtualService 以及工作负载的服务账号。在本教程中,您将部署 Online Boutique,这是一个微服务演示版应用。

      kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/virtual-service.yaml
      kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/service-accounts
      

    查看服务

    1. 查看 onlineboutique 命名空间中的 Pod:

      kubectl get pods -n onlineboutique
      

      预期输出:

      NAME                                     READY   STATUS    RESTARTS   AGE
      adservice-85598d856b-m84m6               2/2     Running   0          2m7s
      cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
      checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
      currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
      emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
      frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
      loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
      paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
      productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
      recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
      redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
      shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
      

      应用的所有 Pod 都应启动并运行,READY 列中应显示 2/2。这表示 Pod 已成功注入 Envoy 边车代理。 如果几分钟后没有显示 2/2,请查看问题排查指南

    2. 获取外部 IP 并将其设置为变量:

      kubectl get services -n asm-ingress
      export FRONTEND_IP=$(kubectl --namespace asm-ingress \
      get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \
      )
      

      您将看到类似如下所示的输出:

      NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
      asm-ingressgateway   LoadBalancer   10.19.247.233   35.239.7.64   80:31380/TCP,443:31390/TCP,31400:31400/TCP   27m
      
      
    3. 在网络浏览器中访问 EXTERNAL-IP 地址。您应该会在浏览器中看到 Online Boutique 商店。

      Online Boutique 前端

    工作负载的 DenyAll 授权

    本部分将添加一个 AuthorizationPolicy,以拒绝发送到货币转换服务的所有传入流量。AuthorizationPolicies 的工作原理是将 AuthorizationPolicies 转换为 Envoy 可读的配置,并将配置应用于边车代理。这使 Envoy 代理能够授权或拒绝对服务的传入请求。

    1. 将一个 AuthorizationPolicy 应用于 currencyservice。请注意 YAML 文件中 currencyservice 标签的匹配项。

      kubectl apply -f docs/authorization/currency-deny-all.yaml -n onlineboutique
      
      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: currency-policy
      spec:
        selector:
          matchLabels:
            app: currencyservice
    2. 请尝试访问您网关的 EXTERNAL-IP,以在网络浏览器中查看 Online Boutique。您应该会看到来自 currency service 的授权错误(500 内部服务错误)。

      authz rbac 500 错误

    查看边车代理日志

    如需了解边车代理的执行情况,您可以查看 Pod 中的日志。

    1. 获取 currencyservice Pod 的名称:

      CURRENCY_POD=$(kubectl get pod -n onlineboutique |grep currency|awk '{print $1}')
      
    2. 将 Envoy 代理设置为启用跟踪记录级别的日志。默认情况下,日志中不会记录被阻止的授权调用:

      kubectl exec -it $CURRENCY_POD -n onlineboutique -c istio-proxy -- curl -X POST "http://localhost:15000/logging?level=trace"
      

      预期输出:active loggers: admin: trace alternate_protocols_cache: trace ... tracing: trace upstream: trace udp: trace wasm: trace

    3. 使用 curl 将流量发送到您的 EXTERNAL_IP,以生成日志:

      for i in {0..10}; do
      curl -s -I $FRONTEND_IP ; done
      
    4. 查看 istio-proxy 中基于角色的访问权限控制 (RBAC) 相关的日志:

      kubectl logs -n onlineboutique $CURRENCY_POD -c istio-proxy | grep -m5 rbac
      

      预期输出:

      2022-07-08T14:19:20.442920Z     debug   envoy rbac      checking request: requestedServerName: outbound_.7000_._.currencyservice.onlineboutique.svc.cluster.local, sourceIP: 10.8.8.5:34080, directRemoteIP: 10.8.8.5:34080, remoteIP: 10.8.8.5:34080,localAddress: 10.8.0.6:7000, ssl: uriSanPeerCertificate: spiffe://christineskim-tf-asm.svc.id.goog/ns/onlineboutique/sa/default, dnsSanPeerCertificate: , subjectPeerCertificate: OU=istio_v1_cloud_workload,O=Google LLC,L=Mountain View,ST=California,C=US, headers: ':method', 'POST'
      2022-07-08T14:19:20.442944Z     debug   envoy rbac      enforced denied, matched policy none
      2022-07-08T14:19:20.442965Z     debug   envoy http      [C73987][S13078781800499437460] Sending local reply with details rbac_access_denied_matched_policy[none]
        ```
      

    您应该会在日志中看到一条“强制拒绝”消息,这表示 currencyservice 被设置为阻止入站请求。

    允许受限访问

    您也可以设置允许访问部分工作负载,而不是设置 DENYALL 政策。因为在有的微服务架构中,您可能会希望确保只有已获授权的服务才能相互通信。

    在本部分中,您将允许 frontendcheckout 服务与 currency 服务进行通信。

    1. 在下面的文件中,您可以看到一个特定的 source.principal(客户端)已被允许访问 currencyservice
    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: currency-policy
    spec:
      selector:
        matchLabels:
          app: currencyservice
      rules:
      - from:
        - source:
            principals: ["cluster.local/ns/onlineboutique/sa/frontend"]
      - from:
        - source:
            principals: ["cluster.local/ns/onlineboutique/sa/checkoutservice"]

    应用政策:

    kubectl apply -f docs/authorization/currency-allow-frontend-checkout.yaml -n onlineboutique
    
    1. 在网络浏览器中访问 EXTERNAL-IP,您现在应该可以访问 Online Boutique。

    在 Anthos Service Mesh 安全界面中观察您的服务

    1. 在 Google Cloud 控制台中,前往 GKE Enterprise 安全页面。

      前往 GKE Enterprise 安全

    2. 安全页面中,您可以添加或启用相关功能来确保应用工作负载安全无虞。如需了解详情,请参阅监控网格安全。选择政策审核标签页以查看工作负载概览。

    3. 请注意,在服务访问权限控制列下,只有 currencyservice 显示为“已启用”。点击已启用以查看 AuthorizationPolicy 的详细信息。

      安全政策审核

    您可以在此处查看所应用的 AuthorizationPolicy。这对于多应用工作负载非常有用,尤其是当您的工作负载应用了大量政策时。浏览该界面。您可以在该界面查看服务彼此交互的情况,并可直观地了解安全相关行为。这只是展现授权政策在保护工作负载方面所具有的优势的一个简单示例。

    清理

    为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

    为避免系统因本教程中使用的资源而导致您的 Google Cloud 账号继续产生费用,您可以删除项目删除各个资源

    删除项目

    在 Cloud Shell 中,删除项目:

    gcloud projects delete PROJECT_ID
    

    删除资源

    • 如果您希望保留集群并移除 Online Boutique 示例,请执行以下操作:

      1. 删除应用命名空间:

        kubectl delete namespace onlineboutique
        

        预期输出:

        namespace "onlineboutique" deleted
        
      2. 删除入站流量网关命名空间:

        kubectl delete namespace asm-ingress
        

        预期输出:

        amespace "asm-ingress" deleted
        
    • 如果您想防止产生额外费用,请删除集群:

      gcloud container clusters delete  CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION
      

    后续步骤