Anthos Service Mesh 示例:mTLS


在 Anthos Service Mesh 1.5 及更高版本中,默认情况下启用了自动双向 TLS(自动 mTLS)。通过自动 mTLS,客户端边车代理会自动检测服务器是否具有 Sidecar。客户端 Sidecar 会将 mTLS 发送到具有 Sidecar 的工作负载,并将纯文本流量发送到没有 Sidecar 的工作负载。但请注意,服务会接受纯文本和 mTLS 流量。在向 Pod 注入 Sidecar 代理时,我们还建议您将服务配置为仅接受 mTLS 流量。

借助 Anthos Service Mesh,您可以通过应用单个 YAML 文件在应用代码之外强制执行 mTLS。借助 Anthos Service Mesh,您可以灵活地将身份验证政策应用于整个服务网格、命名空间或单个工作负载。

双向 mTLS

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

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

准备工作

本教程使用 Online Browsing 示例应用演示如何在安装了 Anthos Service Mesh 的 GKE 集群中配置 mTLS。

访问 Online Boutique

  1. kubectl 的当前上下文设置为在其中部署 Online Boutique 的集群:

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION
    
  2. 获取 Online Boutique 服务的列表:

    kubectl get services -n demo
    

    请注意,frontend-externalLoadBalancer,它具有外部 IP 地址。示例应用包含作为负载均衡器的服务,因此可以在不使用 Anthos Service Mesh 的情况下在 GKE 上部署。

  3. 使用 frontend-external 服务的外部 IP 地址在浏览器中访问该应用:

    http://FRONTEND_EXTERNAL_IP/
    
  4. Anthos Service Mesh 提供了一个名为 istio-ingressgateway 的默认入站流量网关。您还可以使用 istio-ingressgateway 的外部 IP 地址来访问 Online Boutique。获取 istio-ingressgateway 的外部 IP:

    kubectl get service istio-ingressgateway -n istio-system
    
  5. 在浏览器中打开另一个标签页,并使用 istio-ingressgateway 的外部 IP 地址访问该应用:

    http://INGRESS_GATEWAY_EXTERNAL_IP/
    
  6. 运行以下命令以使用来自 demo 命名空间中另一个 pod 的纯文本 HTTP curl frontend 服务。

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

    请求成功并显示 200 状态,因为在默认情况下,TLS 和纯文本流量均可接受。

按命名空间启用双向 TLS

您可以应用使用 kubectlPeerAuthentication 政策来强制执行 mTLS。

  1. 应用以下身份验证政策以将 demo 命名空间中的所有服务配置为仅接受 mTLS:

    kubectl apply -f - <<EOF
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "namespace-policy"
      namespace: "demo"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    预期输出:

    peerauthentication.security.istio.io/namespace-policy created

    YAML 中的 mode: STRICT 行将服务配置为仅接受 mTLS。mode 的默认值为 PERMISSIVE,用于将服务配置为接受纯文本和 mTLS。

  2. 在浏览器中转到使用 frontend-external 服务的外部 IP 地址访问Online Boutique 的标签,然后刷新页面。浏览器会显示以下错误:

    网站无法访问

    刷新页面会导致将纯文本发送到 frontend 服务。由于 STRICT 身份验证政策的原因,边车代理会阻止对服务的请求。

  3. 在浏览器中转到使用 istio-ingressgateway 的外部 IP 地址访问 Online Boutique 的标签,然后刷新页面,页面会成功显示。当您使用 istio-ingressgateway 访问 Online Boutique 时,请求会采用以下路径:

    双向 mTLS

    mTLS 身份验证流程:

    1. 浏览器将纯文本 HTTP 请求发送到服务器。
    2. istio-ingressgateway 代理容器会拦截请求。
    3. istio-ingressgateway 代理使用服务器端代理(在此示例中的前端服务)执行 TLS 握手。此握手包括交换证书。这些证书由 Anthos Service Mesh 预加载到代理容器中。
    4. istio-ingressgateway 代理会对服务器证书执行安全命名检查,以确认是已获授权的身份正在运行服务器。
    5. istio-ingressgateway 和服务器代理建立一个双向 TLS 连接,服务器代理将请求转发到服务器应用容器(前端服务)。
  4. 运行以下命令以使用来自 demo 命名空间中另一个 pod 的纯文本 HTTP curl frontend 服务。

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

    由于 demo 命名空间中的所有服务都设置为 STRICT mTLS,并且边车代理会阻止对服务的请求,所以请求失败。

    预期输出:

    000
    command terminated with exit code 56

查看 mTLS 状态

您可以在 Google Cloud 控制台中查看 Anthos 安全功能的状态,包括身份验证政策。

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

    前往 GKE Enterprise 安全

  2. 从菜单栏的下拉列表中选择 Google Cloud 项目。

    政策摘要显示应用安全的状态,包括 mTLS。

  3. 点击政策审核以查看每个集群和命名空间的工作负载政策状态。mTLS 状态卡片提供了概览。工作负载列表显示每个工作负载的 mTLS 状态。

    所有服务均为严格 mTLS

查找和删除身份验证政策

  1. 如需服务网格中所有 PeerAuthentication 警察的列表,请运行以下命令:

    kubectl get peerauthentication --all-namespaces
    
  2. 删除身份验证政策:

    kubectl delete peerauthentication -n demo namespace-policy
    

    预期输出:

    peerauthentication.security.istio.io "namespace-policy" deleted
  3. 使用 frontend-external 服务的外部 IP 地址访问 Online Boutique,然后刷新页面。页面将按预期显示。

  4. 运行以下命令以使用来自 demo 命名空间中另一个 pod 的纯文本 HTTP curl frontend 服务。

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

    请求成功并显示 200 状态,因为在默认情况下,TLS 和纯文本流量均可接受。

如果您刷新了 Google Cloud 控制台中显示工作负载列表的页面,则现在会显示 mTLS 状态为 Permissive

为每个工作负载启用双向 TLS

要为特定工作负载设置 PeerAuthentication 政策,您必须配置 selector 部分并指定与所需工作负载匹配的标签。但是,Anthos Service Mesh 无法汇总到服务的出站 mTLS 流量的工作负载级政策。您需要配置目标规则来管理该行为。

  1. 将身份验证政策应用于 demo 命名空间中的特定工作负载。请注意以下政策如何使用标签和选择器来定位特定的 frontend 部署。

    cat <<EOF | kubectl apply -n demo -f -
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "frontend"
      namespace: "demo"
    spec:
      selector:
        matchLabels:
          app: frontend
      mtls:
        mode: STRICT
    EOF
    

    预期输出:

    peerauthentication.security.istio.io/frontend created
  2. 配置匹配的目标规则。

    cat <<EOF | kubectl apply -n demo -f -
    apiVersion: "networking.istio.io/v1alpha3"
    kind: "DestinationRule"
    metadata:
      name: "frontend"
    spec:
      host: "frontend.demo.svc.cluster.local"
      trafficPolicy:
        tls:
          mode: ISTIO_MUTUAL
    EOF
    

    预期输出:

    destinationrule.networking.istio.io/frontend created
  3. 使用 frontend-external 服务的外部 IP 地址访问 Online Boutique,然后刷新页面。该页面无法显示,因为 frontend service 设置为 STRICT mTLS,并且边车代理会阻止请求。

  4. 运行以下命令以使用来自 demo 命名空间中另一个 pod 的纯文本 HTTP curl frontend 服务。

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

    您的请求失败,状态代码为 56

    如果您刷新了 Google Cloud 控制台中显示工作负载列表的页面,则现在会显示 frontend 服务的 mTLS 状态为 Strict 且所有其他服务设置为 Permissive

    只有前端服务是严格 mTLS

  5. 删除身份验证政策和目标规则

    kubectl delete peerauthentication -n demo frontend
    kubectl delete destinationrule -n demo frontend
    

强制执行网格级 mTLS

如需阻止网格中的所有服务接受明文流量,请设置 mTLS 模式设置为 STRICT 的网格级 PeerAuthentication 政策。网格级 PeerAuthentication 政策不应具有选择器,并且必须在根命名空间 istio-system 中应用。部署政策时,控制层面会自动预配 TLS 证书,以便工作负载可以相互进行身份验证。

  1. 强制执行网格级 mTLS:

    kubectl apply -f - <<EOF
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "mesh-wide"
      namespace: "istio-system"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    预期输出:

    peerauthentication.security.istio.io/mesh-wide created

  2. 使用 frontend-external 服务的外部 IP 地址访问 Online Boutique,然后刷新页面。页面不会显示。

  3. 运行以下命令以使用来自 demo 命名空间中另一个 pod 的纯文本 HTTP curl frontend 服务。

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

    您的请求失败,状态代码为 56

  4. 删除 mesh-wide 政策:

    kubectl delete peerauthentication -n istio-system mesh-wide
    

如果您刷新了 Google Cloud 控制台中的页面,则会看到所有服务的 mTLS 详细信息现在都显示 Permissive

清理

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

  • 如果您想防止产生额外费用,请删除集群:

    gcloud container clusters delete  CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION
    
  • 如果您希望保留集群并移除 Online Boutique 示例,请执行以下操作:

    kubectl delete namespaces demo
    

后续步骤

  • 如需查看有关如何配置 PeerAuthentication 政策的一般指南,请参阅配置传输安全性