Automatizar o gerenciamento de certificados TLS para o gateway de entrada do Cloud Service Mesh usando o Certificate Authority Service

Neste tutorial, mostramos aos operadores da plataforma como usar o emissor do Certificate Authority Service (CA Service) da ferramenta cert-manager para automatizar o gerenciamento de certificados TLS no gateway de entrada do Cloud Service Mesh. Os certificados permitem que o gateway de entrada encerre o tráfego HTTPS e outros tráfegos TLS e mTLS originários de clientes na sua nuvem privada virtual (VPC, na sigla em inglês), mas fora da malha de serviço. Neste tutorial, presumimos que haja familiaridade básica com o Kubernetes e os certificados TLS.

Introdução

O Cloud Service Mesh provisiona certificados TLS para todas as cargas de trabalho na malha de serviço. Esses certificados permitem a comunicação criptografada e TLS mutuamente autenticada (mTLS) entre cargas de trabalho na malha de serviço. Uma das CAs compatíveis emite e assina os certificados.

No entanto, o Cloud Service Mesh não provisiona certificados automaticamente no gateway de entrada para o tráfego que entra na malha de serviço. Uma solução comum é usar a ferramenta de código aberto cert-manager para automatizar o gerenciamento de certificados do gateway de entrada.

A ferramenta cert-manager solicita certificados de um emissor, que representa uma autoridade certificadora (CA, na sigla em inglês). O CA Service é um serviço do Google Cloud que permite criar sua própria CA particular. A ferramenta cert-manager pode solicitar certificados pelo CA Service usando o emissor externo de código aberto do CA Service.

Uma CA particular pode emitir certificados TLS que autenticam e criptografam o tráfego dentro de uma rede interna. Os gateways de entrada do Cloud Service Mesh geralmente são configurados para permitir o tráfego de entrada de clientes que estão dentro da VPC, mas fora da malha de serviço. Para o tráfego de rede interno, é possível usar uma CA particular no CA Service para emitir certificados para o gateway de entrada.

Neste tutorial, mostramos como configurar a ferramenta cert-manager e o emissor do CA Service para automatizar o provisionamento e a renovação de certificados TLS para o gateway de entrada. A ferramenta cert-manager provisiona certificados como recursos do secret do Kubernetes do tipo TLS. Quando a ferramenta cert-manager atualiza um certificado, ela atualiza o recurso Secret com um novo certificado. O gateway de entrada executa o proxy Envoy e oferece suporte para o serviço de descoberta de secret (SDS) do Envoy. O SDS permite que o gateway de entrada comece a usar um novo certificado sem exigir que um administrador reinicie ou atualize o processo.

Os proxies sidecar que fazem parte da malha podem conseguir certificados TLS com o Serviço de AC ou com a autoridade certificadora do Cloud Service Mesh. Neste tutorial, você usará o CA Service para os certificados de proxy sidecar e de gateway de entrada. Isso permite usar uma CA raiz para todos os certificados TLS.

O diagrama a seguir mostra os recursos provisionados neste tutorial. Provisione um balanceador de carga de rede de passagem interna para o gateway de entrada. O balanceador de carga de rede de passagem interno não é um proxy, por isso não encerra conexões TCP nem executa handshakes de TLS. Em vez disso, ele encaminha conexões aos pods da implantação istio-ingressgateway.

O secret hello-example-com-credential contém um certificado e uma chave privada. O gateway hello configura os pods da implantação istio-ingressgateway para usar esse certificado e a chave privada para executar handshakes de TLS para solicitações com o nome de host hello.example.com.

gerenciamento de mtls com ca service

Os pods da implantação google-cas-issuer no namespace cert-manager solicitam certificados a partir da CA criada no CA Service. Crie uma vinculação de política de gerenciamento de identidade e acesso que permita que os pods ca-service-isser personifiquem uma conta de serviço do Google usando a federação de identidade da carga de trabalho para GKE. Conceda permissão à conta de serviço do Google para solicitar certificados a partir da sua CA no CA Service criando uma vinculação de política do IAM no pool de CAs.

Objetivos

Custos

Neste tutorial, usamos o seguinte componente faturável 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 cobrança contínua. Para mais informações, consulte Limpeza.

Antes de começar

  1. No console do Google Cloud, acesse a página do seletor de projetos e selecione ou crie um.

  2. Verifique se a cobrança está ativada para o projeto do Google Cloud.

  3. No console do Google Cloud, acesse o Cloud Shell.

    Na parte inferior do console do Google Cloud, uma sessão do Cloud Shell é aberta e exibe um prompt de linha de comando. Use o Cloud Shell para executar todos os comandos neste tutorial.

  4. Defina o projeto do console do Google Cloud que você quer usar neste tutorial:

    gcloud config set core/project PROJECT_ID
    

    Substitua PROJECT_ID pelo ID do projeto do Cloud.

    Na caixa de diálogo "Autorizar o Cloud Shell", clique em Autorizar. Ao clicar em Autorizar, você permite que os comandos gcloud executados no Cloud Shell usem suas credenciais de usuário para autenticar nas APIs do Google.

  5. Ative o Resource Manager, o GKE, o GKE Hub, a autoridade certificadora do Cloud Service Mesh e as APIs CA Service:

    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        gkehub.googleapis.com \
        meshca.googleapis.com \
        privateca.googleapis.com
    

Configurar o serviço de CA

Nesta seção, você criará uma CA raiz e duas CAs subordinadas no CA Service. Uma CA subordinada emite certificados para o gateway de entrada e a outra CA subordinada emite certificados para proxies sidecar na malha.

Para simplificar, use o mesmo projeto para o cluster do GKE e as CAs raiz e subordinada neste tutorial. No seu ambiente, é possível usar um projeto diferente para o cluster do GKE e as CAs.

  1. No Cloud Shell, crie um pool de CAs para usar na CA raiz:

    gcloud privateca pools create ROOT_CA_POOL \
        --location CA_LOCATION \
        --tier enterprise
    
    • ROOT_CA_POOL é o nome do pool de CAs. Por exemplo, root-ca-pool-tutorial.
    • CA_LOCATION é o local do pool de CAs. Por exemplo, us-central1.

    É possível listar os locais disponíveis do CA Service usando este comando: gcloud privateca locations list

  2. Crie e ative uma CA raiz:

    gcloud privateca roots create ROOT_CA \
        --auto-enable \
        --key-algorithm ec-p384-sha384 \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --subject "CN=Example Root CA, O=Example Organization" \
        --use-preset-profile root_unconstrained
    
    • ROOT_CA é o nome que você quer usar para a CA raiz. Por exemplo, root-ca-tutorial.
  3. Crie um pool de CAs para usar na CA subordinada que emite certificados para o gateway de entrada:

    gcloud privateca pools create SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --tier devops
    
    • SUBORDINATE_CA_POOL_GATEWAYS é o nome do pool de CAs. Por exemplo, subordinate-ca-mtls-pool-gateways-tutorial.
  4. Crie e ative a CA subordinada que emite certificados para o gateway de entrada:

    gcloud privateca subordinates create SUBORDINATE_CA_GATEWAYS \
        --auto-enable \
        --issuer-location CA_LOCATION \
        --issuer-pool ROOT_CA_POOL \
        --key-algorithm ec-p256-sha256 \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --subject "CN=Example Gateway mTLS CA, O=Example Organization" \
        --use-preset-profile subordinate_mtls_pathlen_0
    
    • SUBORDINATE_CA_GATEWAYS é o nome que você quer usar para a CA subordinada. Por exemplo, subordinate-ca-mtls-gateways-tutorial.
    • A sinalização --use-preset-profile configura a CA subordinada para usar o perfil de certificado Subordinado mTLS. Esse perfil permite que a CA subordinada emita certificados TLS de cliente e servidor para mTLS.

    Se você quiser que o gateway de entrada use TLS simples em vez de mTLS, a CA subordinada precisa emitir apenas certificados TLS de servidor. Nesse caso, é possível usar o perfil de certificado TLS subordinado de servidor (subordinate_server_tls_pathlen_0).

  5. Crie uma política de emissão de certificado:

    cat << EOF > policy.yaml
    baselineValues:
      keyUsage:
        baseKeyUsage:
          digitalSignature: true
          keyEncipherment: true
        extendedKeyUsage:
          serverAuth: true
          clientAuth: true
      caOptions:
        isCa: false
    identityConstraints:
      allowSubjectPassthrough: false
      allowSubjectAltNamesPassthrough: true
      celExpression:
        expression: subject_alt_names.all(san, san.type == URI && san.value.startsWith("spiffe://PROJECT_ID.svc.id.goog/ns/") )
    EOF
    

    Essa política de emissão restringe as CAs a emitir apenas certificados para cargas de trabalho na malha.

  6. Crie um pool de CAs para usar a CA subordinada que emite certificados para os proxies sidecar na malha. Aplique a política de emissão ao pool de CAs:

    gcloud privateca pools create SUBORDINATE_CA_POOL_SIDECARS \
     --issuance-policy policy.yaml \
     --location CA_LOCATION \
     --tier devops
    
    • SUBORDINATE_CA_POOL_SIDECARS é o nome do pool de CAs. Por exemplo, subordinate-ca-mtls-pool-sidecars-tutorial.
  7. Crie e ative a CA subordinada que emite certificados para os proxies sidecar na malha:

    gcloud privateca subordinates create SUBORDINATE_CA_SIDECARS \
        --auto-enable \
        --issuer-location CA_LOCATION \
        --issuer-pool ROOT_CA_POOL \
        --key-algorithm ec-p256-sha256 \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --subject "CN=Example Sidecar mTLS CA, O=Example Organization" \
        --use-preset-profile subordinate_mtls_pathlen_0
    
    • SUBORDINATE_CA_GATEWAYS é o nome que você quer usar para a CA subordinada. Por exemplo, subordinate-ca-mtls-sidecars-tutorial.

Crie um cluster do Google Kubernetes Engine

  1. No Cloud Shell, crie um cluster do GKE:

    gcloud container clusters create CLUSTER_NAME \
        --enable-ip-alias \
        --num-nodes 4 \
        --release-channel regular \
        --scopes cloud-platform \
        --workload-pool PROJECT_ID.svc.id.goog \
        --zone ZONE
    

    Substitua CLUSTER_NAME pelo nome que você quer usar para o cluster. Por exemplo, asm-ingress-cert-manager-ca-service.

    Substitua ZONE pela zona que você quer usar para o cluster. Por exemplo, us-central1-f.

    Observe o seguinte sobre o comando:

    • A sinalização --release-channel seleciona o canal de lançamento do GKE para o cluster.
    • O Cloud Service Mesh e o emissor do CA Service para a ferramenta cert-manager exigem que você defina o escopo cloud-platform nos nós do cluster.
    • O argumento --workload-pool ativa a Federação de identidade da carga de trabalho para GKE, o que permite que a conta de serviço do Kubernetes do emissor do serviço do CA personifique uma conta de serviço do Google. Essa representação significa que os pods do emissor do serviço de CA podem acessar a API CA Service sem fazer o download de um arquivo de chave para a conta de serviço do Google.
  2. Conceda permissões de administrador de cluster à sua conta de usuário:

    kubectl create clusterrolebinding cluster-admin-binding \
        --clusterrole cluster-admin \
        --user $(gcloud config get-value core/account)
    

    Você precisa das permissões fornecidas pelo ClusterRole cluster-admin do Kubernetes para criar as regras de controle de acesso baseado em papéis (RBAC, na sigla em inglês) para o Cloud Service Mesh e para instalar a ferramenta cert-manager.

Instalar o plano de controle do Anthos Service Mesh

Neste tutorial, você vai instalar o Cloud Service Mesh gerenciado para um cluster do GKE no Google Cloud, com todos os recursos em um projeto. No seu ambiente, é possível aplicar a solução descrita neste documento usando o Cloud Service Mesh gerenciado ou um plano de controle no cluster.

O Cloud Service Mesh oferece várias opções de instalação para diferentes cenários. Depois de concluir este tutorial, recomendamos que você leia o guia de instalação para selecionar a opção que melhor se adapta ao seu ambiente.

  1. No Cloud Shell, faça o download da ferramenta de instalação asmcli:

    curl --location --output asmcli https://storage.googleapis.com/csm-artifacts/asm/asmcli_1.19
    
    chmod +x asmcli
    

    Use asmcli para instalar o plano de controle do Cloud Service Mesh.

  2. Instale o plano de controle do Cloud Service Mesh:

    ./asmcli install \
        --ca gcp_cas \
        --ca_pool projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_SIDECARS \
        --cluster_location ZONE \
        --cluster_name CLUSTER_NAME \
        --enable_all \
        --enable_registration \
        --fleet_id PROJECT_ID \
        --managed \
        --output_dir asm-files \
        --project_id PROJECT_ID \
        --verbose
    

    A instalação leva alguns minutos. Quando a instalação estiver concluída, você verá a seguinte saída:

    asmcli: Successfully installed ASM.
    

Instale o gateway de entrada

  1. No Cloud Shell, crie um namespace do Kubernetes para o gateway de entrada:

    kubectl create namespace GATEWAY_NAMESPACE
    
    • GATEWAY_NAMESPACE é o nome do namespace que você quer usar para o gateway de entrada. Por exemplo, istio-ingress.
  2. Reserve um endereço IP interno estático para usar no balanceador de carga de rede do gateway de entrada interno:

    LOAD_BALANCER_IP=$(gcloud compute addresses create \
        asm-ingress-gateway-ilb \
        --region REGION \
        --subnet default \
        --format 'value(address)')
    
    • Substitua REGION pela região que contém a zona ou as zonas que os nós do cluster do GKE usam. Por exemplo, se o cluster usar a zona us-central1-f, substitua REGION por us-central1.

    Esse comando reserva um endereço IP a partir da sub-rede padrão na região especificada.

  3. Crie um manifesto do operador para o gateway de entrada:

    cat << EOF > ingressgateway-operator.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: ingressgateway-operator
      annotations:
        config.kubernetes.io/local-config: "true"
    spec:
      profile: empty
      revision: asm-managed
      components:
        ingressGateways:
        - name: istio-ingressgateway
          namespace: GATEWAY_NAMESPACE
          enabled: true
          k8s:
            overlays:
            - apiVersion: apps/v1
              kind: Deployment
              name: istio-ingressgateway
              patches:
              - path: spec.template.metadata.annotations
                value:
                  inject.istio.io/templates: gateway
              - path: spec.template.metadata.labels.sidecar\.istio\.io/inject
                value: "true"
              - path: spec.template.spec.containers[name:istio-proxy]
                value:
                  name: istio-proxy
                  image: auto
            service:
              loadBalancerIP: $LOAD_BALANCER_IP
            serviceAnnotations:
              networking.gke.io/load-balancer-type: Internal
              networking.gke.io/internal-load-balancer-allow-global-access: "true"
    EOF
    

    Observe o seguinte sobre o manifesto do operador:

  4. Crie o manifesto de instalação do gateway de entrada usando o manifesto do operador e a ferramenta istioctl que o script asmcli fez o download quando você instalou o plano de controle:

    ./asm-files/istioctl manifest generate \
        --filename ingressgateway-operator.yaml \
        --output ingressgateway
    
  5. Instale o gateway de entrada.

    kubectl apply --recursive --filename ingressgateway/
    

Instalar a ferramenta cert-manager

  1. No Cloud Shell, faça o download e aplique o manifesto de instalação da ferramenta cert-manager:

    CERT_MANAGER_VERSION=v1.5.4
    
    curl --location --output cert-manager.yaml "https://github.com/jetstack/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.yaml"
    
    kubectl apply --filename cert-manager.yaml
    

    A instalação da ferramenta cert-manager leva cerca de um minuto para ser concluída.

Instalar o controlador do emissor do CA Service

O controlador do emissor do CA Service permite que a ferramenta cert-manager solicite certificados usando o CA Service. O controlador usa o mecanismo de extensão da ferramenta emissor externo do cert-manager.

  1. No Cloud Shell, crie uma conta de serviço do Google:

    gcloud iam service-accounts create CAS_ISSUER_GSA \
        --display-name "CA Service issuer for cert-manager"
    
    • CAS_ISSUER_GSA é o nome da conta de serviço do Google. Por exemplo, cert-manager-ca-service-issuer.

    O controlador emissor do Certificate Authority Service usa essa conta de serviço do Google para fazer a autenticação nas APIs Certificate Authority Service.

  2. Crie uma vinculação de política de gerenciamento de identidade e acesso para permitir que a conta de serviço do Google do controlador do emissor do Certificate Authority Service solicite certificados pelo pool de CAs que contém a CA subordinada:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
  3. Faça o download do manifesto de instalação do controlador do emissor do Certificate Authority Service:

    CAS_ISSUER_VERSION=v0.5.3
    
    curl --location --output ca-service-issuer.yaml "https://github.com/jetstack/google-cas-issuer/releases/download/${CAS_ISSUER_VERSION}/google-cas-issuer-${CAS_ISSUER_VERSION}.yaml"
    
  4. Crie uma vinculação de política do IAM para permitir que a conta de serviço do Kubernetes ksa-google-cas-issuer no namespace cert-manager personifique a conta de serviço do Google (GSA) usando a Federação de identidade da carga de trabalho para o GKE:

    gcloud iam service-accounts add-iam-policy-binding \
     CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \
        --role roles/iam.workloadIdentityUser
    

    Os pods do controlador de emissor do CA Service usam a conta de serviço ksa-google-cas-issuer do Kubernetes.

  5. Instale o controlador do emissor do CA Service no cluster do GKE:

    kubectl apply --filename ca-service-issuer.yaml
    
  6. Adicione a anotação iam.gke.io/gcp-service-account da federação de identidade da carga de trabalho para o GKE à conta de serviço do Kubernetes usada pelos pods do controlador do emissor do CA Service:

    kubectl annotate serviceaccount ksa-google-cas-issuer --namespace cert-manager \
       "iam.gke.io/gcp-service-account=CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com"
    

    Essa anotação informa ao GKE que a conta de serviço do Kubernetes pode personificar a conta de serviço do Google para acessar as APIs do Google.

Criar um emissor de certificado

  1. No Cloud Shell, crie e aplique um manifesto GoogleCASIssuer:

    cat << EOF > gateway-cas-issuer.yaml
    apiVersion: cas-issuer.jetstack.io/v1beta1
    kind: GoogleCASIssuer
    metadata:
      name: gateway-cas-issuer
      namespace: GATEWAY_NAMESPACE
    spec:
      caPoolId: SUBORDINATE_CA_POOL_GATEWAYS
      location: CA_LOCATION
      project: PROJECT_ID
    EOF
    
    kubectl apply --filename gateway-cas-issuer.yaml
    

    O emissor permite que a ferramenta cert-manager provisione certificados pelo pool de CAs subordinados no namespace do gateway de entrada.

Implantar um aplicativo de amostra

Nesta seção, você vai verificar se a ferramenta cert-manager pode usar o emissor do CA Service para receber certificados no CA Service. Para verificar, implante um aplicativo de amostra com configuração de roteamento de solicitações e um certificado para o gateway de entrada.

  1. No Cloud Shell, crie um namespace para os recursos do aplicativo de amostra:

    cat << EOF > sample-app-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: APP_NAMESPACE
      annotations:
        mesh.cloud.google.com/proxy: '{"managed":"true"}'
      labels:
        istio.io/rev: asm-managed
    EOF
    
    kubectl apply --filename sample-app-namespace.yaml
    
    • APP_NAMESPACE é o nome do namespace do aplicativo de amostra. Por exemplo, sample-app.

    A anotação mesh.cloud.google.com/proxy ativa o plano de dados gerenciado para o namespace.

    O rótulo istio.io/rev: asm-managed seleciona o canal de lançamento regular para o plano de dados gerenciado no namespace do aplicativo de amostra. Altere o valor desse rótulo se você usar os canais de lançamento rápido ou estável.

  2. Crie um recurso de implantação para o aplicativo de amostra:

    cat << EOF > deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello
      namespace: APP_NAMESPACE
      labels:
        app: hello
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: hello
      template:
        metadata:
          labels:
            app: hello
        spec:
          containers:
          - image: gcr.io/google-samples/hello-app:1.0
            name: hello-app
            ports:
            - containerPort: 8080
    EOF
    
    kubectl apply --filename deployment.yaml
    
  3. Crie um recurso de serviço para o aplicativo de amostra:

    cat << EOF > service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: SERVICE_NAME
      namespace: APP_NAMESPACE
    spec:
      ports:
      - name: http-hello
        port: 8080
      selector:
        app: hello
      type: ClusterIP
    EOF
    
    kubectl apply --filename service.yaml
    
    • SERVICE_NAME é o nome do serviço; Por exemplo, hello.
  4. Crie um recurso de certificado para o nome de domínio hello.example.com usando o emissor do certificado:

    cat << EOF > certificate.yaml
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: hello-example-com-certificate
      namespace: GATEWAY_NAMESPACE
    spec:
      secretName: hello-example-com-credential
      commonName: hello.example.com
      dnsNames:
      - hello.example.com
      duration: 24h
      renewBefore: 8h
      issuerRef:
        group: cas-issuer.jetstack.io
        kind: GoogleCASIssuer
        name: gateway-cas-issuer
    EOF
    
    kubectl apply --filename certificate.yaml
    

    O namespace do certificado precisa corresponder ao namespace do gateway de entrada. Normalmente, somente os administradores da plataforma podem alterar recursos nesse namespace, já que as mudanças podem afetar toda a malha de serviço. A ferramenta cert-manager cria o recurso de secret para o certificado TLS no mesmo namespace. Isso significa que os administradores do aplicativo não precisam ter acesso ao namespace do gateway de entrada.

    É possível adicionar outros nomes de host à lista dnsNames no certificado. Esses nomes de host são incluídos no certificado como Nomes alternativos de assunto (SANs, na sigla em inglês).

  5. Crie um recurso de gateway para o aplicativo de exemplo:

    cat << EOF > gateway.yaml
    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: GATEWAY_NAME
      namespace: GATEWAY_NAMESPACE
    spec:
      selector:
        istio: ingressgateway
      servers:
      - hosts:
        - APP_NAMESPACE/hello.example.com
        port:
          name: https-hello
          number: 443
          protocol: HTTPS
        tls:
          credentialName: hello-example-com-credential
          mode: MUTUAL
    EOF
    
    kubectl apply --filename gateway.yaml
    
    • GATEWAY_NAME é o nome do gateway. Por exemplo, hello.
    • O campo credentialName no gateway corresponde ao campo secretName no certificado. A ferramenta cert-manager cria um secret do Kubernetes com o certificado TLS do CA Service. Esse certificado permite que o gateway de entrada encerre o tráfego TLS destinado a hello.example.com.

    O manifesto do gateway especifica o TLS MÚTUO (mTLS). Se você quiser configurar o gateway para o TLS normal, defina o modo do TLS do gateway como SIMPLE.

  6. Crie um recurso VirtualService para o aplicativo de amostra:

    cat << EOF > virtual-service.yaml
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: hello
      namespace: APP_NAMESPACE
    spec:
      hosts:
      - hello.example.com
      gateways:
      - GATEWAY_NAMESPACE/GATEWAY_NAME
      http:
      - route:
        - destination:
            host: SERVICE_NAME
            port:
              number: 8080
    EOF
    
    kubectl apply --filename virtual-service.yaml
    

    O Gateway e o VirtualService usam namespaces diferentes. Esse padrão comum restringe as alterações no roteamento baseado em host no gateway para os administradores da plataforma que têm permissões para alterar recursos no namespace do gateway de entrada.

    Os administradores do aplicativo com permissões para editar o VirtualService no namespace de aplicativo de amostra podem alterar o roteamento por outros campos de solicitação, como o caminho do URL, sem coordenar com os administradores da plataforma.

Se você quiser explorar outras opções de configuração, leia a documentação da API para os recursos de Certificado, Gateway e VirtualService.

É possível aplicar políticas de autenticação e autorização ao tráfego que entra na malha de serviço com o gateway de entrada. Para fazer isso, leia a documentação das APIs PeerAuthentication e AuthorizationPolicy do Istio.

Verificar a solução

Nesta seção, você vai verificar se é possível enviar solicitações HTTPS usando o mTLS para o aplicativo de amostra de fora da malha de serviço. Para verificar, crie uma instância de VM do Compute Engine, solicite um certificado TLS pelo CA Service e use esse certificado para autenticar a solicitação no aplicativo de amostra.

Você precisa ter acesso SSH à instância de VM. A rede padrão inclui uma regra de firewall que permite o acesso SSH. Se você não tiver acesso SSH, siga a documentação sobre regras de firewall para criar uma regra de firewall que permita conexões TCP de entrada na porta 22.

  1. No Cloud Shell, crie uma conta de serviço do Google:

    gcloud iam service-accounts create CLIENT_VM_GSA \
        --display-name "CA Service tutorial VM instance service account"
    
    • CLIENT_VM_GSA é o nome da conta de serviço do Google. Por exemplo, cas-tutorial-client.

    Atribua essa conta de serviço do Google à instância de VM do Compute Engine.

  2. Conceda o papel de Solicitante de certificado do CA Service no pool de CA subordinada dos gateways à conta de serviço do Google:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    

    Esse papel fornece permissões para solicitar certificados pelo pool de CA.

  3. Crie uma instância de VM do Compute Engine na mesma VPC que o cluster do GKE:

    gcloud compute instances create cas-tutorial-client \
        --scopes cloud-platform \
        --service-account CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --zone ZONE
    

    A instância de VM requer o escopo cloud-platform para acessar a API CA Service.

  4. Salve o endereço IP do balanceador de carga de rede de passagem interna do gateway de entrada em um arquivo:

    kubectl get services istio-ingressgateway \
       --namespace GATEWAY_NAMESPACE \
       --output jsonpath='{.status.loadBalancer.ingress[0].ip}' > ilb-ip.txt
    
  5. Salve o certificado de chave pública da CA raiz em um arquivo:

    gcloud privateca roots describe ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --format 'value(pemCaCertificates)' > root-ca-cert.pem
    
  6. Copie o certificado de CA raiz e o arquivo que contém o endereço IP do balanceador de carga de rede de passagem interno do gateway de entrada na instância de VM:

    gcloud compute scp root-ca-cert.pem ilb-ip.txt cas-tutorial-client:~ \
       --zone ZONE
    
  7. Conecte-se à instância de VM usando o SSH.

    gcloud compute ssh cas-tutorial-client --zone ZONE
    

    Execute o restante dos comandos desta seção na sessão do SSH.

  8. Instale os pacotes ca-certificates e coreutils e as ferramentas de linha de comando curl, openssl e jq:

    sudo apt-get update --yes
    
    sudo apt-get install --yes ca-certificates coreutils curl jq openssl
    
  9. Crie um par de chaves para o certificado TLS do cliente:

    openssl genrsa -out private-key.pem 2048
    
    openssl rsa -in private-key.pem -pubout -out public-key.pem
    
  10. Consulte o servidor de metadados para ver o endereço de e-mail da identidade da conta de serviço do Google anexada à instância de VM:

    GSA_EMAIL=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email)
    
  11. Crie um arquivo JSON que você usa como o corpo da solicitação ao solicitar um certificado TLS de cliente à API Certificate Authority Service:

    cat << EOF > request.json
    {
      "config": {
        "publicKey": {
          "format": "PEM",
          "key": "$(base64 --wrap 0 public-key.pem)"
        },
        "subjectConfig": {
          "subject": {
            "commonName": "$(hostname --short)",
            "organization": "Example Organization"
          },
          "subjectAltName": {
            "dnsNames": [
              "$(hostname --fqdn)"
            ],
            "emailAddresses": [
              "$GSA_EMAIL"
            ]
          }
        },
        "x509Config": {
          "caOptions": {
            "isCa": false
          },
          "keyUsage": {
            "baseKeyUsage": {
              "digitalSignature": true,
              "keyEncipherment": true
            },
            "extendedKeyUsage": {
              "clientAuth": true
            }
          }
        }
      },
      "lifetime": "86400s"
    }
    EOF
    

    Para saber mais sobre os campos na seção de configuração, consulte o tipo CertificateConfig na documentação da API CA Service.

  12. Solicite um token de acesso do OAuth 2.0 pelo servidor de metadados:

    TOKEN=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token | jq --raw-output ".access_token")
    

    Esse token de acesso fornece as permissões concedidas à conta de serviço do Google anexada à instância de VM.

  13. Solicite um certificado TLS de cliente pela API CA Service e armazene o corpo da resposta em um arquivo:

    curl --silent --request POST \
        --header "Authorization: Bearer $TOKEN" \
        --header "Content-Type: application/json" \
        --data @request.json \
        --output response.json \
        "https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_GATEWAYS/certificates"
    

    O comando usa o token de acesso para autenticar a solicitação da API.

  14. Salve o certificado do cliente e a cadeia de certificados em um arquivo:

    jq --raw-output --join-output ".pemCertificate , .pemCertificateChain[]" response.json > client-cert-chain.pem
    
  15. Use curl para enviar uma solicitação HTTPS pela instância de VM para o aplicativo de amostra:

    curl --cert client-cert-chain.pem --key private-key.pem \
        --cacert root-ca-cert.pem \
        --resolve hello.example.com:443:$(cat ilb-ip.txt) \
        --silent https://hello.example.com | head -n1
    

    A saída é assim:

    Hello, world!
    

    Essa resposta mostra que curl enviou a solicitação HTTPS usando mTLS. O aplicativo de amostra respondeu com a mensagem que você vê na saída do terminal.

    O comando curl faz o seguinte:

    • As sinalizações --cert e --key instruem curl a usar o certificado TLS de cliente e a chave privada para autenticar a solicitação. O arquivo de certificado do cliente contém a cadeia completa de certificados, desde o certificado do cliente até a CA raiz.

    • A sinalização --cacert instrui curl a verificar se a CA raiz criada neste tutorial, ou uma das CAs subordinadas dela, emitiu o certificado do servidor.

      Se você omitir essa flag, curl tentará verificar o certificado do servidor usando o pacote de AC padrão do sistema operacional, como o pacote ca-certificates no Debian. A verificação falha porque o pacote da CA padrão não inclui a CA raiz criada neste tutorial.

    • A sinalização --resolve instrui curl a usar o endereço IP do balanceador de carga de rede de passagem interno como destino para que as solicitações hospedem hello.example.com na porta 443.

      Se você omitir essa sinalização, curl tentará usar o DNS para resolver o nome de host hello.example.com. A resolução DNS falha porque não há entrada de DNS para esse nome de host.

      No seu ambiente, recomendamos que você crie um registro A de DNS que aponte para o endereço IP do balanceador de carga de rede de passagem interno ($LOAD_BALANCER_IP). Para criar esse registro usando o Cloud DNS, siga a documentação sobre como gerenciar registros.

    • A sinalização --silent suprime os relatórios de progresso de download de resposta na saída do terminal.

    • O comando envia a saída do curl para head -n1. O resultado é que a saída no terminal inclui apenas a primeira linha do corpo da resposta.

  16. Saia da sessão SSH:

    exit
    

Nesta seção, você solicitou um certificado TLS de cliente diretamente pela API CA Service. Caso o cliente seja o gateway de saída de outra malha de serviço em um cluster separado do Kubernetes será possível usar a ferramenta cert-manager e o emissor do Certificate Authority Service com a mesma CA raiz para fornecer ao cliente. certificados para o gateway de saída.

Em outras situações, é possível usar ferramentas como o Hashicorp Vault, Terraform ou gcloud para solicitar certificados TLS de cliente para cargas de trabalho fora da malha de serviço. Para saber mais, consulte a documentação do CA Service para ver exemplos de soluções e a documentação gcloud do CA Service.

(Opcional) Adicionar certificados de CA ao armazenamento confiável

Esta seção opcional mostra como adicionar certificados de CA ao armazenamento de certificados de CA confiáveis para a distribuição do Linux do Debian. Essas instruções também se aplicam a distribuições derivadas do Debian, como o Ubuntu.

Adicionar certificados de CA a esse armazenamento significa que você não precisa especificar o local dos certificados de CA confiáveis ao enviar solicitações HTTPS usando curl, Python, Go e Ruby.

  1. Conecte-se à instância de VM usando o SSH.

    gcloud compute ssh cas-tutorial-client --zone ZONE
    

    Execute o restante dos comandos desta seção na sessão do SSH.

  2. Copie o certificado da CA raiz para o diretório /usr/local/share/ca-certificates e verifique se o arquivo tem a extensão .crt:

    sudo cp root-ca-cert.pem /usr/local/share/ca-certificates/cas-rootca.crt
    
  3. Defina as permissões do arquivo para que todos os usuários possam ler o arquivo do certificado de CA raiz:

    sudo chmod 644 /usr/local/share/ca-certificates/cas-rootca.crt
    
  4. Execute o script update-ca-certificates:

    sudo update-ca-certificates
    

    Esse script adiciona o certificado ao conjunto de certificados confiáveis no diretório /etc/ssl/certs e ao arquivo /etc/ssl/certs/ca-certificates.crt.

    A saída é esta:

    Updating certificates in /etc/ssl/certs...
    1 added, 0 removed; done.
    Running hooks in /etc/ca-certificates/update.d...
    done.
    
  5. Use curl para enviar uma solicitação HTTPS pela instância de VM para o aplicativo de amostra:

    curl --cert client-cert-chain.pem --key private-key.pem \
       --resolve hello.example.com:443:$(cat ilb-ip.txt) \
       --silent https://hello.example.com | head -n1
    

    A saída é assim:

    Hello, world!
    

    Essa resposta mostra que curl enviou a solicitação HTTPS usando mTLS e validou o certificado TLS de servidor do gateway de entrada usando o armazenamento de certificados padrão da CA.

  6. Saia da sessão SSH:

    exit
    

Resolver problemas

Se o controlador do emissor do CA Service não criar o secret do certificado TLS, visualize os registros do controlador do emissor do CA Service:

kubectl logs deployment/google-cas-issuer --namespace cert-manager

Se você tiver problemas para instalar o Cloud Service Mesh, execute a ferramenta asmcli para validar o projeto do Cloud e o cluster do GKE.

Se você tiver problemas ao seguir este tutorial, recomendamos que consulte estes documentos:

Limpar

Para evitar cobranças recorrentes na conta do Google Cloud pelos recursos usados neste tutorial, é possível excluir o projeto ou excluir os recursos individuais.

Exclua o projeto

  1. No Cloud Shell, exclua o projeto:

    gcloud projects delete PROJECT_ID
    

Excluir os recursos

Se você quiser manter o projeto do Google Cloud usado neste tutorial, exclua os recursos individuais:

  1. No Cloud Shell, cancele o registro do cluster do GKE no GKE Hub:

    gcloud container hub memberships unregister CLUSTER_NAME \
        --gke-cluster ZONE/CLUSTER_NAME
    
  2. Exclua o cluster do GKE:

    gcloud container clusters delete CLUSTER_NAME \
        --zone ZONE --async --quiet
    
  3. Exclua as vinculações de política do IAM no pool de CA subordinada:

    gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
    gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
  4. Desative e programe a exclusão das CAs subordinadas e da CA raiz:

    gcloud privateca subordinates disable SUBORDINATE_CA_GATEWAYS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --quiet
    
    gcloud privateca subordinates delete SUBORDINATE_CA_GATEWAYS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --ignore-active-certificates \
        --quiet
    
    gcloud privateca subordinates disable SUBORDINATE_CA_SIDECARS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --quiet
    
    gcloud privateca subordinates delete SUBORDINATE_CA_SIDECARS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --ignore-active-certificates \
        --quiet
    
    gcloud privateca roots disable ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --quiet
    
    gcloud privateca roots delete ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --ignore-active-certificates \
        --quiet
    
  5. Exclua a vinculação da política do IAM da conta de serviço do controlador do emissor do CA Service:

    gcloud iam service-accounts remove-iam-policy-binding \
        CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \
        --role roles/iam.workloadIdentityUser
    
  6. Exclua as contas de serviço do Google:

    gcloud iam service-accounts delete --quiet \
        CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com
    
    gcloud iam service-accounts delete --quiet \
        CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com
    
  7. Exclua o endereço IP do balanceador de carga reservado:

    gcloud compute addresses delete asm-ingress-gateway-ilb \
        --region REGION --quiet
    
  8. Exclua a instância de VM do Compute Engine:

    gcloud compute instances delete cas-tutorial-client \
        --zone ZONE --quiet
    

A seguir