Cloud Service Mesh por exemplo: mTLS

No Cloud Service Mesh 1.5 e posterior, o TLS mútuo automático (mTLS automático) está ativado por predefinição. Com o mTLS automático, um proxy sidecar do lado do cliente deteta automaticamente se o servidor tem um sidecar. O sidecar do cliente envia mTLS para cargas de trabalho com sidecars e envia texto simples para cargas de trabalho sem sidecars. No entanto, os serviços aceitam tráfego de texto simples e mTLS. À medida que injeta proxies sidecar nos seus pods, recomendamos que também configure os seus serviços para aceitarem apenas tráfego mTLS.

Com a malha de serviços na nuvem, pode aplicar o mTLS, fora do código da sua aplicação, através da aplicação de um único ficheiro YAML. O Cloud Service Mesh oferece-lhe a flexibilidade de aplicar uma política de autenticação a toda a malha de serviços, a um espaço de nomes ou a uma carga de trabalho individual.

mTLS mútuo

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação gratuita.

Quando terminar este tutorial, pode evitar custos contínuos eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

Antes de começar

  • Certifique-se de que a faturação está ativada para o seu projeto do Google Cloud. Saiba como confirmar que a faturação está ativada para o seu projeto.

  • Instale o Cloud Service Mesh num cluster do GKE e implemente um gateway de entrada. Se precisar de configurar um cluster para este tutorial, consulte o guia de início rápido do Cloud Service Mesh, que explica como:

    • Criar um cluster do GKE.
    • Aprovisiona o Cloud Service Mesh gerido.
    • Implementar um gateway de entrada.
    • Implementar a aplicação de exemplo Online Boutique a partir do repositório anthos-service-mesh-packages, que é modificada a partir do conjunto original de manifestos no repositório microservices-demo. Seguindo as práticas recomendadas, cada serviço é implementado num espaço de nomes separado com uma conta de serviço única.
  • Crie um pod TestCurl para enviar tráfego de texto simples para testes.

      apiVersion: v1
      kind: Pod
      metadata:
        name: testcurl
        namespace: default
        annotations:
          sidecar.istio.io/inject: "false"
      spec:
        containers:
        - name: curl
          image: curlimages/curl
          command: ["sleep", "600"]
    

Aceda à boutique online

  1. Defina o contexto atual de kubectl para o cluster onde implementou a Online Boutique:

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  2. Liste os serviços no espaço de nomes frontend:

    kubectl get services -n frontend
    

    Repare que frontend-external é um LoadBalancer e tem um endereço IP externo. A aplicação de exemplo inclui um serviço que é um balanceador de carga para que possa ser implementado no GKE sem a malha de serviços da nuvem.

  3. Visite a aplicação no navegador através do endereço IP externo do serviço frontend-external:

    http://FRONTEND_EXTERNAL_IP/
    
  4. O Cloud Service Mesh oferece-lhe a capacidade de implementar um gateway de entrada. Também pode aceder à Online Boutique através do endereço IP externo do gateway de entrada. Obtenha o IP externo do gateway. Substitua os marcadores de posição pelas seguintes informações:

    • GATEWAY_SERVICE_NAME : O nome do serviço de gateway de entrada. Se implementou o gateway de exemplo sem modificações ou se implementou o gateway de entrada predefinido, o nome é istio-ingressgateway.
    • GATEWAY_NAMESPACE: o espaço de nomes no qual implementou a gateway de entrada. Se implementou o gateway de entrada predefinido, o espaço de nomes é istio-system.
    kubectl get service GATEWAY_NAME -n GATEWAY_NAMESPACE
    
  5. Abra outro separador no navegador e visite a aplicação através do endereço IP externo do gateway de entrada:

    http://INGRESS_GATEWAY_EXTERNAL_IP/
    
  6. Execute o seguinte comando para curl o serviço frontend com HTTP simples a partir de outro pod. Como os serviços estão em espaços de nomes diferentes, tem de usar o comando curl no nome DNS do serviço frontend.

    kubectl debug --image istio/base --target istio-proxy -it \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    O seu pedido é bem-sucedido com o estado 200, porque, por predefinição, o tráfego TLS e de texto simples é aceite.

Ative o TLS mútuo por espaço de nomes

Aplica o mTLS aplicando uma política PeerAuthentication com kubectl.

  1. Guarde a seguinte política de autenticação como mtls-namespace.yaml.

    cat <<EOF > mtls-namespace.yaml
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "namespace-policy"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    A linha mode: STRICT no YAML configura os serviços para aceitarem apenas mTLS. Por predefinição, o valor é PERMISSIVE, o que configura os serviços para aceitarem texto simples e mTLS.mode

  2. Aplique a política de autenticação para configurar todos os serviços da Online Boutique de modo a aceitarem apenas mTLS:

    for ns in ad cart checkout currency email frontend loadgenerator \
         payment product-catalog recommendation shipping; do
    kubectl apply -n $ns -f mtls-namespace.yaml
    done
    

    Resultado esperado:

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

  3. Aceda ao separador no navegador que acede à Online Boutique através do endereço IP externo do serviço frontend-external:

    http://FRONTEND_EXTERNAL_IP/
    
  4. Atualize a página. O navegador apresenta o seguinte erro:

    Não é possível aceder ao site

    A atualização da página faz com que o texto simples seja enviado para o serviço frontend. Devido à STRICTpolítica de autenticação, o proxy sidecar bloqueia o pedido ao serviço.

  5. Aceda ao separador no navegador que acede à loja online através do endereço IP externo do istio-ingressgateway e atualize a página, que é apresentada com êxito. Quando acede à Online Boutique através do gateway de entrada, o pedido segue o seguinte caminho:

    mTLS mútuo

    Fluxo de autenticação mTLS:

    1. O navegador envia um pedido HTTP de texto simples para o servidor.
    2. O contentor do proxy do gateway de entrada interceta o pedido.
    3. O proxy de gateway de entrada faz um handshake TLS com o proxy do lado do servidor (o serviço de front-end neste exemplo). Esta negociação inclui uma troca de certificados. Estes certificados são pré-carregados nos contentores de proxy pelo Cloud Service Mesh.
    4. O proxy do gateway de entrada faz uma verificação de nomenclatura segura no certificado do servidor, validando se uma identidade autorizada está a executar o servidor.
    5. O gateway de entrada e os proxies do servidor estabelecem uma ligação TLS mútua, e o proxy do servidor encaminha o pedido para o contentor da aplicação do servidor (o serviço de frontend).
  6. Execute o seguinte comando para curl o serviço frontend com HTTP simples a partir de outro pod.

    kubectl exec testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    O seu pedido falha porque estamos a enviar tráfego de texto simples a partir de uma carga de trabalho sem sidecar onde é aplicada a política STRICT peerAuthentication.

Encontre e elimine políticas de autenticação

  1. Para ver uma lista de todas as PeerAuthenticationpolíticas na malha de serviços:

    kubectl get peerauthentication --all-namespaces
    

    O resultado é semelhante ao seguinte:

    NAMESPACE         NAME               MODE     AGE
    ad                namespace-policy   STRICT   17m
    cart              namespace-policy   STRICT   17m
    checkout          namespace-policy   STRICT   17m
    currency          namespace-policy   STRICT   17m
    email             namespace-policy   STRICT   17m
    frontend          namespace-policy   STRICT   17m
    loadgenerator     namespace-policy   STRICT   17m
    payment           namespace-policy   STRICT   17m
    product-catalog   namespace-policy   STRICT   17m
    recommendation    namespace-policy   STRICT   17m
    shipping          namespace-policy   STRICT   17m
    
  2. Elimine a política de autenticação de todos os espaços de nomes da Online Boutique:

    for ns in ad cart checkout currency email frontend loadgenerator payment \
      product-catalog recommendation shipping; do
        kubectl delete peerauthentication -n $ns namespace-policy
    done;
    

    Resultado esperado:

    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    
  3. Aceda à Online Boutique através do endereço IP externo do serviço frontend-external e atualize a página. A página é apresentada conforme esperado.

  4. Execute o seguinte comando para curl o serviço frontend com HTTP simples a partir de outro pod.

    kubectl debug --image istio/base --target istio-proxy -it \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    O seu pedido é bem-sucedido com o estado 200, porque, por predefinição, o tráfego TLS e de texto simples é aceite.

Se atualizar a página na Google Cloud consola que apresenta a lista de Workloads, esta mostra agora que o estado do mTLS é Permissive.

Ative o TLS mútuo por carga de trabalho

Para definir uma política de PeerAuthentication para uma carga de trabalho específica, tem de configurar a secção selector e especificar as etiquetas que correspondem à carga de trabalho pretendida. No entanto, a Cloud Service Mesh não pode agregar políticas ao nível da carga de trabalho para tráfego mTLS de saída para um serviço. Tem de configurar uma regra de destino para gerir esse comportamento.

  1. Aplique uma política de autenticação a uma carga de trabalho específica. Repare como a política seguinte usa etiquetas e seletores para segmentar a implementação específica.frontend

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

    Resultado esperado:

    peerauthentication.security.istio.io/frontend created
  2. Configure uma regra de destino correspondente.

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

    Resultado esperado:

    destinationrule.networking.istio.io/frontend created
  3. Aceda à Online Boutique através do endereço IP externo do serviço frontend-external e atualize a página. A página não é apresentada porque o frontend service está definido como STRICT mTLS e o proxy sidecar bloqueia o pedido.

  4. Execute o seguinte comando para curl o serviço frontend com HTTP simples a partir de outro pod.

    kubectl exec testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    O seu pedido falha porque estamos a enviar tráfego de texto simples a partir de uma carga de trabalho sem sidecar onde é aplicada a política STRICT peerAuthentication.

  5. Elimine a política de autenticação:

    kubectl delete peerauthentication -n frontend frontend
    

    Resultado esperado:

    peerauthentication.security.istio.io "frontend" deleted
    
  6. Elimine a regra de destino:

    kubectl delete destinationrule -n frontend frontend
    

    Resultado esperado:

    destinationrule.networking.istio.io "frontend" deleted
    

Aplicar mTLS em toda a malha

Para impedir que todos os seus serviços na malha aceitem tráfego de texto simples, defina uma política ao nível da malha com o modo mTLS definido como STRICT.PeerAuthentication A política PeerAuthentication ao nível da malha não deve ter um seletor e tem de ser aplicada no espaço de nomes raiz, istio-system. Quando implementa a política, o plano de controlo aprovisiona automaticamente certificados TLS para que as cargas de trabalho possam autenticar-se entre si.

  1. Aplique o mTLS em toda a malha:

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

    Resultado esperado:

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

  2. Aceda à Online Boutique através do endereço IP externo do serviço frontend-external e atualize a página. A página não é apresentada.

  3. Execute o seguinte comando para curl o serviço frontend com HTTP simples a partir de outro pod.

    kubectl exec testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    O seu pedido falha porque estamos a enviar tráfego de texto simples a partir de uma carga de trabalho sem sidecar onde é aplicada a política STRICT peerAuthentication.

  4. Elimine a política mesh-wide:

    kubectl delete peerauthentication -n istio-system mesh-wide
    

    Resultado esperado:

    peerauthentication.security.istio.io "mesh-wide" deleted
    

Limpar

Para evitar incorrer em custos na sua conta do Google Cloud pelos recursos usados neste tutorial, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.

  • Se quiser evitar cobranças adicionais, elimine o cluster:

    gcloud container clusters delete  CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  • Se quiser manter o cluster e remover o exemplo da loja online:

    1. Elimine os espaços de nomes da aplicação:
    kubectl delete -f online-boutique/kubernetes-manifests/namespaces
    

    Resultado esperado:

    namespace "ad" deleted
    namespace "cart" deleted
    namespace "checkout" deleted
    namespace "currency" deleted
    namespace "email" deleted
    namespace "frontend" deleted
    namespace "loadgenerator" deleted
    namespace "payment" deleted
    namespace "product-catalog" deleted
    namespace "recommendation" deleted
    namespace "shipping" deleted
    
    1. Elimine as entradas de serviço:
    kubectl delete -f online-boutique/istio-manifests/allow-egress-googleapis.yaml
    

    Resultado esperado:

    serviceentry.networking.istio.io "allow-egress-googleapis" deleted
    serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
    

O que se segue?