Exemplo de Cloud Service Mesh: mTLS


No Cloud Service Mesh 1.5 e versões mais recentes, o TLS mútuo automático (mTLS 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 o tráfego de texto simples e mTLS. Ao injetar proxies de arquivo secundário nos seus pods, recomendamos que você também configure os serviços para aceitar apenas o 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 o Guia de início rápido do Cloud Service Mesh, que mostra como:

    • 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.

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, é necessário agrupar o nome DNS do serviço frontend.

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -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 nos 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 \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    A solicitação falha porque todos os serviços do Online Boutique estão definidos como mTLS STRICT e o proxy sidecar bloqueia a solicitação para o serviço.

    Resposta esperada:

    000
    command terminated with exit code 56

Ver o status de mTLS

É possível conferir o status dos recursos de segurança do GKE Enterprise, incluindo políticas de autenticação, no console do Google Cloud.

  1. No console do Google Cloud, acesse a página Visão geral do GKE Enterprise.

    Ir para Visão geral

  2. Selecione o projeto do Google Cloud na lista de projetos na barra de menus.

  3. No card "Status da política", dependendo da sua configuração, clique em Ver política ou Ativar política. O painel do Policy Controller é aberto.

  4. Clique na guia Violations.

  5. Em Tipo de recurso, marque a caixa de seleção Pod. Isso mostra uma lista de pods que violam uma política.

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
    

    A saída 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 exec \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -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 agrega políticas no nível da carga de trabalho para o tráfego mTLS de saída 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 \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Sua solicitação falhou com o código de status 56.

    Se você atualizar a página no console do Google Cloud que exibe a lista Cargas de trabalho, ela mostrará que o status mTLS do serviço frontend é Strict e todos os outros serviços estão definidos como Permissive.

    somente o serviço de front-end é um mtls rigoroso

  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 \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Sua solicitação falhou com o código de status 56.

  4. Exclua a política mesh-wide:

    kubectl delete peerauthentication -n istio-system mesh-wide
    

    Resposta esperada:

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

    Se você atualizar a página no console do Google Cloud, verá que os detalhes de mTLS para todos os serviços agora exibem Permissive.

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