Exemplo de Cloud Service Mesh: mTLS

No Cloud Service Mesh 1.5 e posterior, o TLS mútuo (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ê aplica 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

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 amostra inclui um serviço que é um balanceador de carga, por isso, ele pode 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 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 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 testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Sua solicitação falha porque estamos enviando tráfego de texto simples de uma carga de trabalho sem sidecar em que a política STRICT peerAuthentication é 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á 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 testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Sua solicitação falha porque estamos enviando tráfego de texto simples de uma carga de trabalho sem sidecar em que a política STRICT peerAuthentication é 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 falha porque estamos enviando tráfego de texto simples de uma carga de trabalho sem sidecar em que a política STRICT peerAuthentication é 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