Exemplo de Cloud Service Mesh: mTLS


No Cloud Service Mesh 1.5 e versões mais recentes, o TLS mútuo automático (mm automático) é ativado por padrão. Com o mTLS automático, um proxy sidecar do cliente detecta automaticamente se o servidor tem um sidecar. O sidecar do cliente envia o mTLS para as cargas de trabalho que têm sidecars e texto simples para as que não têm. No entanto, os serviços aceitam tráfego de texto simples e mTLS. Conforme você injetar proxies sidecar nos pods, configure também os serviços para aceitar apenas tráfego mTLS.

Com o Cloud Service Mesh, você pode aplicar o mTLS fora do código do aplicativo ao aplicar um único arquivo YAML. O Cloud Service Mesh oferece flexibilidade para aplicar uma política de autenticação a toda a malha de serviço, a um namespace ou a uma carga de trabalho individual.

mTLS mútuo

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Ao concluir este tutorial, exclua os recursos criados para evitar custos contínuos. Para mais informações, consulte Limpeza.

Antes de começar

  • Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como confirmar se o faturamento está ativado para o projeto.

  • Instale o Cloud Service Mesh em um cluster do GKE e implante um gateway de entrada. Se você precisar configurar um cluster para este tutorial, consulte a Guia de início rápido do Cloud Service Mesh, que vai ajudar você a:

    • Como criar um cluster do GKE
    • Provisiona o Cloud Service Mesh gerenciado.
    • Como implantar um gateway de Entrada.
    • Como implantar o aplicativo de amostra Online Boutique a partir do repositório anthos-service-mesh-packages, que é modificado com base no conjunto original de manifestos no repositório microservices-demo. Seguindo as práticas recomendadas, cada serviço é implantado em um namespace separado com uma conta de serviço exclusiva.
  • 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"]
    

Acessar o Online Boutique

  1. Defina o contexto atual de kubectl no cluster em que você implantou o Online Boutique:

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

    kubectl get services -n frontend
    

    Observe que frontend-external é um LoadBalancer e tem um endereço IP externo. O aplicativo de exemplo inclui um serviço que é um balanceador de carga, para que ele possa ser implantado no GKE sem o Cloud Service Mesh.

  3. Acesse o aplicativo no navegador usando o endereço IP externo do serviço frontend-external:

    http://FRONTEND_EXTERNAL_IP/
    
  4. O Cloud Service Mesh permite implantar um gateway de entrada. Também é possível acessar o "Online Boutique" usando o endereço IP externo do gateway de entrada. Consulte o IP externo do gateway: Substitua os marcadores pelas informações a seguir:

    • GATEWAY_SERVICE_NAME : o nome do serviço de gateway de entrada. Se você implantou o gateway de amostra sem modificação ou se implantou o gateway de entrada padrão, o nome é istio-ingressgateway.
    • GATEWAY_NAMESPACE: o namespace em que você implantou o gateway de entrada: Se você implantou o gateway de entrada padrão, o namespace é istio-system.
    kubectl get service GATEWAY_NAME -n GATEWAY_NAMESPACE
    
  5. Abra outra guia no navegador e acesse o aplicativo usando o endereço IP externo do gateway de entrada:

    http://INGRESS_GATEWAY_EXTERNAL_IP/
    
  6. Execute o seguinte comando para fazer curl no serviço frontend usando HTTP simples de outro pod. Como os serviços estão em namespaces diferentes, Usar o comando curl em Nome do 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'
    

    Sua solicitação é bem-sucedida com o status 200 porque, por padrão, são aceitos tráfego TLS e de texto simples.

Ativar o TLS mútuo por namespace

Você impõe o mTLS aplicando uma política PeerAuthentication com kubectl.

  1. Salve 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 aceitar apenas mTLS. Por padrão, o mode é PERMISSIVE, que configura os serviços para aceitar texto simples e mTLS.

  2. Aplique a política de autenticação para configurar todos os serviços do Online Boutique de modo que aceite 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
    

    Resposta esperada:

    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. Acesse o Online Boutique no navegador usando o endereço IP externo do serviço frontend-external:

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

    não é possível acessar o site

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

  5. No seu navegador, vá para a guia que dá acesso ao Online Boutique usando o endereço IP externo de istio-ingressgateway e atualize a página, que é exibida. Ao acessar o "Online Boutique" usando o gateway de entrada, a solicitação usa o seguinte caminho:

    mTLS mútuo

    Fluxo de autenticação do mTLS:

    1. O navegador envia ao servidor uma solicitação HTTP de texto simples.
    2. O contêiner do proxy do gateway de entrada intercepta a solicitação.
    3. O proxy do gateway de entrada executa um handshake de TLS com o proxy do lado do servidor (o serviço de front-end neste exemplo). Esse handshake inclui uma troca de certificados. Esses certificados são pré-carregados contêineres de proxy pelo Cloud Service Mesh.
    4. O proxy de entrada executa uma verificação de nomenclatura segura no certificado do servidor, verificando se uma identidade autorizada está em execução no servidor.
    5. Os proxies de servidor e o gateway de entrada estabelecem uma conexão TLS mútua, e o proxy do servidor encaminha a solicitação para o contêiner do aplicativo de servidor (o serviço de front-end).
  6. Execute o seguinte comando para fazer curl no serviço frontend usando HTTP simples de outro pod.

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

    Sua solicitação falhou porque estamos enviando tráfego em texto simples de uma carga de trabalho sem sidecar, em que a política peerAuthentication RÍGIDA é aplicada.

Encontrar e excluir políticas de autenticação

  1. Para uma lista de todas as políticas PeerAuthentication na malha de serviço:

    kubectl get peerauthentication --all-namespaces
    

    O resultado será assim:

    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. Exclua a política de autenticação de todos os namespaces do 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;
    

    Resposta esperada:

    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. Acesse o Online Boutique usando o endereço IP externo do serviço frontend-external e atualize a página. A página é exibida conforme o esperado.

  4. Execute o seguinte comando para fazer curl no serviço frontend usando HTTP simples 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'
    

    Sua solicitação é bem-sucedida com o status 200 porque, por padrão, são aceitos tráfego TLS e de texto simples.

Se você atualizar a página no console do Google Cloud que exibe a lista Cargas de trabalho, ela mostrará agora que o status do mTLS é Permissive.

Ativar o TLS mútuo por carga de trabalho

Para definir uma política PeerAuthentication para uma carga de trabalho específica, configure a seção selector e especifique os rótulos que correspondem à carga de trabalho pretendida. No entanto, o Cloud Service Mesh não pode agregar políticas de nível de carga de trabalho para o tráfego mTLS para um serviço. Você precisa configurar uma regra de destino para gerenciar esse comportamento.

  1. Aplique uma política de autenticação a uma carga de trabalho específica. Observe como a política a seguir usa identificadores e seletores para segmentar a implantação específica de 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
    

    Resposta esperada:

    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
    

    Resposta esperada:

    destinationrule.networking.istio.io/frontend created
  3. Acesse o Online Boutique usando o endereço IP externo do serviço frontend-external e atualize a página. A página não é exibida porque frontend service está definido como mTLSSTRICT e o proxy sidecar bloqueia a solicitação.

  4. Execute o seguinte comando para fazer curl no serviço frontend usando HTTP simples de outro pod.

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

    Sua solicitação falhou porque estamos enviando tráfego em texto simples de uma carga de trabalho sem sidecar, em que a política peerAuthentication RÍGIDA é aplicada.

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

    kubectl delete peerauthentication -n frontend frontend
    

    Resposta esperada:

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

    kubectl delete destinationrule -n frontend frontend
    

    Resposta esperada:

    destinationrule.networking.istio.io "frontend" deleted
    

Como aplicar o mTLS em toda a malha

Para impedir que todos os serviços na malha aceitem tráfego de texto simples, defina uma política PeerAuthentication para toda a malha, com o modo mTLS definido como STRICT. A política PeerAuthentication em toda a malha não pode ter um seletor e precisa ser aplicada no namespace raiz, istio-system. Quando você implanta a política, o plano de controle provisiona certificados TLS automaticamente, para que as cargas de trabalho possam ser autenticadas 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
    

    Resposta esperada:

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

  2. Acesse o Online Boutique usando o endereço IP externo do serviço frontend-external e atualize a página. A página não é exibida.

  3. Execute o seguinte comando para fazer curl no serviço frontend usando HTTP simples de outro pod.

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

    Sua solicitação falhou porque estamos enviando tráfego em texto simples de uma carga de trabalho sem sidecar, em que a política peerAuthentication RÍGIDA é aplicada.

  4. Exclua a política mesh-wide:

    kubectl delete peerauthentication -n istio-system mesh-wide
    

    Saída esperada:

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

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

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

    gcloud container clusters delete  CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  • Se quiser manter o cluster e remover o aplicativo de amostra do Online Boutique:

    1. Exclua os namespaces do aplicativo:
    kubectl delete -f online-boutique/kubernetes-manifests/namespaces
    

    Saída esperada:

    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. Exclua as entradas de serviço:
    kubectl delete -f online-boutique/istio-manifests/allow-egress-googleapis.yaml
    

    Resposta esperada:

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

A seguir