Integrar a IAP com o Cloud Service Mesh

Este guia descreve como integrar o Identity-Aware Proxy (IAP) com a Cloud Service Mesh. A integração do IAP com a Cloud Service Mesh permite-lhe aceder em segurança aos serviços com base nos princípios do BeyondCorp da Google. O IAP valida a identidade do utilizador e o contexto do pedido para determinar se um utilizador deve ter permissão para aceder a uma aplicação ou a um recurso. A integração do IAP com a Cloud Service Mesh oferece-lhe as seguintes vantagens:

  • Controlo de acesso sensível ao contexto completo aos cargas de trabalho em execução no Cloud Service Mesh. Pode definir políticas de acesso detalhadas com base nos atributos do pedido de origem, como a identidade do utilizador, o endereço IP e o tipo de dispositivo. Pode combinar as suas políticas de acesso com restrições baseadas no nome do anfitrião e no caminho de um URL de pedido.

  • Ativar o suporte para reivindicações sensíveis ao contexto na autorização da malha de serviços na nuvem.

  • Acesso escalável, seguro e de alta disponibilidade à sua aplicação através de um balanceador de carga do Google Cloud. O balanceamento de carga de alto desempenho oferece proteção integrada contra ataques de negação de serviço distribuída (DDoS) e suporte para endereçamento IP anycast global.

Pré-requisitos

Siga os passos em Instale ferramentas dependentes e valide o cluster para:

Além disso, este guia pressupõe que tem:

Configurar um cluster com o Anthos Service Mesh

Esta secção explica como fazer a configuração para a integração da IAP para novas instalações da Cloud Service Mesh e atualizações.

Novas instalações

  1. Ative iap.googleapis.com. No comando seguinte, substitua PROJECT_IDpelo projeto no qual vai instalar o Cloud Service Mesh:

    gcloud services enable \
      --project=PROJECT_ID \
      iap.googleapis.com
    
  2. O cluster que está a atualizar tem de ter a opção --addons=HttpLoadBalancing definida. O suplemento HttpLoadBalancingativa um controlador de balanceamento de carga HTTP (L7) para o cluster. Execute o seguinte comando para atualizar o cluster com as opções necessárias para a Cloud Service Mesh. A menos que tenha definido uma zona ou uma região predefinida, tem de fornecer a região (--region=REGION) ou a zona (--zone=ZONE) no comando.

    gcloud container clusters update CLUSTER_NAME \
      --project=PROJECT_ID \
      --update-addons=HttpLoadBalancing=ENABLED
    
  3. Por predefinição, o ficheiro iap-operator.yaml tem a porta 31223 definida como a porta de estado e a porta 31224 definida como a porta http. Se a porta 31223 já estiver a ser usada no cluster, execute o seguinte para definir outra porta de estado:

    kpt cfg set asm gcloud.container.cluster.ingress.statusPort STATUS_PORT
    

    Se a porta 31224 já estiver a ser usada no seu cluster, execute o seguinte para definir outra porta http:

    kpt cfg set asm gcloud.container.cluster.ingress.httpPort HTTP_PORT
    
  4. Siga os passos em Instale as funcionalidades predefinidas e a AC de malha para usar um script fornecido pela Google para instalar o Cloud Service Mesh. Quando executar o script, inclua a seguinte opção:

    --option iap-operator
    

    Por exemplo:

    ./asmcli install \
      --project_id "PROJECT_ID" \
      --cluster_name "CLUSTER_NAME" \
      --cluster_location "CLUSTER_LOCATION" \
      --fleet_id FLEET_PROJECT_ID \
      --output_dir DIR_PATH \
      --enable_all \
      --option iap-operator
    

    Quando instala o Cloud Service Mesh, o ficheiro iap-operator.yaml define o campo type no serviço istio-ingressgateway como NodePort, o que configura o gateway para abrir uma porta específica na malha de serviços. Isto permite-lhe configurar um equilibrador de carga que encaminha o tráfego enviado para o nome do seu domínio para esta porta.

  5. Se estiver a instalar o Cloud Service Mesh gerido, conclua também os seguintes passos:

    1. Adicione a etiqueta de revisão ao espaço de nomes istio-system.

    2. Transfira a especificação do serviço de gateway de entrada do Istio para o IAP e atribua-lhe o nome iap_operator.yaml.

    3. Instale o ingresso como um serviço NodePort. Para mais informações, consulte o artigo Migrar do IstioOperator.

      asmcli experimental mcp-migrate-check -f iap_operator.yaml
      
      istioctl install -f /asm-generated-configs/gateways-istiooperator/"GATEWAY_NAME".yaml
      

Após instalar o Cloud Service Mesh, regresse a este guia e continue com a secção seguinte para configurar a integração com o IAP.

Atualizações

Esta secção aborda os seguintes exemplos de utilização de atualizações:

  • Já configurou a integração do IAP e está a atualizar o Cloud Service Mesh. Neste caso, já ativou o iap.googleapis.com no seu projeto e o suplemento HttpLoadBalancing no seu cluster. Avance para o passo 3 para transferir o pacote asm e atualizar o Cloud Service Mesh.

  • Está a atualizar o Cloud Service Mesh e quer configurar a integração com o IAP pela primeira vez. Neste caso, tem de concluir todos os seguintes passos, atualizar o Cloud Service Mesh e voltar a este guia após a atualização para concluir a integração.

  1. Ative iap.googleapis.com. No comando seguinte, substitua PROJECT_ID pelo projeto no qual vai instalar o Cloud Service Mesh.

    gcloud services enable \
      --project=PROJECT_ID \
      iap.googleapis.com
    
  2. O cluster que está a atualizar tem de ter a opção --addons=HttpLoadBalancing definida. O suplemento HttpLoadBalancingativa um controlador de balanceamento de carga HTTP (L7) para o cluster. Execute o seguinte comando para atualizar o cluster com as opções necessárias para a Cloud Service Mesh. A menos que tenha definido uma zona ou uma região predefinida, tem de fornecer a região (--region=REGION) ou a zona (--zone=ZONE) no comando.

    gcloud container clusters update CLUSTER_NAME \
      --project=PROJECT_ID
      --update-addons=HttpLoadBalancing=ENABLED
    
  3. Se estiver a atualizar um HTTP Cloud Load Balancer existente e em funcionamento, execute o seguinte comando para preservar as portas http e de estado existentes:

    kpt cfg set asm gcloud.container.cluster.ingress.httpPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
    
    kpt cfg set asm gcloud.container.cluster.ingress.statusPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')
    
  4. Siga os passos em Atualizar o Cloud Service Mesh para usar um script fornecido pela Google para atualizar o Cloud Service Mesh.

    Quando atualiza o Cloud Service Mesh, o ficheiro iap-operator.yaml define o campo type no serviço istio-ingressgateway como NodePort, o que configura o gateway para abrir uma porta específica na malha de serviços. Isto permite-lhe configurar um balanceador de carga, que encaminha o tráfego enviado para o seu nome de domínio para esta porta.

    Por predefinição, o ficheiro iap-operator.yaml tem a porta 31223 definida como a porta de estado e a porta 31224 definida como a porta http.

    Quando executar o script, inclua a seguinte opção:

    --option iap-operator
    

    Por exemplo:

    ./asmcli install \
      --project_id "PROJECT_ID" \
      --cluster_name "CLUSTER_NAME" \
      --cluster_location "CLUSTER_LOCATION" \
      --fleet_id FLEET_PROJECT_ID \
      --output_dir DIR_PATH \
      --enable_all \
      --option iap-operator
    
  5. Conclua a atualização acionando a injeção automática de proxy sidecar nas suas cargas de trabalho. Para ver detalhes, consulte o artigo Implementar e reimplementar cargas de trabalho.

    Após concluir a atualização, regresse a este guia e continue com a secção seguinte para configurar a integração com as CAs.

Reservar um endereço IP estático e configurar o DNS

Para integrar o Identity-Aware Proxy com a Cloud Service Mesh, tem de configurar um Google Cloud equilibrador de carga HTTP(S), que requer um nome de domínio que aponte para um endereço IP estático. Pode reservar um endereço IP externo estático, que atribui o endereço ao seu projeto indefinidamente até o libertar explicitamente.

  1. Reserve um endereço IP externo estático:

    gcloud compute addresses create example-static-ip --global
    
  2. Obtenha o endereço IP estático:

    gcloud compute addresses describe example-static-ip --global
    
  3. Na entidade de registo do nome do domínio, configure um nome do domínio totalmente qualificado (FQDN) com o endereço IP estático. Normalmente, adiciona um registo A às definições de DNS. Os passos de configuração e a terminologia para adicionar um registo A para um FQDN variam consoante a sua entidade de registo de nome de domínio.

    A propagação da definição de DNS pode demorar entre 24 e 48 horas. Pode continuar a configurar tudo neste guia, mas não vai poder testar a configuração até que as definições de DNS sejam propagadas.

Implementar uma aplicação de exemplo

Antes de ativar as CAs, precisa de uma aplicação em execução no seu cluster do GKE para poder validar se todos os pedidos têm uma identidade. Este guia usa o exemplo Bookinfo para demonstrar como configurar o balanceador de carga HTTP(S) e ativar a IAP.

Siga os passos para implementar o Bookinfo. Até implementar o balanceador de carga, a aplicação Bookinfo não está acessível fora do cluster do GKE (por exemplo, a partir de um navegador).

Pedidos externos

O recurso Gateway do Bookinfo (definido em samples/bookinfo/networking/bookinfo-gateway.yaml) usa o istio-ingressgateway pré-configurado. Recorde que, quando implementou o Cloud Service Mesh, especificou NodePort para o istio-ingressgateway, que abre uma porta específica na service mesh. Embora os nós no seu cluster tenham endereços IP externos, os pedidos provenientes de fora do cluster são bloqueados por Google Cloud regras de firewall. Com a IAP, a forma correta de expor aplicações à Internet pública é através de um equilibrador de carga. Não exponha os endereços dos nós através de regras de firewall, o que contornaria o IAP.

Para encaminhar pedidos para o Bookinfo, configure um balanceador de carga HTTP(S) no seu Google Cloud projeto. Uma vez que o balanceador de carga está no seu projeto, está dentro da firewall e pode aceder aos nós no seu cluster. Depois de configurar o equilibrador de carga com o endereço IP estático e o nome do domínio, pode enviar pedidos para o nome do domínio, e o equilibrador de carga encaminha os pedidos para os nós no cluster.

Ativar CNA

Os passos seguintes descrevem como ativar as CNA.

  1. Use o ID de cliente (CLIENT_ID no passo acima) e CLIENT_SECRET para ativar o Cloud Service Mesh. Crie um segredo do Kubernetes com os materiais do seu cliente OAuth:

    kubectl create secret generic -n istio-system my-secret --from-literal=client_id=CLIENT_ID \
    --from-literal=client_secret=CLIENT_SECRET

Implementar o balanceador de carga

Pode usar um recurso Ingress para criar um balanceador de carga de HTTP(S) com certificados SSL configurados automaticamente. Os certificados SSL geridos são aprovisionados, renovados e geridos para o seu domínio.

  1. Crie um recurso ManagedCertificate. Este recurso especifica o domínio do certificado SSL. A lista spec.domains tem de conter apenas um domínio. Os domínios com carateres universais não são suportados. No YAML seguinte, substitua DOMAIN_NAME pelo nome do domínio que configurou para o endereço IP estático externo.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: example-certificate
      namespace: istio-system
    spec:
      domains:
        - DOMAIN_NAME
    EOF
  2. Crie um recurso BackendConfig. Este recurso indica ao GCLB como realizar verificações de estado no gateway de entrada, bem como configurar o proxy com reconhecimento de identidade. Primeiro, recolha alguns valores do gateway de entrada sobre as verificações de estado:

    • Porta de entrada da verificação de funcionamento: esta é a porta de verificação de funcionamento do istio-ingress.

      export HC_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')

    • Caminho de entrada da verificação de funcionamento: este é o caminho de verificação de funcionamento do istio-ingress.

      export HC_INGRESS_PATH=$(kubectl get pods -n istio-system -l app=istio-ingressgateway -o jsonpath='{.items[0].spec.containers[?(@.name=="istio-proxy")].readinessProbe.httpGet.path}')

    cat <<EOF | kubectl apply -n istio-system -f -
    apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: http-hc-config
    spec:
      healthCheck:
        checkIntervalSec: 2
        timeoutSec: 1
        healthyThreshold: 1
        unhealthyThreshold: 10
        port: ${HC_INGRESS_PORT}
        type: HTTP
        requestPath: ${HC_INGRESS_PATH}
      iap:
        enabled: true
        oauthclientCredentials:
          secretName: my-secret
    EOF
  3. Anote o serviço de entrada com o seu BackendConfig.

        kubectl annotate -n istio-system service/istio-ingressgateway --overwrite \
          cloud.google.com/backend-config='{"default": "http-hc-config"}' \
          cloud.google.com/neg='{"ingress":false}'
    
  4. Crie o balanceador de carga definindo o recurso Ingress.

    • Defina a anotação networking.gke.io/managed-certificates para o nome do certificado que criou no passo anterior, example-certificate.

    • Defina a anotação kubernetes.io/ingress.global-static-ip-name para o nome do endereço IP estático que reservou, example-static-ip.

    • Defina o serviceName como istio-ingressgateway, que é usado no recurso Gateway para o exemplo Bookinfo.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: example-ingress
      namespace: istio-system
      annotations:
        kubernetes.io/ingress.global-static-ip-name: example-static-ip
        networking.gke.io/managed-certificates: example-certificate
    spec:
      defaultBackend:
        service:
          name: istio-ingressgateway
          port:
            number: 80
    EOF
  5. Na Google Cloud consola, aceda à página Kubernetes Engine > Serviços & Ingress.

    Aceda à página Serviços e entrada

    Deve ver a mensagem "A criar entrada" na coluna Estado. Aguarde que o GKE aprovisione totalmente o Ingress antes de continuar. Atualize a página a cada poucos minutos para obter o estado mais atualizado do Ingress. Depois do aprovisionamento do Ingress, pode ver o estado "OK" ou o erro "Todos os serviços de back-end estão no estado UNHEALTHY". Um dos recursos que o GKE aprovisiona é uma verificação de estado predefinida. Se vir a mensagem de erro, significa que o Ingress foi aprovisionado e que a verificação de estado predefinida foi executada. Quando vir o estado "OK" ou o erro, continue com a secção seguinte para configurar as verificações de estado do equilibrador de carga.

Configure a lista de acesso da IAP

Adicione um utilizador à política de acesso para o IAP:

gcloud beta iap web add-iam-policy-binding \
    --member=user:EMAIL_ADDRESS \
    --role=roles/iap.httpsResourceAccessor

onde EMAIL_ADDRESS é o endereço de email completo do utilizador, como alice@example.com.

  1. Teste o balanceador de carga. Direcione o navegador para:

    http://DOMAIN_NAME/productpage

    onde DOMAIN_NAME é o nome do domínio que configurou com o endereço IP estático externo.

    Deve ver o productpage da aplicação Bookinfo. Se atualizar a página várias vezes, deve ver diferentes versões das críticas apresentadas de forma rotativa: estrelas vermelhas, estrelas pretas e sem estrelas.

    Também deve testar o acesso https ao Bookinfo.

Ative a compatibilidade com RCToken na malha de serviços

Por predefinição, o IAP gera um símbolo da Web JSON (JWT) com âmbito para o cliente OAuth. Para a Cloud Service Mesh, pode configurar o IAP para gerar um RequestContextToken (RCToken), que é um JWT, mas com um público-alvo configurável. O RCToken permite-lhe configurar o público-alvo do JWT para uma string arbitrária, que pode ser usada nas políticas da Cloud Service Mesh para autorização detalhada.

Para configurar o RCToken:

  1. Crie uma variável de ambiente para o público-alvo do RCToken. Pode ser qualquer string que quiser.

    export RCTOKEN_AUD="your-rctoken-aud"
    
  2. Opcional: o passo seguinte requer o BACKEND_SERVICE_ID. Se precisar de saber o BACKEND_SERVICE_ID, execute o seguinte comando:

    kubectl -n istio-system get Ingress example-ingress -o json | jq \
     '.metadata.annotations."ingress.kubernetes.io/backends"'
    

    O resultado esperado é semelhante a "{\"BACKEND_SERVICE_ID\":\"HEALTHY\"}". Por exemplo, "ingress.kubernetes.io/backends": "{\"k8s-be-31224--51f3b55cd1457fb6\":\"HEALTHY\"}". O BACKEND_SERVICE_ID neste exemplo é k8s-be-31224--51f3b55cd1457fb6.

  3. Obter as definições de CNA existentes.

    gcloud iap settings get --format json \
    --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID > iapSettings.json
    
  4. Atualize IapSettings com o público-alvo do RCToken.

    cat iapSettings.json | jq --arg RCTOKEN_AUD_STR $RCTOKEN_AUD \
    '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \
    > updatedIapSettings.json
    
    gcloud iap settings set updatedIapSettings.json --format json \
    --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID
    
  5. Ative a autenticação RCToken no gateway de entrada do Istio.

    cat <<EOF | kubectl apply -f -
    apiVersion: "security.istio.io/v1beta1"
    kind: "RequestAuthentication"
    metadata:
      name: "ingressgateway-jwt-policy"
      namespace: "istio-system"
    spec:
      selector:
        matchLabels:
          app: istio-ingressgateway
      jwtRules:
      - issuer: "https://cloud.google.com/iap"
        jwksUri: "https://www.gstatic.com/iap/verify/public_key-jwk"
        audiences:
        - $RCTOKEN_AUD
        fromHeaders:
        - name: ingress-authorization
          prefix: "Istio "
        outputPayloadToHeader: "verified-jwt"
        forwardOriginalToken: true
    EOF
    
  6. Opcional: certifique-se de que os pedidos que não têm JWTs válidos são rejeitados:

      cat <<EOF | kubectl apply -f -
      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: iap-gateway-require-jwt
        namespace: istio-system
      spec:
        selector:
          matchLabels:
            app: istio-iap-ingressgateway
        action: DENY
        rules:
          - from:
              - source:
                  notRequestPrincipals: ["*"]
      EOF
      

  7. Certifique-se de que os pedidos ao Bookinfo productpage continuam a ser bem-sucedidos:

    http://DOMAIN_NAME/productpage

Para testar a política:

  1. Crie um objeto de pedido IapSettings, mas defina o rctokenAud como uma string diferente:

    cat iapSettings.json | jq --arg RCTOKEN_AUD_STR wrong-rctoken-aud \
    '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \
    > wrongIapSettings.json
    
  2. Chame a API IapSettings para definir o público-alvo do RCtoken.

    gcloud beta iap settings set wrongIapSettings.json --project=PROJECT_ID --resource-type=compute --service=BACKEND_SERVICE
  3. Faça um pedido ao Bookinfo productpage e este deve falhar:

    http://DOMAIN_NAME/productpage

Limpar

Após concluir este tutorial, remova os seguintes recursos para evitar a incorrência de cobranças indesejadas na sua conta:

  1. Elimine o certificado gerido:

    kubectl delete managedcertificates example-certificate
  2. Elimine a entrada, que anula a atribuição dos recursos de balanceamento de carga:

    kubectl -n istio-system delete ingress example-ingress

  3. Elimine o endereço IP estático:

    gcloud compute addresses delete example-static-ip --global

    Se o fizer, certifique-se de que elimina o endereço IP da sua entidade de registo de domínios.

  4. Elimine o cluster, o que elimina os recursos que compõem o cluster, como as instâncias de computação, os discos e os recursos de rede:

    gcloud container clusters delete CLUSTER_NAME