Configure a segurança do serviço com gRPC sem proxy

Este guia mostra como configurar um serviço de segurança para uma malha de serviços gRPC sem proxy.

Requisitos

Antes de configurar a segurança do serviço para a malha de serviços sem proxy gRPC, certifique-se de que cumpre os seguintes requisitos.

Configure a gestão de identidade e de acesso

Tem de ter as autorizações necessárias para usar o Google Kubernetes Engine. No mínimo, tem de ter as seguintes funções:

  • roles/container.clusterAdmin Função do GKE
  • roles/compute.instanceAdmin Função do Compute Engine
  • roles/iam.serviceAccountUser função

Para criar os recursos necessários para a configuração, tem de ter a função de compute.NetworkAdmin. Esta função contém todas as autorizações necessárias para criar, atualizar, eliminar, listar e usar (ou seja, referenciar esta função noutros recursos) os recursos necessários. Se for o proprietário-editor do seu projeto, tem automaticamente esta função.

Tenha em atenção que networksecurity.googleapis.com.clientTlsPolicies.use e networksecurity.googleapis.com.serverTlsPolicies.use não são aplicados quando faz referência a estes recursos no recurso do serviço de back-end.

Se esta opção for aplicada no futuro e estiver a usar a função compute.NetworkAdmin, não vai notar problemas quando esta verificação for aplicada.

Se estiver a usar funções personalizadas e esta verificação for aplicada no futuro, tem de se certificar de que inclui a autorização .use respetiva. Caso contrário, no futuro, pode descobrir que a sua função personalizada não tem as autorizações necessárias para fazer referência a clientTlsPolicy ou serverTlsPolicy a partir do serviço de back-end.

Prepare-se para a configuração

A segurança da malha de serviços sem proxy (PSM) adiciona segurança a uma malha de serviços configurada para o equilíbrio de carga de acordo com a documentação dos serviços gRPC sem proxy. Numa malha de serviços sem proxy, um cliente gRPC usa o esquema xds: no URI para aceder ao serviço, o que ativa as funcionalidades de equilíbrio de carga e descoberta de pontos finais do PSM.

Atualize os clientes e os servidores gRPC para a versão correta

Crie ou recrie as suas aplicações com a versão mínima suportada do gRPC para o seu idioma.

Atualize o ficheiro de arranque

As aplicações gRPC usam um único ficheiro de arranque, que tem de ter todos os campos necessários pelo código do lado do cliente e do servidor gRPC. Um gerador de arranque gera automaticamente o ficheiro de arranque para incluir flags e valores de que a segurança do PSM precisa. Para mais informações, consulte a secção Ficheiro de inicialização, que inclui um ficheiro de inicialização de exemplo.

Vista geral da configuração

Este processo de configuração é uma extensão da configuração da malha de serviços na nuvem com o GKE e os serviços gRPC sem proxy. Os passos existentes não modificados deste procedimento de configuração são referenciados sempre que se aplicam.

As principais melhorias à configuração do Cloud Service Mesh com o GKE são as seguintes:

  1. Configurar o serviço de AC, no qual cria conjuntos de ACs privadas e as autoridades de certificação necessárias.
  2. Criar um cluster do GKE com a Federação de identidades de cargas de trabalho do GKE para o GKE e funcionalidades de certificados de malha e integração do serviço de AC.
  3. Configurar a emissão de certificados de malha no cluster.
  4. Criar as contas de serviço de cliente e servidor.
  5. Configurar o servidor de exemplo que usa APIs xDS e credenciais do servidor xDS para adquirir a configuração de segurança da Cloud Service Mesh.
  6. Configurar o cliente de exemplo que usa credenciais xDS.
  7. A atualizar a configuração do Cloud Service Mesh para incluir a configuração de segurança.

Pode ver exemplos de código para usar credenciais xDS nas seguintes localizações:

Atualize a CLI Google Cloud

Para atualizar a Google Cloud CLI, execute o seguinte comando:

gcloud components update

Configure variáveis de ambiente

Neste guia, usa comandos do Cloud Shell e as informações repetidas nos comandos são representadas por várias variáveis de ambiente. Defina os seus valores específicos para as seguintes variáveis de ambiente no ambiente de shell antes de executar os comandos. Cada linha de comentário indica o significado da variável de ambiente associada.

# Your project ID
PROJECT_ID=PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME=CLUSTER_NAME
ZONE=ZONE
gcloud config set compute/zone $ZONE

# GKE cluster URL derived from the above
GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/${PROJECT_ID}/locations/${ZONE}/clusters/${CLUSTER_NAME}"

# Workload pool to be used with the GKE cluster
WORKLOAD_POOL="${PROJECT_ID}.svc.id.goog"

# Kubernetes namespace to run client and server demo.
K8S_NAMESPACE='default'
DEMO_BACKEND_SERVICE_NAME='grpc-gke-helloworld-service'

# Compute other values
# Project number for your project
PROJNUM=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")

# VERSION is the GKE cluster version. Install and use the most recent version
# from the rapid release channel and substitute its version for
# CLUSTER_VERSION, for example:
# VERSION=latest available version
# Note that the minimum required cluster version is 1.21.4-gke.1801.
VERSION="CLUSTER_VERSION"
SA_GKE=service-${PROJNUM}@container-engine-robot.iam.gserviceaccount.com

Ative o acesso às APIs necessárias

Esta secção explica como ativar o acesso às APIs necessárias.

  1. Execute o seguinte comando para ativar a Cloud Service Mesh e outras APIs necessárias para a segurança da Service Mesh gRPC sem proxy.

    gcloud services enable \
        container.googleapis.com \
        cloudresourcemanager.googleapis.com \
        compute.googleapis.com \
        trafficdirector.googleapis.com \
        networkservices.googleapis.com \
        networksecurity.googleapis.com \
        privateca.googleapis.com \
        gkehub.googleapis.com
    
  2. Execute o seguinte comando para permitir que a conta de serviço predefinida aceda à API Cloud Service Mesh security.

    GSA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \
        --filter='displayName:Compute Engine default service account')
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member serviceAccount:${GSA_EMAIL} \
       --role roles/trafficdirector.client
    

Crie ou atualize um cluster do GKE

A segurança do serviço Cloud Service Mesh depende da integração do serviço de AC com o GKE. O cluster do GKE tem de cumprir os seguintes requisitos, além dos requisitos de configuração:

  • Use uma versão mínima do cluster de 1.21.4-gke.1801. Se precisar de funcionalidades que estão numa versão posterior, pode obter essa versão no canal de lançamento rápido.
  • O cluster do GKE tem de estar ativado e configurado com certificados de malha, conforme descrito no artigo Criar autoridades de certificação para emitir certificados.
  1. Crie um novo cluster que use a Workload Identity Federation para o GKE. Se estiver a atualizar um cluster existente, avance para o passo seguinte. O valor que indica para --tags tem de corresponder ao nome transmitido ao parâmetro --target-tags para o comando firewall-rules create na secção Configurar a malha de serviços na nuvem com componentes do Cloud Load Balancing.

    # Create a GKE cluster with GKE managed mesh certificates.
    gcloud container clusters create CLUSTER_NAME \
      --release-channel=rapid \
      --scopes=cloud-platform \
      --image-type=cos_containerd \
      --machine-type=e2-standard-2 \
      --zone=ZONE \
      --workload-pool=PROJECT_ID.svc.id.goog \
      --enable-mesh-certificates \
      --cluster-version=CLUSTER_VERSION \
      --enable-ip-alias \
      --tags=allow-health-checks \
      --workload-metadata=GKE_METADATA
    

    A criação do cluster pode demorar vários minutos.

  2. Se estiver a usar um cluster existente, ative a Workload Identity Federation para o GKE e os certificados de malha do GKE. Certifique-se de que o cluster foi criado com a flag --enable-ip-alias, que não pode ser usada com o comando update.

    gcloud container clusters update CLUSTER_NAME \
      --enable-mesh-certificates
    
  3. Execute o seguinte comando para mudar para o novo cluster como cluster predefinido para os seus comandos kubectl:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --zone ZONE
    

Registe clusters numa frota

Registe o cluster que criou ou atualizou em Criar um cluster do GKE com uma frota. O registo do cluster facilita a configuração de clusters em vários projetos.

Tenha em atenção que cada um destes passos pode demorar até dez minutos a ser concluído.

  1. Registe o seu cluster na frota:

    gcloud container fleet memberships register CLUSTER_NAME \
      --gke-cluster=ZONE/CLUSTER_NAME \
      --enable-workload-identity --install-connect-agent \
      --manifest-output-file=MANIFEST-FILE_NAME
    

    Substitua as variáveis da seguinte forma:

    • CLUSTER_NAME: o nome do cluster.
    • ZONE: a zona do seu cluster.
    • MANIFEST-FILE_NAME: o caminho onde estes comandos geram o manifesto para registo.

    Quando o processo de registo é bem-sucedido, é apresentada uma mensagem como a seguinte:

    Finished registering the cluster CLUSTER_NAME with the fleet.
  2. Aplique o ficheiro de manifesto gerado ao cluster:

    kubectl apply -f MANIFEST-FILE_NAME
    

    Quando o processo de candidatura é bem-sucedido, vê mensagens como as seguintes:

    namespace/gke-connect created
    serviceaccount/connect-agent-sa created
    podsecuritypolicy.policy/gkeconnect-psp created
    role.rbac.authorization.k8s.io/gkeconnect-psp:role created
    rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created
    role.rbac.authorization.k8s.io/agent-updater created
    rolebinding.rbac.authorization.k8s.io/agent-updater created
    role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created
    rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    role.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    secret/http-proxy created
    deployment.apps/gke-connect-agent-20210416-01-00 created
    service/gke-connect-monitoring created
    secret/creds-gcp create
    
  3. Obtenha o recurso de subscrição do cluster:

    kubectl get memberships membership -o yaml
    

    O resultado deve incluir o Workload Identity Pool atribuído pela frota, onde PROJECT_ID é o ID do seu projeto:

    workload_identity_pool: PROJECT_ID.svc.id.goog
    

    Isto significa que o cluster foi registado com êxito.

Crie autoridades de certificação para emitir certificados

Para emitir certificados para os seus pods, crie um conjunto do serviço de AC e as seguintes autoridades de certificação (ACs):

  • CA de raiz. Esta é a raiz de fidedignidade para todos os certificados de malha emitidos. Pode usar uma AC raiz existente, se tiver uma. Crie a CA de raiz no nível enterprise, que se destina à emissão de certificados de longa duração e baixo volume.
  • CA subordinado. Esta AC emite certificados para cargas de trabalho. Crie a AC subordinada na região onde o cluster está implementado. Crie a AC subordinada no nível devops, que se destina à emissão de certificados de curta duração e em grande volume.

A criação de uma CA subordinada é opcional, mas recomendamos vivamente que crie uma, em vez de usar a CA de raiz para emitir certificados da malha do GKE. Se decidir usar a AC de raiz para emitir certificados de malha, certifique-se de que o modo de emissão baseado na configuração predefinido continua a ser permitido.

A AC subordinada pode estar numa região diferente do seu cluster, mas recomendamos vivamente que a crie na mesma região que o cluster para otimizar o desempenho. No entanto, pode criar as ACs raiz e subordinadas em diferentes regiões sem qualquer impacto no desempenho ou na disponibilidade.

Estas regiões são suportadas para o serviço de AC:

Nome da região Descrição da região
asia-east1 Taiwan
asia-east2 Hong Kong
asia-northeast1 Tóquio
asia-northeast2 Osaca
asia-northeast3 Seul
asia-south1 Mumbai
asia-south2 Deli
asia-southeast1 Singapura
asia-southeast2 Jacarta
australia-southeast1 Sydney
australia-southeast2 Melbourne
europe-central2 Varsóvia
europe-north1 Finlândia
europe-southwest1 Madrid
europe-west1 Bélgica
europe-west2 Londres
europe-west3 Frankfurt
europe-west4 Países Baixos
europe-west6 Zurique
europe-west8 Milão
europe-west9 Paris
europe-west10 Berlim
europe-west12 Turim
me-central1 Doha
me-central2 Damã
me-west1 Telavive
northamerica-northeast1 Montréal
northamerica-northeast2 Toronto
southamerica-east1 São Paulo
southamerica-west1 Santiago
us-central1 Iowa
us-east1 Carolina do Sul
us-east4 Virgínia do Norte
us-east5 Columbus
us-south1 Dallas
us-west1 Oregon
us-west2 Los Angeles
us-west3 Salt Lake City
us-west4 Las Vegas

Também pode verificar a lista de localizações suportadas executando o seguinte comando:

gcloud privateca locations list
  1. Conceda o IAM roles/privateca.caManager a indivíduos que criam um conjunto de ACs e uma AC. Tenha em atenção que, para MEMBER, o formato correto é user:userid@example.com. Se essa pessoa for o utilizador atual, pode obter o ID do utilizador atual com o comando de shell $(gcloud auth list --filter=status:ACTIVE --format="value(account)").

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.caManager
    
  2. Conceda a função role/privateca.admin para o serviço de AC a indivíduos que precisam de modificar as políticas de IAM, em que MEMBER é um indivíduo que precisa deste acesso, especificamente, todos os indivíduos que executam os passos que se seguem e que concedem as funções privateca.auditor e privateca.certificateManager:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.admin
    
  3. Crie o pool do serviço de AC de raiz.

    gcloud privateca pools create ROOT_CA_POOL_NAME \
      --location ROOT_CA_POOL_LOCATION \
      --tier enterprise
    
  4. Crie uma AC de raiz.

    gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \
      --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \
      --key-algorithm="ec-p256-sha256" \
      --max-chain-length=1 \
      --location ROOT_CA_POOL_LOCATION
    

    Para esta configuração de demonstração, use os seguintes valores para as variáveis:

    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_NAME=pkcs2-ca
    • ROOT_CA_POOL_LOCATION=us-east1
    • ROOT_CA_ORGANIZATION="TestCorpLLC"
  5. Crie o grupo subordinado e a CA subordinada. Certifique-se de que o modo de emissão baseado na configuração predefinido permanece permitido.

    gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --tier devops
    
    gcloud privateca subordinates create SUBORDINATE_CA_NAME \
      --pool SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --issuer-pool ROOT_CA_POOL_NAME \
      --issuer-location ROOT_CA_POOL_LOCATION \
      --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \
      --key-algorithm "ec-p256-sha256" \
      --use-preset-profile subordinate_mtls_pathlen_0
    

    Para esta configuração de demonstração, use os seguintes valores para as variáveis:

    • SUBORDINATE_CA_POOL_NAME="td-ca-pool"
    • SUBORDINATE_CA_POOL_LOCATION=us-east1
    • SUBORDINATE_CA_NAME="td-ca"
    • SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_POOL_LOCATION=us-east1
  6. Conceda a função privateca.auditor do IAM ao conjunto de ACs raiz para permitir o acesso a partir da conta de serviço do GKE:

    gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \
     --location ROOT_CA_POOL_LOCATION \
     --role roles/privateca.auditor \
     --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  7. Conceda a função de IAM privateca.certificateManager para o conjunto de ACs subordinado para permitir o acesso a partir da conta de serviço do GKE:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --role roles/privateca.certificateManager \
      --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  8. Guarde a seguinte configuração YAML para indicar ao cluster como emitir certificados de malha:WorkloadCertificateConfig

    apiVersion: security.cloud.google.com/v1
    kind: WorkloadCertificateConfig
    metadata:
      name: default
    spec:
      # Required. The CA service that issues your certificates.
      certificateAuthorityConfig:
        certificateAuthorityServiceConfig:
          endpointURI: ISSUING_CA_POOL_URI
    
      # Required. The key algorithm to use. Choice of RSA or ECDSA.
      #
      # To maximize compatibility with various TLS stacks, your workloads
      # should use keys of the same family as your root and subordinate CAs.
      #
      # To use RSA, specify configuration such as:
      #   keyAlgorithm:
      #     rsa:
      #       modulusSize: 4096
      #
      # Currently, the only supported ECDSA curves are "P256" and "P384", and the only
      # supported RSA modulus sizes are 2048, 3072 and 4096.
      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
      # Optional. Validity duration of issued certificates, in seconds.
      #
      # Defaults to 86400 (1 day) if not specified.
      validityDurationSeconds: 86400
    
      # Optional. Try to start rotating the certificate once this
      # percentage of validityDurationSeconds is remaining.
      #
      # Defaults to 50 if not specified.
      rotationWindowPercentage: 50
    
    

    Substitua o seguinte:

    • O ID do projeto no qual o cluster é executado:
      PROJECT_ID
    • O URI totalmente qualificado da CA que emite os certificados da malha (ISSUING_CA_POOL_URI). Pode ser a sua CA subordinada (recomendado) ou a sua CA de raiz. O formato é:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
  9. Guarde a seguinte configuração YAML TrustConfig para indicar ao cluster como confiar nos certificados emitidos:

    apiVersion: security.cloud.google.com/v1
    kind: TrustConfig
    metadata:
      name: default
    spec:
      # You must include a trustStores entry for the trust domain that
      # your cluster is enrolled in.
      trustStores:
      - trustDomain: PROJECT_ID.svc.id.goog
        # Trust identities in this trustDomain if they appear in a certificate
        # that chains up to this root CA.
        trustAnchors:
        - certificateAuthorityServiceURI: ROOT_CA_POOL_URI
    

    Substitua o seguinte:

    • O ID do projeto no qual o cluster é executado:
      PROJECT_ID
    • O URI totalmente qualificado do conjunto de ACs de raiz (ROOT_CA_POOL_URI). O formato é:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
  10. Aplique as configurações ao cluster:

    kubectl apply -f WorkloadCertificateConfig.yaml
    kubectl apply -f TrustConfig.yaml
    

Crie um serviço gRPC sem proxy com NEGs

Para a segurança do PSM, precisa de um servidor gRPC sem proxy capaz de usar o xDS para adquirir a configuração de segurança da malha de serviços na nuvem. Este passo é semelhante à configuração dos serviços GKE com NEGs no guia de configuração do equilíbrio de carga do PSM, mas usa o servidor helloworld ativado para xDS no exemplo xDS no grpc-javarepositório, em vez da imagem java-example-hostname.

Cria e executa este servidor num contentor criado a partir de uma imagem openjdk:8-jdk. Também usa a funcionalidade NEG com nome, que lhe permite especificar um nome para o NEG. Isto simplifica os passos posteriores porque a implementação conhece o nome do NEG sem ter de o procurar.

Segue-se um exemplo completo da especificação do Kubernetes do servidor gRPC. Tenha em atenção o seguinte:

  • A especificação cria uma conta de serviço do Kubernetes example-grpc-server que é usada pelo pod do servidor gRPC.
  • A especificação usa o campo name na anotação cloud.google.com/neg do serviço para especificar o nome do NEG example-grpc-server.
  • A variável ${PROJNUM} representa o número do projeto.
  • A especificação usa a secção initContainers para executar um gerador de arranque para preencher o ficheiro de arranque de que a biblioteca gRPC sem proxy precisa. Este ficheiro de arranque reside em /tmp/grpc-xds/td-grpc-bootstrap.json no contentor do servidor gRPC denominado example-grpc-server.

Adicione a seguinte anotação à especificação do pod:

 annotations:
   security.cloud.google.com/use-workload-certificates: ""

Pode ver o posicionamento correto na especificação completa que se segue.

Na criação, cada agrupamento recebe um volume de /var/run/secrets/workload-spiffe-credentials. Este volume contém o seguinte:

  • private_key.pem é uma chave privada gerada automaticamente.
  • certificates.pem é um pacote de certificados formatados em PEM que podem ser apresentados a outro pod como a cadeia de certificados de cliente ou usados como uma cadeia de certificados de servidor.
  • ca_certificates.pem é um pacote de certificados formatados em PEM a usar como âncoras de confiança ao validar a cadeia de certificados de cliente apresentada por outro pod ou a cadeia de certificados de servidor recebida quando se liga a outro pod.

Tenha em atenção que ca_certificates.pem contém certificados para o domínio de confiança local para as cargas de trabalho, que é o conjunto de cargas de trabalho do cluster.

O certificado de folha em certificates.pem contém a seguinte declaração de identidade SPIFFE de texto simples:

spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT

Nesta afirmação:

  • WORKLOAD_POOL é o nome do pool de cargas de trabalho do cluster.
  • NAMESPACE é o espaço de nomes da sua conta de serviço do Kubernetes.
  • KUBERNETES_SERVICE_ACCOUNT é o nome da sua conta de serviço do Kubernetes.

As seguintes instruções para o seu idioma criam a especificação a usar neste exemplo.

Java

  1. Execute o seguinte comando para garantir que o número do projeto está definido corretamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a especificação:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: openjdk:8-jdk
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 800m
               memory: 512Mi
             requests:
               cpu: 100m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

C++

  1. Execute o seguinte comando para garantir que o número do projeto está definido corretamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a especificação:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: phusion/baseimage:18.04-1.0.0
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

Python

  1. Execute o seguinte comando para garantir que o número do projeto está definido corretamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a especificação:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: phusion/baseimage:18.04-1.0.0
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

Ir

  1. Execute o seguinte comando para garantir que o número do projeto está definido corretamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a especificação:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: golang:1.16-alpine
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

    Conclua o processo da seguinte forma.

  1. Aplique a especificação:

    kubectl apply -f example-grpc-server.yaml
    
  2. Conceda as funções necessárias à conta de serviço:

    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \
      ${PROJNUM}-compute@developer.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \
      --role roles/trafficdirector.client
    
  3. Execute estes comandos para verificar se o serviço e o pod foram criados corretamente:

    kubectl get deploy/example-grpc-server
    kubectl get svc/example-grpc-server
    
  4. Verifique se o nome do NEG está correto:

    gcloud compute network-endpoint-groups list \
        --filter "name=example-grpc-server" --format "value(name)"
    

    O comando deve devolver o nome do NEG example-grpc-server.

Configure o Cloud Service Mesh com Google Cloud componentes de equilíbrio de carga

Os passos nesta secção são semelhantes aos da secção Configurar a Cloud Service Mesh com componentes de equilíbrio de carga, mas existem algumas alterações, conforme descrito nas secções seguintes.

Crie a verificação de funcionamento, a regra de firewall e o serviço de back-end

Quando o servidor gRPC está configurado para usar mTLS, as verificações de funcionamento do gRPC não funcionam porque o cliente de verificação de funcionamento não consegue apresentar um certificado de cliente válido aos servidores. Pode resolver esta situação de duas formas.

Na primeira abordagem, o servidor cria uma porta de publicação adicional designada como a porta de verificação do estado. Isto está anexado a um serviço de verificação de estado especial, como texto simples ou TLS para essa porta.

O helloworld servidor de exemplo xDS usa PORT_NUMBER + 1 como a porta de verificação de funcionamento de texto simples. O exemplo usa 50052 como a porta de verificação de funcionamento porque 50051 é a porta do servidor de aplicações gRPC.

Na segunda abordagem, configura a verificação de estado de funcionamento para verificar apenas a conetividade TCP à porta de publicação da aplicação. Esta verificação apenas verifica a conetividade e também gera tráfego desnecessário para o servidor quando existem negociações de TLS sem êxito. Por este motivo, recomendamos que use a primeira abordagem.

  1. Crie a verificação de funcionamento. Tenha em atenção que a verificação de funcionamento só é iniciada depois de criar e iniciar o servidor.

    • Se estiver a criar uma porta de publicação designada para a verificação de funcionamento, que é a abordagem que recomendamos, use este comando:

      gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
       --enable-logging --port 50052
      
    • Se estiver a criar uma verificação de funcionamento de TCP, o que não recomendamos, use este comando:

      gcloud compute health-checks create tcp grpc-gke-helloworld-hc \
      --use-serving-port
      
  2. Crie a firewall. Certifique-se de que o valor de --target-tags corresponde ao valor que indicou para --tags na secção Crie ou atualize um cluster do GKE.

    gcloud compute firewall-rules create grpc-gke-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051-50052
    
  3. Crie o serviço de back-end:

    gcloud compute backend-services create grpc-gke-helloworld-service \
       --global \
       --load-balancing-scheme=INTERNAL_SELF_MANAGED \
       --protocol=GRPC \
       --health-checks grpc-gke-helloworld-hc
    
  4. Associe o NEG ao serviço de back-end:

    gcloud compute backend-services add-backend grpc-gke-helloworld-service \
       --global \
       --network-endpoint-group example-grpc-server \
       --network-endpoint-group-zone ${ZONE} \
       --balancing-mode RATE \
       --max-rate-per-endpoint 5
    

Crie os recursos Mesh e GRPCRoute

Isto é semelhante à forma como configura os recursos Mesh e GRPCRoute em Configure serviços gRPC sem proxy.

  1. Crie a especificação Mesh e guarde-a num ficheiro denominado mesh.yaml.

    name: grpc-mesh
    
  2. Importe o recurso Mesh da especificação.

    gcloud network-services meshes import grpc-mesh \
      --source=mesh.yaml \
      --location=global
    
  3. Crie a especificação GRPCRoute e guarde-a num ficheiro denominado grpc_route.yaml.

    name: helloworld-grpc-route
    hostnames:
    - helloworld-gke:8000
    meshes:
    - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
    
  4. Importe o recurso GRPCRoute da especificação grpc_route.yaml.

    gcloud network-services grpc-routes import helloworld-grpc-route \
      --source=grpc_route.yaml \
      --location=global
    

Configure o Cloud Service Mesh com a segurança gRPC sem proxy

Este exemplo demonstra como configurar o mTLS nos lados do cliente e do servidor.

Formato para referências de políticas

Tenha em atenção o seguinte formato necessário para fazer referência às políticas de TLS do servidor e de TLS do cliente:

projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies]/[server-tls-policy|client-mtls-policy]

Por exemplo:

projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy

Configure o mTLS do lado do servidor

Primeiro, crie uma política de TLS do servidor. A política pede ao lado do servidor gRPC para usar a configuração do plug-in certificateProvicerInstance identificada pelo nome google_cloud_private_spiffe para o certificado de identidade, que faz parte do serverCertificate. A secção mtlsPolicy indica a segurança mTLS e usa o mesmo google_cloud_private_spiffe que a configuração do plug-in para clientValidationCa, que é a especificação do certificado de raiz (validação).

Em seguida, crie uma política de pontos finais. Isto especifica que um back-end, por exemplo, um servidor gRPC, que usa a porta 50051 com quaisquer ou nenhumas etiquetas de metadados, recebe a política TLS do servidor anexada denominada server-mtls-policy. Especifica etiquetas de metadados com MATCH_ALL ou um valor compatível. Pode encontrar as etiquetas de metadados suportadas no campo endpointMatcher.metadataLabelMatcher.metadataLabelMatchCriteria no documento NetworkServicesEndpointPolicy. Cria a política de ponto final com um ficheiro temporário ep-mtls-psms.yaml que contém os valores para o recurso da política de ponto final usando a política que já definiu.

  1. Crie um ficheiro temporário server-mtls-policy.yaml no diretório atual com os valores do recurso de política de TLS do servidor:

    name: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    mtlsPolicy:
      clientValidationCa:
      - certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
    
  2. Crie um recurso de política TLS do servidor denominado server-mtls-policy importando o ficheiro temporário server-mtls-policy.yaml:

    gcloud network-security server-tls-policies import server-mtls-policy \
      --source=server-mtls-policy.yaml --location=global
    
  3. Crie a política de pontos finais criando o ficheiro temporário ep-mtls-psms.yaml:

    name: "ep-mtls-psms"
    type: "GRPC_SERVER"
    serverTlsPolicy: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy"
    trafficPortSelector:
      ports:
      - "50051"
    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: "MATCH_ALL"
        metadataLabels:
        - labelName: app
          labelValue: helloworld
    
  4. Crie o recurso de política de pontos finais importando o ficheiro ep-mtls-psms.yaml:

    gcloud beta network-services endpoint-policies import ep-mtls-psms \
      --source=ep-mtls-psms.yaml --location=global
    

Configure o mTLS do lado do cliente

A política de segurança do lado do cliente está anexada ao serviço de back-end. Quando um cliente acede a um back-end (o servidor gRPC) através do serviço de back-end, a política de segurança do lado do cliente anexada é enviada para o cliente.

  1. Crie o conteúdo do recurso da política TLS do cliente num ficheiro temporário denominado client-mtls-policy.yaml no diretório atual:

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Crie o recurso de política TLS do cliente denominado client-mtls-policy importando o ficheiro temporário client-mtls-policy.yaml:

    gcloud network-security client-tls-policies import client-mtls-policy \
      --source=client-mtls-policy.yaml --location=global
    
  3. Crie um fragmento num ficheiro temporário para fazer referência a esta política e adicione detalhes para subjectAltNames na mensagem SecuritySettings, como no exemplo seguinte. Substitua ${PROJECT_ID} pelo valor do ID do projeto, que é o valor da variável de ambiente ${PROJECT_ID} descrita anteriormente. Tenha em atenção que example-grpc-server em subjectAltNames é o nome da conta de serviço do Kubernetes que é usado para o pod do servidor gRPC na especificação de implementação.

    if [ -z "$PROJECT_ID" ] ; then echo Please make sure PROJECT_ID is set. ; fi
    cat << EOF > client-security-settings.yaml
    securitySettings:
      clientTlsPolicy: projects/${PROJECT_ID}/locations/global/clientTlsPolicies/client-mtls-policy
      subjectAltNames:
        - "spiffe://${PROJECT_ID}.svc.id.goog/ns/default/sa/example-grpc-server"
    EOF
    
  4. Adicione a mensagem securitySettings ao serviço de back-end que já criou. Estes passos exportam o conteúdo do serviço de back-end atual, adicionam a mensagem securitySetting do cliente e reimportam o novo conteúdo para atualizar o serviço de back-end.

    gcloud compute backend-services export grpc-gke-helloworld-service --global \
      --destination=/tmp/grpc-gke-helloworld-service.yaml
    
    cat /tmp/grpc-gke-helloworld-service.yaml client-security-settings.yaml \
      >/tmp/grpc-gke-helloworld-service1.yaml
    
    gcloud compute backend-services import grpc-gke-helloworld-service --global \
      --source=/tmp/grpc-gke-helloworld-service1.yaml -q
    

Valide a configuração

A configuração da Cloud Service Mesh está agora concluída, incluindo a segurança do lado do servidor e do cliente. Em seguida, prepara e executa as cargas de trabalho do servidor e do cliente. Isto conclui o exemplo.

Crie um cliente gRPC sem proxy

Este passo é semelhante ao passo anterior Criar um serviço gRPC sem proxy. Usa o cliente helloworld com xDS do diretório de exemplo do xDS no repositório grpc-java. Cria e executa o cliente num contentor criado a partir de uma imagem do openjdk:8-jdk. A especificação do Kubernetes do cliente gRPC faz o seguinte:

  • Cria uma conta de serviço do Kubernetes example-grpc-client que é usada pelo pod do cliente gRPC.
  • ${PROJNUM} representa o número do projeto e tem de ser substituído pelo número real.

Adicione a seguinte anotação à especificação do pod:

  annotations:
    security.cloud.google.com/use-workload-certificates: ""

Na criação, cada agrupamento recebe um volume de /var/run/secrets/workload-spiffe-credentials. Este volume contém o seguinte:

  • private_key.pem é uma chave privada gerada automaticamente.
  • certificates.pem é um pacote de certificados formatados em PEM que podem ser apresentados a outro pod como a cadeia de certificados de cliente ou usados como uma cadeia de certificados de servidor.
  • ca_certificates.pem é um pacote de certificados formatados em PEM a usar como âncoras de confiança ao validar a cadeia de certificados de cliente apresentada por outro pod ou a cadeia de certificados de servidor recebida quando se liga a outro pod.

Tenha em atenção que ca_certificates.pem contém os certificados de raiz para o domínio de confiança local para as cargas de trabalho, que é o conjunto de cargas de trabalho do cluster.

O certificado de folha em certificates.pem contém a seguinte declaração de identidade SPIFFE de texto simples:

spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT

Nesta afirmação:

  • WORKLOAD_POOL é o nome do pool de cargas de trabalho do cluster.
  • NAMESPACE é o nome da sua conta de serviço do Kubernetes.
  • KUBERNETES_SERVICE_ACCOUNT é o espaço de nomes da sua conta de serviço do Kubernetes.

As seguintes instruções para o seu idioma criam a especificação a usar neste exemplo.

Java

  1. Execute o seguinte comando para garantir que o número do projeto está definido corretamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a seguinte especificação:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: openjdk:8-jdk
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 800m
                memory: 512Mi
              requests:
                cpu: 100m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

C++

  1. Execute o seguinte comando para garantir que o número do projeto está definido corretamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a seguinte especificação:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: phusion/baseimage:18.04-1.0.0
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Python

  1. Execute o seguinte comando para garantir que o número do projeto está corretamente definido:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a seguinte especificação:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: phusion/baseimage:18.04-1.0.0
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Ir

  1. Execute o seguinte comando para garantir que o número do projeto está corretamente definido:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crie a seguinte especificação:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: golang:1.16-alpine
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Conclua o processo da seguinte forma.

  1. Aplique a especificação:

    kubectl apply -f example-grpc-client.yaml
    
  2. Conceda as funções necessárias à conta de serviço:

    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \
      ${PROJNUM}-compute@developer.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \
      --role roles/trafficdirector.client
    
  3. Verifique se o pod do cliente está em execução:

    kubectl get pods
    

    O comando devolve texto semelhante ao seguinte:

    NAMESPACE   NAME                                    READY   STATUS    RESTARTS   AGE
    default     example-grpc-client-7c969bb997-9fzjv    1/1     Running   0          104s
    [..skip..]
    

Execute o servidor

Crie e execute o servidor helloworld com a funcionalidade xDS no pod do servidor que criou anteriormente.

Java

  1. Obtenha o nome do pod criado para o serviço example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Vê feedback como o seguinte:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. Na shell, verifique se o ficheiro de arranque em /tmp/grpc-xds/td-grpc-bootstrap.json corresponde ao esquema descrito na secção Ficheiro de arranque.

  4. Transfira a versão 1.42.1 do gRPC Java e crie a aplicação de servidor xds-hello-world.

    curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz
    
    cd grpc-java-1.42.1/examples/example-xds
    
    ../gradlew --no-daemon installDist
    
  5. Execute o servidor com a flag --xds-creds para indicar a segurança ativada para xDS, usando 50051 como a porta de escuta e xds-server como o nome de identificação do servidor:

    ./build/install/example-xds/bin/xds-hello-world-server --xds-creds 50051 xds-server
    
  6. Depois de o servidor obter a configuração necessária do Cloud Service Mesh, vê o seguinte resultado:

    Listening on port 50051
    plain text health service listening on port 50052
    

C++

  1. Obtenha o nome do pod criado para o serviço example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Vê feedback como o seguinte:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. Na shell, verifique se o ficheiro de arranque em /tmp/grpc-xds/td-grpc-bootstrap.json corresponde ao esquema descrito na secção Ficheiro de arranque.

  4. Transfira o gRPC C++ e crie a aplicação de servidor xds-hello-world.

    apt-get update -y && \
            apt-get install -y \
                build-essential \
                clang \
                python3 \
                python3-dev
    
    curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
    
    cd grpc-master
    
    tools/bazel build examples/cpp/helloworld:xds_greeter_server
    
  5. Execute o servidor com 50051 como porta de escuta e xds_greeter_server como nome de identificação do servidor:

    bazel-bin/examples/cpp/helloworld/xds_greeter_server --port=50051 --maintenance_port=50052 --secure
    

    Para executar o servidor sem credenciais, pode especificar o seguinte:

    bazel-bin/examples/cpp/helloworld/xds_greeter_server --nosecure
    
  6. Depois de o servidor obter a configuração necessária do Cloud Service Mesh, vê o seguinte resultado:

    Listening on port 50051
    plain text health service listening on port 50052
    

Python

  1. Obtenha o nome do pod criado para o serviço example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Vê feedback como o seguinte:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. Na shell, verifique se o ficheiro de arranque em /tmp/grpc-xds/td-grpc-bootstrap.json corresponde ao esquema descrito na secção Ficheiro de arranque.

  4. Transfira a versão 1.41.0 do gRPC Python e crie a aplicação de exemplo.

    apt-get update -y
    
    apt-get install -y python3 python3-pip
    
    curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
    
    cd grpc-1.41.x/examples/python/xds/
    
    python3 -m virtualenv venv
    
    source venv/bin/activate
    
    python3 -m pip install -r requirements.txt
    

  5. Execute o servidor com a flag --xds-creds para indicar a segurança ativada para xDS, usando 50051 como porta de deteção.

    python3 server.py 50051 --xds-creds
    
  6. Depois de o servidor obter a configuração necessária do Cloud Service Mesh, vê o seguinte resultado:

    2021-05-06 16:10:34,042: INFO     Running with xDS Server credentials
    2021-05-06 16:10:34,043: INFO     Greeter server listening on port 50051
    2021-05-06 16:10:34,046: INFO     Maintenance server listening on port 50052
    

Ir

  1. Obtenha o nome do pod criado para o serviço example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Vê feedback como o seguinte:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
    
  3. Na shell, verifique se o ficheiro de arranque em /tmp/grpc-xds/td-grpc-bootstrap.json corresponde ao esquema descrito na secção Ficheiro de arranque.

  4. Transfira a versão 1.41.0 do gRPC Go e navegue para o diretório que contém a aplicação de servidor xds-hello-world.

    apk add curl
    
    curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz
    
    cd grpc-go-1.42.0/examples/features/xds/server
    
    
  5. Crie e execute o servidor com a flag --xds_creds para indicar a segurança ativada para xDS, usando 50051 como porta de escuta:

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -port 50051
    
  6. Depois de o servidor obter a configuração necessária do Cloud Service Mesh, vê o seguinte resultado:

    Using xDS credentials...
    Serving GreeterService on 0.0.0.0:50051 and HealthService on 0.0.0.0:50052
    

O processo de verificação de funcionamento demora entre 3 e 5 minutos a mostrar que o seu serviço está em bom estado após o início do servidor.

Execute o cliente e valide a configuração

Crie e execute o cliente com xDS ativado no pod do cliente que criou anteriormente.helloworld

Java

  1. Obtenha o nome do pod do cliente:

    kubectl get pods | grep example-grpc-client
    

    Vê feedback como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Na shell de comandos, transfira a versão 1.42.1 do gRPC Java e crie a aplicação cliente xds-hello-world.

    curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz
    
    cd grpc-java-1.42.1/examples/example-xds
    
    ../gradlew --no-daemon installDist
    
  4. Execute o cliente com a flag --xds-creds para indicar a segurança ativada para xDS, o nome do cliente e a string de ligação de destino:

    ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \
          xds:///helloworld-gke:8000
    

    Deverá ver uma saída semelhante a esta:

    Greeting: Hello xds-client, from xds-server
    

C++

  1. Obtenha o nome do pod do cliente:

    kubectl get pods | grep example-grpc-client
    

    Vê feedback como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Depois de estar no shell, transfira o gRPC C++ e crie a aplicação cliente xds-hello-world.

    apt-get update -y && \
            apt-get install -y \
                build-essential \
                clang \
                python3 \
                python3-dev
    
    curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
    
    cd grpc-master
    
    tools/bazel build examples/cpp/helloworld:xds_greeter_client
    
  4. Execute o cliente com a flag --xds-creds para indicar a segurança ativada para xDS, o nome do cliente e a string de ligação de destino:

    bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000
    

    Para executar o cliente sem credenciais, use o seguinte:

    bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000 --nosecure
    

    Deverá ver uma saída semelhante a esta:

    Greeter received: Hello world
    

Python

  1. Obtenha o nome do pod do cliente:

    kubectl get pods | grep example-grpc-client
    

    Vê feedback como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Depois de estar no shell, transfira a versão 1.41.0 do gRPC Python e crie a aplicação cliente de exemplo.

    apt-get update -y
    apt-get install -y python3 python3-pip
    python3 -m pip install virtualenv
    curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
    cd grpc-1.41.x/examples/python/xds/
    python3 -m virtualenv venv
    source venv/bin/activate
    python3 -m pip install -r requirements.txt
    
  4. Execute o cliente com a flag --xds-creds para indicar a segurança ativada para xDS, o nome do cliente e a string de ligação de destino:

    python3 client.py xds:///helloworld-gke:8000 --xds-creds
    

    Deverá ver uma saída semelhante a esta:

    Greeter client received: Hello you from example-host!
    

Ir

  1. Obtenha o nome do pod do cliente:

    kubectl get pods | grep example-grpc-client
    

    Vê feedback como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abra uma shell para o pod do cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
    
  3. Depois de estar na shell, transfira a versão 1.42.0 do gRPC Go e navegue para o diretório que contém a aplicação cliente xds-hello-world.

    apk add curl
    
    curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz
    
    cd grpc-go-1.42.0/examples/features/xds/client
    
  4. Crie e execute o cliente com a flag --xds_creds para indicar a segurança ativada para xDS, o nome do cliente e a string de ligação de destino:

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke:8000
    

    Deverá ver uma saída semelhante a esta:

    Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
    

Configure o acesso ao nível do serviço com uma política de autorização

O suporte do gRFC A41 é necessário para o suporte da política de autorização. Pode encontrar as versões de idioma necessárias no github

Use estas instruções para configurar o acesso ao nível do serviço com políticas de autorização. Antes de criar políticas de autorização, leia o aviso em Restrinja o acesso através da autorização.

Para facilitar a validação da configuração, crie um nome de anfitrião adicional que o cliente possa usar para se referir ao serviço helloworld-gke.

  1. Atualize a especificação GRPCRoute armazenada anteriormente em grpc_route.yaml

    name: helloworld-grpc-route
    hostnames:
    - helloworld-gke:8000
    - helloworld-gke-noaccess:8000
    meshes:
    - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
    
  2. Importe novamente o recurso GRPCRoute da especificação grpc_route.yaml.

    gcloud network-services grpc-routes import helloworld-grpc-route \
      --source=grpc_route.yaml \
      --location=global
    

As instruções seguintes criam uma política de autorização que permite pedidos enviados pela conta example-grpc-client na qual o nome do anfitrião é helloworld-gke:8000 e a porta é 50051.

gcloud

  1. Crie uma política de autorização criando um ficheiro denominado helloworld-gke-authz-policy.yaml.

    action: ALLOW
    name: helloworld-gke-authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/default/sa/example-grpc-client
      destinations:
      - hosts:
        - helloworld-gke:8000
        ports:
        - 50051
    
  2. Importe a política.

    gcloud network-security authorization-policies import \
      helloworld-gke-authz-policy \
      --source=helloworld-gke-authz-policy.yaml \
      --location=global
    
  3. Atualize a política de ponto final para fazer referência à nova política de autorização acrescentando o seguinte ao ficheiro ep-mtls-psms.yaml.

    authorizationPolicy: projects/${PROJECT_ID}/locations/global/authorizationPolicies/helloworld-gke-authz-policy
    

    A política de pontos finais especifica agora que o mTLS e a política de autorização têm de ser aplicados a pedidos recebidos para pods cujos ficheiros de arranque gRPC contenham a etiqueta app:helloworld.

  4. Importe a política:

    gcloud network-services endpoint-policies import ep-mtls-psms \
      --source=ep-mtls-psms.yaml --location=global
    

Valide a política de autorização

Siga estas instruções para confirmar se a política de autorização está a funcionar corretamente.

Java

  1. Abra uma shell para o pod do cliente que usou anteriormente.

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. Na shell de comandos, execute os seguintes comandos para validar a configuração.

    cd grpc-java-1.42.1/examples/example-xds
    ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \
          xds:///helloworld-gke:8000
    

    Deverá ver uma saída semelhante a esta:

    Greeting: Hello xds-client, from xds-server
    
  3. Execute o cliente novamente com o nome do servidor alternativo. Tenha em atenção que este é um caso de falha. O pedido é inválido porque a política de autorização só permite o acesso ao nome do anfitrião helloworld-gke:8000.

    ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \
          xds:///helloworld-gke-noaccess:8000
    

    Deverá ver uma saída semelhante a esta:

    WARNING: RPC failed: Status{code=PERMISSION_DENIED}
    

    Se não vir este resultado, a política de autorização pode ainda não estar em uso. Aguarde alguns minutos e tente novamente todo o processo de validação.

Ir

  1. Abra uma shell para o pod do cliente que usou anteriormente.

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. Na shell de comandos, execute os seguintes comandos para validar a configuração.

    cd grpc-go-1.42.0/examples/features/xds/client
    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke:8000
    

    Deverá ver uma saída semelhante a esta:

    Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
    
  3. Execute o cliente novamente com o nome do servidor alternativo. Tenha em atenção que este é um caso de falha. O pedido é inválido porque a política de autorização só permite o acesso ao nome do anfitrião helloworld-gke:8000.

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke-noaccess:8000
    

    Deverá ver uma saída semelhante a esta:

    could not greet: rpc error: code = PermissionDenied desc = Incoming RPC is not allowed: rpc error: code = PermissionDenied desc = incoming RPC did not match an allow policy
    exit status 1
    

    Se não vir este resultado, a política de autorização pode ainda não estar em uso. Aguarde alguns minutos e tente novamente todo o processo de validação.

Use TLS em vez de mTLS

A utilização do TLS neste exemplo requer apenas uma pequena alteração.

  1. No ServerTlsPolicy, deixe cair o mtlsPolicy:

    cat << EOF > server-tls-policy.yaml
    name: "server-tls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    EOF
    
  2. Em alternativa, use esta política no EndpointPolicy:

    cat << EOF > ep-tls-psms.yaml
    name: "ep-mtls-psms"
    type: "GRPC_SERVER"
    serverTlsPolicy: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-tls-policy"
    trafficPortSelector:
      ports:
      - "50051"
    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: "MATCH_ALL"
        metadataLabels: []
    EOF
    
  3. O ClientTlsPolicy para mTLS também funciona no caso do TLS, mas a secção clientCertificate da política pode ser ignorada, uma vez que não é necessária para o TLS:

    cat << EOF > client-tls-policy.yaml
    name: "client-tls-policy"
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    EOF
    

Use a segurança de serviços com o exemplo da Carteira

Esta secção oferece uma vista geral de como ativar o exemplo da Carteira com segurança do serviço para Java, C++ e Go.

Java

Pode encontrar o código-fonte de exemplo para Java no github. O código já usa as credenciais XdsChannel e XdsServer quando configura a segurança sem proxy.

Estas instruções descrevem a configuração do exemplo da Carteira com Go. O processo é semelhante para Java. As instruções usam uma imagem do Docker pré-existente que obtém do Google Cloud repositório de contentores.

Para criar o exemplo, siga estas instruções:

  1. Clone o repositório e obtenha os ficheiros no diretório gRPC examples.
  2. Edite o ficheiro 00-common-env.sh. Comente a linha existente que define o valor de WALLET_DOCKER_IMAGE para a imagem do Docker do Go e descomente a linha que define o valor de WALLET_DOCKER_IMAGE para a imagem do Docker do Java.
  3. Crie e configure instâncias do Cloud Router através das instruções em Crie e configure instâncias do Cloud Router ou através da função create_cloud_router_instances no script 10.apis.sh.
  4. Crie um cluster através das instruções do exemplo hello world. ou da função create_cluster no script 20-cluster.sh.
  5. Crie autoridades de certificação privadas através das instruções para o serviço de AC ou através do script 30-private-ca-setup.sh.
  6. Crie recursos do Kubernetes, incluindo contas de serviço, namespaces, serviços do Kubernetes, NEGs e implementação do lado do servidor para todos os serviços: account, stats, stats_premium, wallet_v1 e wallet_v2, através do script 40-k8s-resources.sh.
  7. Para cada um dos serviços que criou, crie uma verificação de funcionamento e um serviço de back-end usando create_health_check e create_backend_service no script 50-td-components.sh.
  8. Crie os componentes de encaminhamento da Cloud Service Mesh com create_routing_components no script 60-routing-components.sh.
  9. Crie os componentes de segurança da Cloud Service Mesh para cada serviço de back-end usando create_security_components no script 70-security-components.sh.
  10. Crie a implementação do cliente do Wallet com create_client_deployment no script 75-client-deployment.sh.
  11. Valide a configuração iniciando o seu cliente conforme descrito em Valide com clientes grpc-wallet.

C++

Pode encontrar o código fonte de exemplo para C++ no github. O código já usa credenciais de XdsChannel e XdsServer quando configura a segurança sem proxy.

Estas instruções descrevem a configuração do exemplo da Carteira com Go. O processo é semelhante para C++. As instruções usam uma imagem Docker pré-existente que obtém do Google Cloud repositório de contentores.

Para criar o exemplo, siga estas instruções:

  1. Clone o repositório e obtenha os ficheiros no diretório gRPC examples.
  2. Edite o ficheiro 00-common-env.sh. Comente a linha existente que define o valor de WALLET_DOCKER_IMAGE para a imagem do Docker do Go e descomente a linha que define o valor de WALLET_DOCKER_IMAGE para a imagem do Docker do C++.
  3. Crie e configure instâncias do Cloud Router através das instruções em Crie e configure instâncias do Cloud Router ou através da função create_cloud_router_instances no script 10.apis.sh.
  4. Crie um cluster através das instruções do exemplo hello world. ou da função create_cluster no script 20-cluster.sh.
  5. Crie autoridades de certificação privadas através das instruções para o serviço de AC ou através do script 30-private-ca-setup.sh.
  6. Crie recursos do Kubernetes, incluindo contas de serviço, namespaces, serviços do Kubernetes, NEGs e implementação do lado do servidor para todos os serviços: account, stats, stats_premium, wallet_v1 e wallet_v2, através do script 40-k8s-resources.sh.
  7. Para cada um dos serviços que criou, crie uma verificação de funcionamento e um serviço de back-end usando create_health_check e create_backend_service no script 50-td-components.sh.
  8. Crie os componentes de encaminhamento da Cloud Service Mesh com create_routing_components no script 60-routing-components.sh.
  9. Crie os componentes de segurança da Cloud Service Mesh para cada serviço de back-end usando create_security_components no script 70-security-components.sh.
  10. Crie a implementação do cliente do Wallet com create_client_deployment no script 75-client-deployment.sh.
  11. Valide a configuração iniciando o seu cliente conforme descrito em Valide com clientes grpc-wallet.

Ir

Pode encontrar um exemplo de código fonte para Go no github. O código já usa credenciais XdsChannel eXdsServer quando configura a segurança sem proxy.

As instruções usam uma imagem do Docker pré-existente que obtém do Google Cloud repositório de contentores.

Para criar o exemplo, siga estas instruções:

  1. Clone o repositório e obtenha os ficheiros no diretório gRPC examples.
  2. Edite o ficheiro 00-common-env.sh para definir os valores corretos para as variáveis de ambiente.
  3. Crie e configure instâncias do Cloud Router através das instruções em Crie e configure instâncias do Cloud Router ou através da função create_cloud_router_instances no script 10.apis.sh.
  4. Crie um cluster através das instruções do exemplo hello world. ou da função create_cluster no script 20-cluster.sh.
  5. Crie autoridades de certificação privadas através das instruções para o serviço de AC ou através do script 30-private-ca-setup.sh.
  6. Crie recursos do Kubernetes, incluindo contas de serviço, namespaces, serviços do Kubernetes, NEGs e implementação do lado do servidor para todos os serviços: account, stats, stats_premium, wallet_v1 e wallet_v2, através do script 40-k8s-resources.sh.
  7. Para cada um dos serviços que criou, crie uma verificação de funcionamento e um serviço de back-end usando create_health_check e create_backend_service no script 50-td-components.sh.
  8. Crie os componentes de encaminhamento da Cloud Service Mesh com create_routing_components no script 60-routing-components.sh.
  9. Crie os componentes de segurança da Cloud Service Mesh para cada serviço de back-end usando create_security_components no script 70-security-components.sh.
  10. Crie a implementação do cliente do Wallet com create_client_deployment no script 75-client-deployment.sh.
  11. Valide a configuração iniciando o seu cliente conforme descrito em Valide com clientes grpc-wallet.

Ficheiro de arranque

O processo de configuração neste guia usa um gerador de bootstrap para criar o ficheiro de bootstrap necessário. Esta secção fornece informações de referência sobre o próprio ficheiro de arranque.

O ficheiro de arranque contém informações de configuração necessárias para o código gRPC sem proxy, incluindo informações de ligação para o servidor xDS. O ficheiro de arranque contém uma configuração de segurança exigida pela funcionalidade de segurança gRPC sem proxy. O servidor gRPC requer um campo adicional. Um ficheiro de arranque de amostra tem o seguinte aspeto:

{
  "xds_servers": [
    {
      "server_uri": "trafficdirector.googleapis.com:443",
      "channel_creds": [
        {
          "type": "google_default"
        }
      ],
      "server_features": [
        "xds_v3"
      ]
    }
  ],
  "authorities": {
    "traffic-director-c2p.xds.googleapis.com": {
      "xds_servers": [
        {
          "server_uri": "dns:///directpath-pa.googleapis.com",
          "channel_creds": [
            {
              "type": "google_default"
            }
          ],
          "server_features": [
            "xds_v3",
            "ignore_resource_deletion"
          ]
        }
      ],
      "client_listener_resource_name_template": "xdstp://traffic-director-c2p.xds.googleapis.com/envoy.config.listener.v3.Listener/%s"
    }
  },
  "node": {
    "id": "projects/9876012345/networks/mesh:grpc-mesh/nodes/b59f49cc-d95a-4462-9126-112f794d5dd3",
    "cluster": "cluster",
    "metadata": {
      "INSTANCE_IP": "10.28.2.8",
      "TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE": true,
      "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER": "223606568246",
      "TRAFFICDIRECTOR_NETWORK_NAME": "default",
      "app": "helloworld"
    },
    "locality": {
      "zone": "us-central1-c"
    }
  },
  "certificate_providers": {
    "google_cloud_private_spiffe": {
      "plugin_name": "file_watcher",
      "config": {
        "certificate_file": "/var/run/secrets/workload-spiffe-credentials/certificates.pem",
        "private_key_file": "/var/run/secrets/workload-spiffe-credentials/private_key.pem",
        "ca_certificate_file": "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem",
        "refresh_interval": "600s"
      }
    }
  },
  "server_listener_resource_name_template": "grpc/server?xds.resource.listening_address=%s"
}

Atualizações ao ficheiro de arranque para o serviço de segurança

Os seguintes campos refletem modificações relacionadas com a segurança e a utilização do xDS v3:

O campo id no interior de node fornece uma identidade exclusiva para o cliente gRPC para o Cloud Service Mesh. Tem de fornecer o Google Cloud número do projeto e o nome da rede através do ID do nó neste formato:

projects/{project number}/networks/{network name}/nodes/[UNIQUE_ID]

Um exemplo para o número do projeto 1234 e a rede predefinida é:

projects/1234/networks/default/nodes/client1

O campo INSTANCE_IP é o endereço IP do pod ou 0.0.0.0 para indicar INADDR_ANY. Este campo é usado pelo servidor gRPC para obter o recurso Listener do Cloud Service Mesh para segurança do lado do servidor.

Campos de configuração de segurança no ficheiro de arranque

Chave JSON Tipo Valor Notas
server_listener_resource_name_template String grpc/server?xds.resource.listening_address=%s Obrigatório para servidores gRPC. O gRPC usa este valor para compor o nome do recurso para obter o recurso "Listener" da Cloud Service Mesh para segurança do lado do servidor e outra configuração. O gRPC usa isto para formar a string do nome do recurso
certificate_providers Estrutura JSON google_cloud_private_spiffe Obrigatório. O valor é uma estrutura JSON que representa um mapa de nomes para instâncias de fornecedores de certificados. Uma instância do fornecedor de certificados é usada para obter certificados de identidade e raiz. O ficheiro de arranque de exemplo contém um nome: google_cloud_private_spiffe com a estrutura JSON da instância do fornecedor de certificados como valor. Cada estrutura JSON da instância do fornecedor de certificados tem dois campos:
  • plugin_name. Valor obrigatório que identifica o plug-in do fornecedor de certificados a ser usado, conforme exigido pela arquitetura de plug-ins do gRPC para fornecedores de certificados. O gRPC tem suporte integrado para o plug-in file-watcher que é usado nesta configuração. O plugin_name é file_watcher.
  • config. Valor obrigatório que identifica o blogue de configuração JSON para o plug-in file_watcher. O esquema e o conteúdo dependem do plug-in.

O conteúdo da estrutura JSON config para o plug-in file_watcher é:

  • certificate_file: string obrigatória. Este valor é a localização do certificado de identidade.
  • private_key_file: string obrigatória. O valor é a localização do ficheiro de chave privada, que deve corresponder ao certificado de identidade.
  • ca_certificate_file: string obrigatória. O valor é a localização do certificado de raiz, que também é conhecido como o pacote de confiança.
  • refresh_interval: string opcional. O valor indica o intervalo de atualização, especificado através da representação de string do mapeamento JSON de uma duração. O valor predefinido é "600s", uma duração de 10 minutos.

Gerador de bootstrap

A imagem do contentor do gerador de arranque está disponível em gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0. O respetivo código-fonte está disponível em https://github.com/GoogleCloudPlatform/traffic-director-grpc-bootstrap. As opções de linha de comandos mais usadas são as seguintes:

  • --output: use esta opção para especificar onde o ficheiro de arranque de saída é escrito. Por exemplo, o comando --output /tmp/bootstrap/td-grpc-bootstrap.json gera o ficheiro de arranque para /tmp/bootstrap/td-grpc-bootstrap.json no sistema de ficheiros do pod.
  • --config-mesh-experimental: use esta opção para especificar o nome da malha, que deve corresponder ao recurso Mesh.
  • --node-metadata: use esta flag para preencher os metadados do nó no ficheiro de arranque. Isto é necessário quando usa correspondências de etiquetas de metadados no EndpointPolicy, em que a Cloud Service Mesh usa os dados de etiquetas fornecidos na secção de metadados do nó do ficheiro de arranque. O argumento é fornecido no formato chave=valor, por exemplo: --node-metadata version=prod --node-metadata type=grpc

As informações anteriores adicionam o seguinte na secção de metadados do nó do ficheiro de arranque:

{
  "node": {
...
    "metadata": {
      "version": "prod",
      "type": "grpc",
...
    },
...
  },
...
}

Elimine a implementação

Opcionalmente, pode executar estes comandos para eliminar a implementação que criou através deste guia.

Para eliminar o cluster, execute este comando:

gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet

Para eliminar os recursos que criou, execute estes comandos:

gcloud compute backend-services delete grpc-gke-helloworld-service --global --quiet
gcloud compute network-endpoint-groups delete example-grpc-server --zone ZONE --quiet
gcloud compute firewall-rules delete grpc-gke-allow-health-checks --quiet
gcloud compute health-checks delete grpc-gke-helloworld-hc --quiet
gcloud network-services endpoint-policies delete ep-mtls-psms \
    --location=global --quiet
gcloud network-security authorization-policies delete helloworld-gke-authz-policy \
   --location=global --quiet
gcloud network-security client-tls-policies delete client-mtls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-tls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-mtls-policy \
    --location=global --quiet

Resolução de problemas

Use estas instruções para ajudar a resolver problemas com a sua implementação de segurança.

As cargas de trabalho não conseguem obter a configuração da malha de serviços na nuvem

Se vir um erro semelhante a este:

PERMISSION_DENIED: Request had insufficient authentication scopes.

Certifique-se do seguinte:

  • Criou o cluster do GKE com o argumento --scopes=cloud-platform argument.
  • Atribuiu o roles/trafficdirector.client às contas de serviço do Kubernetes.
  • Atribuiu a função roles/trafficdirector.client à sua conta de serviço Google Cloud predefinida (${GSA_EMAIL} acima).
  • Ativou o serviço trafficdirector.googleapis.com (API).

O seu servidor gRPC não usa TLS/mTLS, mesmo com a configuração correta da Cloud Service Mesh

Certifique-se de que especifica GRPC_SERVER na configuração das políticas de pontos finais. Se especificou SIDECAR_PROXY, o gRPC ignora a configuração.

Não é possível criar o cluster do GKE com a versão do cluster pedida

O comando de criação do cluster do GKE pode falhar com um erro semelhante ao seguinte:

Node version "1.20.5-gke.2000" is unsupported.

Certifique-se de que está a usar o argumento --release-channel rapid no comando de criação do cluster. Tem de usar o canal de lançamento rápido para obter a versão correta para este lançamento.

Vê um erro No usable endpoint

Se um cliente não conseguir comunicar com o servidor devido a um erro, o verificador de estado pode ter marcado os back-ends do servidor como não íntegros.No usable endpoint Para verificar o estado dos back-ends, execute este comando gcloud:

gcloud compute backend-services get-health grpc-gke-helloworld-service --global

Se o comando devolver o estado do back-end como não saudável, pode dever-se a um dos seguintes motivos:

  • A firewall não foi criada ou não contém o intervalo de IPs de origem correto.
  • As etiquetas de destino na sua firewall não correspondem às etiquetas no cluster que criou.

As cargas de trabalho não conseguem comunicar na configuração de segurança

Se as suas cargas de trabalho não conseguirem comunicar depois de configurar a segurança para a sua malha de serviços sem proxy, siga estas instruções para determinar a causa.

  1. Desative a segurança sem proxy e elimine problemas nos exemplos de utilização do balanceamento de carga da malha de serviço sem proxy. Para desativar a segurança na malha, faça um dos seguintes:
    1. Usar credenciais de texto simples do lado do cliente e do servidor OU
    2. Não configure a segurança para o serviço de back-end e a política de pontos finais na configuração do Cloud Service Mesh.

Siga os passos em Resolução de problemas de implementações da malha de serviços na nuvem sem proxy, uma vez que não existe configuração de segurança na sua implementação.

  1. Modifique as suas cargas de trabalho para usar credenciais xDS com texto simples ou credenciais não seguras como credenciais alternativas. Mantenha a configuração do Cloud Service Mesh com a segurança desativada, conforme abordado anteriormente. Neste caso, embora o gRPC permita que a Cloud Service Mesh configure a segurança, a Cloud Service Mesh não envia informações de segurança, caso em que o gRPC deve recorrer a credenciais de texto simples (ou não seguras), que devem funcionar de forma semelhante ao primeiro caso anterior. Se este caso não funcionar, faça o seguinte:

    1. Aumente o nível de registo do lado do cliente e do servidor para poder ver as mensagens xDS trocadas entre o gRPC e o Cloud Service Mesh.
    2. Certifique-se de que a malha de serviços na nuvem não tem a segurança ativada nas respostas CDS e LDS enviadas para as cargas de trabalho.
    3. Certifique-se de que as cargas de trabalho não estão a usar modos TLS ou mTLS nos respetivos canais. Se vir mensagens de registo relacionadas com handshakes TLS, verifique o código-fonte da sua aplicação e certifique-se de que está a usar texto simples ou inseguro como credenciais alternativas. Se o código fonte da aplicação estiver correto, pode tratar-se de um erro na biblioteca gRPC
  2. Verifique se a integração do serviço de AC com o GKE está a funcionar corretamente para o seu cluster do GKE seguindo os passos de resolução de problemas nesse guia do utilizador. Certifique-se de que os certificados e as chaves fornecidos por essa funcionalidade são disponibilizados no diretório especificado, /var/run/secrets/workload-spiffe-credentials/.

  3. Ative o TLS (em vez do mTLS) na sua malha, conforme descrito anteriormente, e reinicie as cargas de trabalho do cliente e do servidor.

    1. Aumente o nível de registo do lado do cliente e do servidor para poder ver as mensagens xDS trocadas entre o gRPC e o Cloud Service Mesh.
    2. Certifique-se de que o Cloud Service Mesh ativou a segurança nas respostas CDS e LDS enviadas para as cargas de trabalho.

O cliente falha com um CertificateException e uma mensagem Peer certificate SAN check failed

Isto indica um problema com os valores subjectAltNames na mensagem SecuritySettings. Tenha em atenção que estes valores baseiam-se nos serviços do Kubernetes que criou para o seu serviço de back-end. Para cada serviço Kubernetes criado, existe um ID SPIFFE associado, neste formato:

spiffe://${WORKLOAD_POOL}/ns/${K8S_NAMESPACE}/sa/${SERVICE_ACCOUNT}

Estes valores são:

  • WORKLOAD_POOL: o conjunto de cargas de trabalho para o cluster, que é ${PROJECT_ID}.svc.id.goog
  • K8S_NAMESPACE: o namespace do Kubernetes que usou na implementação do serviço
  • SERVICE_ACCOUNT: A conta de serviço do Kubernetes que usou na implementação do serviço

Para cada serviço do Kubernetes que anexou ao seu serviço de back-end como um grupo de pontos finais de rede, certifique-se de que calculou corretamente o ID SPIFFE e adicionou esse ID SPIFFE ao campo subjectAltNames na mensagem SecuritySettings.

As aplicações não podem usar os certificados mTLS com a sua biblioteca gRPC

Se as suas aplicações não conseguirem usar os certificados mTLS com a sua biblioteca gRPC, faça o seguinte:

  1. Verifique se a especificação do pod contém a security.cloud.google.com/use-workload-certificatesanotação descrita no artigo Criar um serviço gRPC sem proxy com NEGs.

  2. Verifique se os ficheiros que contêm a cadeia de certificados juntamente com o certificado principal, a chave privada e os certificados da AC fidedigna estão acessíveis nos seguintes caminhos a partir do Pod:

    1. Cadeia de certificados juntamente com o certificado de entidade final: "/var/run/secrets/workload-spiffe-credentials/certificates.pem"
    2. Chave privada: "/var/run/secrets/workload-spiffe-credentials/private_key.pem"
    3. CA Bundle: "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem"
  3. Se os certificados no passo anterior não estiverem disponíveis, faça o seguinte:

      gcloud privateca subordinates describe SUBORDINATE_CA_POOL_NAME 
    --location=LOCATION

    1. Verifique se o plano de controlo do GKE tem a associação de função do IAM correta, o que lhe concede acesso ao serviço de CA:

      # Get the IAM policy for the CA
      gcloud privateca roots get-iam-policy ROOT_CA_POOL_NAME
      
      # Verify that there is an IAM binding granting access in the following format
      - members:
      - serviceAccount:service-projnumber@container-engine-robot.iam.gserviceaccount.com
      role: roles/privateca.certificateManager
      
      # Where projnumber is the project number (e.g. 2915810291) for the GKE cluster.
      
    2. Verifique se o certificado não expirou. Esta é a cadeia de certificados e o certificado de entidade final em /var/run/secrets/workload-spiffe-credentials/certificates.pem. Para verificar, execute este comando:

      cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
      

    3. Verifique se o tipo de chave é suportado pela sua aplicação executando o seguinte comando:

      cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
      

    4. Verifique se a sua aplicação Java gRPC tem o seguinte keyAlgorithm no ficheiro YAML WorkloadCertificateConfig:

      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
  4. Verifique se a AC usa a mesma família de chaves que a chave do certificado.

O certificado de uma aplicação é rejeitado pelo cliente, pelo servidor ou pelo par

  1. Verifique se a aplicação de pares usa o mesmo pacote de confiança para validar o certificado.
  2. Verifique se o certificado em utilização não expirou (cadeia de certificados juntamente com o certificado de folha: "/var/run/secrets/workload-spiffe-credentials/certificates.pem").

Os agrupamentos permanecem num estado pendente

Se os pods permanecerem num estado pendente durante o processo de configuração, aumente os recursos de CPU e memória para os pods na especificação de implementação.

Não é possível criar o cluster com a flag --enable-mesh-certificates

Certifique-se de que está a executar a versão mais recente da CLI gcloud:

gcloud components update

Tenha em atenção que a flag --enable-mesh-certificates só funciona com gcloud beta.

Os pods não são iniciados

Os pods que usam certificados da malha do GKE podem não ser iniciados se o aprovisionamento de certificados falhar. Isto pode acontecer em situações como as seguintes:

  • O WorkloadCertificateConfig ou o TrustConfig está configurado incorretamente ou em falta.
  • Os CSRs não estão a ser aprovados.

Pode verificar se o aprovisionamento de certificados está a falhar verificando os eventos do pod.

  1. Verifique o estado do seu Pod:

    kubectl get pod -n POD_NAMESPACE POD_NAME
    

    Substitua o seguinte:

    • POD_NAMESPACE: o espaço de nomes do seu Pod.
    • POD_NAME: o nome do seu Pod.
  2. Verifique os eventos recentes do seu Pod:

    kubectl describe pod -n POD_NAMESPACE POD_NAME
    
  3. Se o aprovisionamento de certificados estiver a falhar, é apresentado um evento com Type=Warning, Reason=FailedMount, From=kubelet e um campo Message que começa com MountVolume.SetUp failed for volume "gke-workload-certificates". O campo Message contém informações de resolução de problemas.

    Events:
      Type     Reason       Age                From       Message
      ----     ------       ----               ----       -------
      Warning  FailedMount  13s (x7 over 46s)  kubelet    MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)
    
  4. Consulte os seguintes passos de resolução de problemas se os seus Pods não iniciarem devido a objetos configurados incorretamente ou a CSRs rejeitados.

WorkloadCertificateConfig ou TrustConfig está configurado incorretamente

Certifique-se de que criou os objetos WorkloadCertificateConfig e TrustConfig corretamente. Pode diagnosticar configurações incorretas em qualquer um destes objetos através do kubectl.

  1. Obter o estado atual.

    Para WorkloadCertificateConfig:

    kubectl get WorkloadCertificateConfig default -o yaml
    

    Para TrustConfig:

    kubectl get TrustConfig default -o yaml
    
  2. Inspeccione o resultado do estado. Um objeto válido tem uma condição com type: Ready e status: "True".

    status:
      conditions:
      - lastTransitionTime: "2021-03-04T22:24:11Z"
        message: WorkloadCertificateConfig is ready
        observedGeneration: 1
        reason: ConfigReady
        status: "True"
        type: Ready
    

    Para objetos inválidos, é apresentado status: "False". Os camposreasonemessage contêm detalhes de resolução de problemas adicionais.

Os CSRs não são aprovados

Se algo correr mal durante o processo de aprovação do CSR, pode verificar os detalhes do erro nas condições type: Approved e type: Issued do CSR.

  1. Liste os CSRs relevantes através de kubectl:

    kubectl get csr \
      --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
    
  2. Escolha um CSR que seja Approved e não Issued, ou que não seja Approved.

  3. Obtenha detalhes do CSR selecionado através do kubectl:

    kubectl get csr CSR_NAME -o yaml
    

    Substitua CSR_NAME pelo nome do CSR que escolheu.

Um CSR válido tem uma condição com type: Approved e status: "True", e um certificado válido no campo status.certificate:

status:
  certificate: <base64-encoded data>
  conditions:
  - lastTransitionTime: "2021-03-04T21:58:46Z"
    lastUpdateTime: "2021-03-04T21:58:46Z"
    message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
    reason: AutoApproved
    status: "True"
    type: Approved

As informações de resolução de problemas para CSRs inválidos são apresentadas nos campos message e reason.

Os pods não têm certificados

  1. Obtenha a especificação do agrupamento para o seu agrupamento:

    kubectl get pod -n POD_NAMESPACE POD_NAME -o yaml
    

    Substitua o seguinte:

    • POD_NAMESPACE: o espaço de nomes do seu Pod.
    • POD_NAME: o nome do seu Pod.
  2. Verifique se a especificação do pod contém a security.cloud.google.com/use-workload-certificates anotação descrita no artigo Configure pods to receive mTLS credentials (Configure pods para receber credenciais mTLS).

  3. Verifique se o controlador de admissão de certificados da malha do GKE injetou com êxito um volume do controlador CSI do tipo workloadcertificates.security.cloud.google.com na especificação do pod:

    volumes:
    ...
    -csi:
      driver: workloadcertificates.security.cloud.google.com
      name: gke-workload-certificates
    ...
    
  4. Verifique a presença de uma montagem de volume em cada um dos contentores:

    containers:
    - name: ...
      ...
      volumeMounts:
      - mountPath: /var/run/secrets/workload-spiffe-credentials
        name: gke-workload-certificates
        readOnly: true
      ...
    
  5. Verifique se os seguintes conjuntos de certificados e a chave privada estão disponíveis nas seguintes localizações no pod:

    • Pacote da cadeia de certificados: /var/run/secrets/workload-spiffe-credentials/certificates.pem
    • Chave privada: /var/run/secrets/workload-spiffe-credentials/private_key.pem
    • Pacote de âncoras de fidedignidade da AC: /var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
  6. Se os ficheiros não estiverem disponíveis, siga estes passos:

    1. Recupere a instância do serviço de CA (pré-visualização) para o cluster:

      kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'
      
    2. Obtenha o estado da instância do serviço de AC (pré-visualização):

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Substitua o seguinte:

      • ISSUING_CA_TYPE: o tipo de AC emissora, que tem de ser subordinates ou roots.
      • ISSUING_CA_NAME: o nome da AC emissora.
      • ISSUING_CA_LOCATION: a região da AC emissora.
    3. Obtenha a Política IAM para a AC raiz:

      gcloud privateca roots get-iam-policy ROOT_CA_NAME
      

      Substitua ROOT_CA_NAME pelo nome da sua AC raiz.

    4. Na política IAM, verifique se a associação de políticas privateca.auditor existe:

      ...
      - members:
        - serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
        role: roles/privateca.auditor
      ...
      

      Neste exemplo, PROJECT_NUMBER é o número do projeto do seu cluster.

    5. Obtenha a Política IAM para a AC subordinada:

      gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAME
      

      Substitua SUBORDINATE_CA_NAME pelo nome da AC subordinada.

    6. Na política IAM, verifique se a associação de políticas privateca.certificateManager existe:

      ...
      - members:
        - serviceAccount: service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
        role: roles/privateca.certificateManager
      ...
      

      Neste exemplo, PROJECT_NUMBER é o número do projeto do seu cluster.

As aplicações não podem usar credenciais mTLS emitidas

  1. Verifique se o certificado não expirou:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  2. Verifique se o tipo de chave que usou é suportado pela sua aplicação.

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
    
  3. Verifique se a AC emissora usa a mesma família de chaves que a chave do certificado.

    1. Obtenha o estado da instância do serviço de CA (pré-visualização):

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Substitua o seguinte:

      • ISSUING_CA_TYPE: o tipo de AC emissora, que tem de ser subordinates ou roots.
      • ISSUING_CA_NAME: o nome da AC emissora.
      • ISSUING_CA_LOCATION: a região da AC emissora.
    2. Verifique se o keySpec.algorithm na saída é o mesmo algoritmo de chave que definiu no manifesto YAML WorkloadCertificateConfig. O resultado tem o seguinte aspeto:

      config:
        ...
        subjectConfig:
          commonName: td-sub-ca
          subject:
            organization: TestOrgLLC
          subjectAltName: {}
      createTime: '2021-05-04T05:37:58.329293525Z'
      issuingOptions:
        includeCaCertUrl: true
      keySpec:
        algorithm: RSA_PKCS1_2048_SHA256
       ...
      

Os certificados são rejeitados

  1. Verifique se a aplicação de pares usa o mesmo pacote de confiança para validar o certificado.
  2. Verifique se o certificado não expirou:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  3. Verifique se o código do cliente, se não estiver a usar a API de recarregamento de credenciais do gRPC Go, atualiza periodicamente as credenciais do sistema de ficheiros.

  4. Verifique se as cargas de trabalho estão no mesmo domínio de confiança que a AC. Os certificados de malha do GKE suportam a comunicação entre cargas de trabalho num único domínio de confiança.

Limitações

A segurança do serviço Cloud Service Mesh só é suportada com o GKE. Não pode implementar a segurança de serviços com o Compute Engine.

O Cloud Service Mesh não suporta cenários em que existem dois ou mais recursos de políticas de pontos finais que correspondem igualmente a um ponto final, por exemplo, duas políticas com as mesmas etiquetas e portas, ou duas ou mais políticas com etiquetas diferentes que correspondem igualmente às etiquetas de um ponto final. Para mais informações sobre como as políticas de pontos finais são associadas às etiquetas de um ponto final, consulte as APIs for EndpointPolicy.EndpointMatcher.MetadataLabelMatcher. Nestas situações, o Cloud Service Mesh não gera uma configuração de segurança a partir de nenhuma das políticas em conflito.