Cloud Service Mesh 示例:授权


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

什么是授权?

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

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

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

费用

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

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

准备工作

  • 克隆代码库:

    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. 启用用于注入的命名空间。所需步骤取决于您的 Cloud Service Mesh 类型(代管式或集群内):

    代管式

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

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

    此标签对应于 Cloud Service Mesh 版本当前托管的 Cloud 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]
      ```
    

您应该会在日志中看到一条 enforced denied 消息,显示 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。

清理

为避免因本教程中使用的资源导致您的 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 
    

后续步骤