Configurer la sécurité du service avec gRPC sans proxy

Ce guide explique comment configurer un service de sécurité pour un maillage de services gRPC sans proxy.

Exigences

Avant de configurer la sécurité du service pour le maillage de services gRPC sans proxy, assurez-vous que vous remplissez les conditions suivantes.

Configurer la gestion de l'authentification et des accès (IAM)

Vous devez disposer des autorisations requises pour utiliser Google Kubernetes Engine. Vous devez au moins disposer des rôles suivants :

  • Rôle GKE roles/container.clusterAdmin
  • Rôle Compute Engine roles/compute.instanceAdmin
  • Rôle roles/iam.serviceAccountUser

Pour créer les ressources requises pour la configuration, vous devez disposer du rôle compute.NetworkAdmin. Ce rôle contient toutes les autorisations nécessaires pour créer, mettre à jour, supprimer, répertorier et utiliser (c'est-à-dire, y faire référence dans d'autres ressources) les ressources requises. Si vous êtes le propriétaire ou l'éditeur du projet, ce rôle vous est automatiquement attribué.

Notez que les autorisations networksecurity.googleapis.com.clientTlsPolicies.use et networksecurity.googleapis.com.serverTlsPolicies.use ne sont pas appliquées lorsque vous référencez ces ressources dans le service de backend et dans les ressources du proxy HTTPS cible.

Si cette autorisation est appliquée par la suite et que vous utilisez le rôle compute.NetworkAdmin, vous ne remarquerez aucun problème lors de l'application de cette vérification.

Si vous utilisez des rôles personnalisés et que cette vérification est appliquée ultérieurement, vous devez inclure l'autorisation .use correspondante. À l'avenir, vous remarquerez peut-être que votre rôle personnalisé ne dispose pas des autorisations nécessaires pour faire référence à clientTlsPolicy ou serverTlsPolicy, respectivement à partir du service de backend ou du proxy HTTPS cible.

Préparer la configuration

La sécurité du maillage de services sans proxy (PSM, Proxyless Service Mesh) ajoute une sécurité à un maillage de services configuré pour l'équilibrage de charge conformément à la documentation des services gRPC sans proxy. Dans un maillage de services sans proxy, un client gRPC utilise le schéma xds: dans l'URI pour accéder au service, ce qui active les fonctionnalités PSM d'équilibrage de charge et de découverte des points de terminaison.

Mettre à jour les clients et les serveurs gRPC vers la version appropriée

Compilez ou recompilez vos applications en utilisant la version gRPC minimale compatible avec votre langage.

Mettre à jour le fichier d'amorçage

Les applications gRPC utilisent un seul fichier d'amorçage, qui doit comporter tous les champs obligatoires pour le code côté client et côté serveur gRPC. Un générateur d'amorçage génère automatiquement le fichier d'amorçage pour inclure les options et les valeurs dont la sécurité PSM a besoin. Pour en savoir plus, consultez la section Fichier d'amorçage, qui inclut un exemple de fichier d'amorçage.

Vue d'ensemble de la configuration

Ce processus de configuration est une extension de la configuration de Traffic Director avec GKE et des services gRPC sans proxy. Les étapes existantes non modifiées de cette configuration sont référencées partout où elles s'appliquent.

Les principales améliorations apportées à la configuration de Traffic Director avec GKE sont les suivantes :

  1. Configurer CA Service dans lequel vous créez des pools d'autorités de certification privés et les autorités de certification requises.
  2. Créer un cluster GKE avec des fonctionnalités de GKE Workload Identity et de certificats de maillage, et l'intégration de CA Service.
  3. Configurer l'émission de certificats de maillage sur le cluster.
  4. Créer les comptes de service client et serveur.
  5. Configurer l'exemple de serveur qui utilise les API xDS et les identifiants du serveur xDS pour acquérir la configuration de sécurité auprès de Traffic Director.
  6. Configurer l'exemple de client qui utilise des identifiants xDS.
  7. Mettre à jour la configuration de Traffic Director pour inclure la configuration de sécurité.

Vous pouvez consulter des exemples de code pour utiliser des identifiants xDS aux emplacements suivants :

Mettre à jour Google Cloud CLI

Pour mettre à jour Google Cloud CLI, exécutez la commande suivante :

gcloud components update

Configurer des variables d'environnement

Dans ce guide, vous utilisez les commandes Cloud Shell et les informations répétées dans ces commandes sont représentées par diverses variables d'environnement. Définissez vos valeurs spécifiques dans les variables d'environnement suivantes dans l'environnement shell avant d'exécuter les commandes. Chaque ligne de commentaire indique la signification de la variable d'environnement associée.

# Your project ID
PROJECT_ID=YOUR_PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME="secure-psm-cluster"
ZONE="us-east1-d"

# 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

Activer l'accès aux API requises

Cette section vous explique comment activer l'accès aux API requises.

  1. Exécutez la commande suivante pour activer l'API Traffic Director et les autres API requises pour la sécurité du maillage de services gRPC sans 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. Exécutez la commande suivante pour autoriser le compte de service par défaut à accéder à l'API de sécurité Traffic Director.

    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
    

Créer ou mettre à jour un cluster GKE

La sécurité du service Traffic Director dépend de l'intégration de CA Service à GKE. Le cluster GKE doit répondre aux exigences suivantes, en plus de celles concernant la configuration :

  • Utilisez au moins la version de cluster 1.21.4-gke.1801. Si vous avez besoin de fonctionnalités disponibles dans une version ultérieure, vous pouvez obtenir cette version auprès de la version précoce.
  • Le cluster GKE doit être activé et configuré avec des certificats de maillage, comme décrit dans la section Créer des autorités de certification pour émettre des certificats.
  1. Créez un cluster qui utilise Workload Identity. Si vous mettez à jour un cluster existant, passez à l'étape suivante. La valeur que vous attribuez à --tags doit correspondre au nom transmis à l'option --target-tags pour la commande firewall-rules create dans la section Configurer Traffic Director avec des composants 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
    

    La création du cluster peut prendre plusieurs minutes.

  2. Si vous utilisez un cluster existant, activez les certificats de maillage Workload Identity et GKE. Assurez-vous que le cluster a été créé avec l'option --enable-ip-alias, qui ne peut pas être utilisée avec la commande update.

    gcloud container clusters update CLUSTER_NAME \
      --enable-mesh-certificates
    
  3. Exécutez la commande suivante pour passer au nouveau cluster en tant que cluster par défaut pour vos commandes kubectl :

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

Enregistrer des clusters avec un parc

Enregistrez le cluster que vous avez créé ou mis à jour à la section Créer un cluster GKE avec un parc. L'enregistrement du cluster vous permet de configurer des clusters plus facilement dans plusieurs projets.

Notez que ces étapes peuvent prendre jusqu'à 10 minutes pour chacune d'entre elles.

  1. Enregistrez votre cluster dans le parc:

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

    Remplacez les variables comme suit :

    • CLUSTER_NAME : nom de votre cluster
    • ZONE : zone de votre cluster.
    • MANIFEST-FILE_NAME : chemin d'accès au fichier dans lequel ces commandes génèrent le fichier manifeste pour l'enregistrement.

    Une fois le processus d'enregistrement terminé, un message de ce type s'affiche :

    Finished registering the cluster CLUSTER_NAME with the fleet.
  2. Appliquez le fichier manifeste généré à votre cluster :

    kubectl apply -f MANIFEST-FILE_NAME
    

    Une fois le processus d'application réussi, des messages de ce type s'affichent :

    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. Récupérez la ressource d'appartenance à partir du cluster :

    kubectl get memberships membership -o yaml
    

    Le résultat doit inclure le pool d'identités Workoad attribué par le parc, où PROJECT_ID correspond à l'ID de votre projet:

    workload_identity_pool: PROJECT_ID.svc.id.goog
    

    Cela signifie que le cluster a bien été enregistré.

Créer des autorités de certification pour émettre des certificats

Pour émettre des certificats sur vos pods, créez un pool CA Service et les autorités de certification suivantes :

  • Autorité de certification racine Il s'agit de la racine de confiance pour tous les certificats de maillages émis. Vous pouvez utiliser une autorité de certification racine existante, si vous en avez une. Créez l'autorité de certification racine au niveau enterprise, conçu pour l'émission de certificats de longue durée, à faible volume.
  • Autorité de certification subordonnée Cette autorité de certification délivre des certificats pour les charges de travail. Créez l'autorité de certification subordonnée dans la région où votre cluster est déployé. Créez l'autorité de certification subordonnée au niveau devops, conçu pour l'émission de certificats de courte durée, à volume élevé.

La création d'une autorité de certification subordonnée est facultative, mais nous vous recommandons vivement d'en créer une plutôt que d'utiliser votre autorité de certification racine pour émettre des certificats de maillage GKE. Si vous décidez d'utiliser l'autorité de certification racine pour émettre des certificats de maillage, assurez-vous que le mode d'émission basé sur la configuration par défaut reste autorisé.

L'autorité de certification subordonnée peut se trouver dans une région différente de votre cluster, mais nous vous recommandons vivement de la créer dans la même région que votre cluster pour optimiser les performances. Toutefois, vous pouvez créer des autorités de certification racine et subordonnées dans différentes régions sans affecter les performances ou la disponibilité.

Les régions suivantes sont compatibles avec CA Service :

Nom de la région Description de la région
asia-east1 Taïwan
asia-east2 Hong Kong
asia-northeast1 Tokyo
asia-northeast2 Osaka
asia-northeast3 Séoul
asia-south1 Mumbai
asia-south2 Delhi
asia-southeast1 Singapour
asia-southeast2 Jakarta
australia-southeast1 Sydney
australia-southeast2 Melbourne
europe-central2 Varsovie
europe-north1 Finlande
europe-southwest1 Madrid
europe-west1 Belgique
europe-west2 Londres
europe-west3 Francfort
europe-west4 Pays-Bas
europe-west6 Zurich
europe-west8 Milan
europe-west9 Paris
europe-west10 Berlin
europe-west12 Turin
me-central1 Doha
me-central2 Dammam
me-west1 Tel Aviv
northamerica-northeast1 Montréal
northamerica-northeast2 Toronto
southamerica-east1 São Paulo
southamerica-west1 Santiago
us-central1 Iowa
us-east1 Caroline du Sud
us-east4 Virginie du Nord
us-east5 Columbus
us-south1 Dallas
us-west1 Oregon
us-west2 Los Angeles
us-west3 Salt Lake City
us-west4 Las Vegas

Vous pouvez également vérifier la liste des emplacements acceptés en exécutant la commande suivante :

gcloud privateca locations list
  1. Accordez le rôle IAM roles/privateca.caManager aux utilisateurs qui créent un pool d'autorités de certification et une autorité de certification. Notez que le format approprié de MEMBER est user:userid@example.com. Si cette personne est l'utilisateur actuel, vous pouvez obtenir son ID à l'aide de la commande 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. Attribuez le rôle role/privateca.admin pour le service CA aux personnes ayant besoin de modifier les stratégies IAM, où MEMBER est une personne qui a besoin de cet accès, en particulier toute personne effectuant les étapes ci-dessous qui attribuent les rôles privateca.auditor et privateca.certificateManager :

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.admin
    
  3. Créez le pool CA Service racine.

    gcloud privateca pools create ROOT_CA_POOL_NAME \
      --location ROOT_CA_POOL_LOCATION \
      --tier enterprise
    
  4. Créez une autorité de certification racine.

    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
    

    Pour cette configuration de démonstration, utilisez les valeurs suivantes pour les variables :

    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_NAME=pkcs2-ca
    • ROOT_CA_POOL_LOCATION=us-east1
    • ROOT_CA_ORGANIZATION="TestCorpLLC"
  5. Créez le pool et l'autorité de certification subordonnés. Assurez-vous que le mode d'émission basé sur la configuration par défaut reste autorisé.

    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
    

    Pour cette configuration de démonstration, utilisez les valeurs suivantes pour les variables :

    • 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. Attribuez le rôle IAM privateca.auditor au pool d'autorités de certification racine pour autoriser l'accès à partir du compte de service 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. Accordez le rôle IAM privateca.certificateManager au pool d'autorités de certification subordonné pour autoriser l'accès à partir du compte de service 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. Enregistrez la configuration YAML WorkloadCertificateConfig suivante pour indiquer à votre cluster comment émettre des certificats de maillage :

    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
    
    

    Remplacez les éléments suivants :

    • ID du projet dans lequel votre cluster s'exécute:
      PROJECT_ID
    • URI complet de l'autorité de certification qui émet vos certificats de maillage (ISSUING_CA_POOL_URI). Il peut s'agir de votre autorité de certification subordonnée (recommandé) ou de votre autorité de certification racine. Il a le format suivant :
      //privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
  9. Enregistrez la configuration YAML TrustConfig suivante pour indiquer à votre cluster comment approuver les certificats émis :

    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
    

    Remplacez les éléments suivants :

    • ID du projet dans lequel votre cluster s'exécute:
      PROJECT_ID
    • URI complet du pool d'autorités de certification racine (ROOT_CA_POOL_URI). Son format est le suivant :
      //privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
  10. Appliquez les configurations à votre cluster.

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

Créer un service gRPC sans proxy avec des NEG

Pour la sécurité PSM, vous avez besoin d'un serveur gRPC sans proxy capable d'utiliser xDS pour acquérir la configuration de sécurité de Traffic Director. Cette étape est semblable à la configuration des services GKE avec des NEG dans le guide de configuration de l'équilibrage de charge PSM, à la différence que vous utilisez le serveur helloworld compatible xDS de l'exemple xDS dans le dépôt grpc-java au lieu de l'image java-example-hostname.

Vous créez et exécutez ce serveur dans un conteneur créé à partir d'une image openjdk:8-jdk. Vous utilisez également la fonctionnalité de NEG nommé, qui vous permet de spécifier un nom pour le NEG. Cela simplifie les étapes ultérieures, car votre déploiement connaît le nom du NEG sans avoir à le rechercher.

Voici un exemple complet de la spécification Kubernetes du serveur gRPC. Notez les points suivants :

  • La spécification crée un compte de service Kubernetes example-grpc-server qui est utilisé par le pod du serveur gRPC.
  • La spécification utilise le champ name de l'annotation cloud.google.com/neg du service pour spécifier le nom du NEG example-grpc-server.
  • La variable ${PROJNUM} représente le numéro de votre projet.
  • La spécification utilise la section initContainers pour exécuter un générateur d'amorçage afin de remplir le fichier d'amorçage nécessaire à la bibliothèque gRPC sans proxy. Ce fichier d'amorçage se trouve à l'emplacement /tmp/grpc-xds/td-grpc-bootstrap.json dans le conteneur de serveur gRPC appelé example-grpc-server.

Ajoutez l'annotation suivante à votre spécification de pod :

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

L'emplacement approprié est indiqué dans la spécification complète qui suit.

Lors de la création, chaque pod reçoit un volume à /var/run/secrets/workload-spiffe-credentials. Ce volume contient les éléments suivants :

  • private_key.pem est une clé privée générée automatiquement.
  • certificates.pem est un bundle de certificats au format PEM qui peuvent être présentés à un autre pod sous la forme d'une chaîne de certificats client, ou utilisés comme chaîne de certificats de serveur.
  • ca_certificates.pem est un bundle de certificats au format PEM à utiliser en tant qu'ancres de confiance pour valider la chaîne de certificats client présentée par un autre pod, ou la chaîne de certificats du serveur reçue lors de la connexion à un autre pod.

Notez que ca_certificates.pem contient des certificats pour le domaine de confiance local pour les charges de travail, qui correspond au pool de charges de travail du cluster.

Le certificat feuille dans certificates.pem contient l'assertion d'identité SPIFFE en texte brut suivante :

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

Dans cette assertion :

  • WORKLOAD_POOL est le nom du pool de charges de travail du cluster.
  • NAMESPACE est l'espace de noms de votre compte de service Kubernetes.
  • KUBERNETES_SERVICE_ACCOUNT est le nom de votre compte de service Kubernetes.

Les instructions suivantes propres à votre langage créent la spécification à utiliser dans cet exemple.

Java

  1. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification :

    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.13.0
           imagePullPolicy: Always
           args:
           - --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. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification :

    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.13.0
           imagePullPolicy: Always
           args:
           - --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. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification :

    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.13.0
           imagePullPolicy: Always
           args:
           - --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
    

Go

  1. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification :

    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.13.0
           imagePullPolicy: Always
           args:
           - --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
    

    Suivez la procédure ci-dessous.

  1. Appliquez la spécification :

    kubectl apply -f example-grpc-server.yaml
    
  2. Attribuez les rôles requis au compte de service :

    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. Exécutez les commandes suivantes pour vérifier que le service et le pod ont été créés correctement :

    kubectl get deploy/example-grpc-server
    kubectl get svc/example-grpc-server
    
  4. Vérifiez que le nom du NEG est correct :

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

    La commande ci-dessus doit renvoyer le nom du NEG example-grpc-server.

Configurer Traffic Director avec les composants de l'équilibrage de charge Google Cloud

Les étapes de cette section sont semblables à celles de la section Configurer Traffic Director avec des composants d'équilibrage de charge, mais présentent quelques modifications décrites ci-dessous.

Créer la vérification d'état, la règle de pare-feu et le service de backend

Lorsque le serveur gRPC est configuré pour utiliser mTLS, les vérifications d'état gRPC ne fonctionnent pas, car le client de vérification de l'état ne peut pas présenter de certificat client valide aux serveurs. Vous pouvez résoudre cela de l'une des manières suivantes.

Dans la première approche, vous demandez au serveur de créer un port de diffusion supplémentaire désigné en tant que port de vérification d'état. Celui-ci est associé à un service de vérification d'état spécial, en tant que texte brut ou TLS.

L'exemple de serveur xDS helloworld utilise PORT_NUMBER + 1 comme port de vérification de l'état en texte brut. L'exemple utilise 50052 comme port de vérification de l'état, car 50051 est le port du serveur d'applications gRPC.

Dans la seconde approche, vous configurez la vérification de l'état pour vérifier uniquement la connectivité TCP au port de diffusion de l'application. Cela ne vérifie que la connectivité et génère également du trafic inutile vers le serveur en cas de handshakes TLS ayant échoué. C'est pourquoi nous vous recommandons de suivre la première approche.

  1. Créez la vérification d'état. Notez que la vérification d'état ne démarre pas tant que vous n'avez pas créé et démarré le serveur.

    • Si vous créez un port de diffusion désigné pour la vérification d'état, ce que nous recommandons, utilisez cette commande :

      gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
       --enable-logging --port 50052
      
    • Si vous créez une vérification d'état TCP, ce que nous vous déconseillons, exécutez la commande suivante :

      gcloud compute health-checks create tcp grpc-gke-helloworld-hc \
      --use-serving-port
      
  2. Créez le pare-feu. Assurez-vous que la valeur de --target-tags correspond à celle que vous avez fournie pour --tags dans la section Créer ou mettre à jour un cluster 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. Créez le service de backend :

    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. Associez le NEG au service de backend :

    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
    

Créer la carte des règles de routage

Cette démarche est semblable à la façon dont vous créez une carte des règles de routage dans la section Configuration de Traffic Director avec Google Kubernetes Engine et des services gRPC sans proxy.

  1. Créez le mappage d'URL :

    gcloud compute url-maps create grpc-gke-url-map \
       --default-service grpc-gke-helloworld-service
    
  2. Ajoutez l'outil de mise en correspondance des chemins d'accès au mappage d'URL :

    gcloud compute url-maps add-path-matcher grpc-gke-url-map \
       --default-service grpc-gke-helloworld-service \
       --path-matcher-name grpc-gke-path-matcher \
       --new-hosts helloworld-gke:8000
    
  3. Créez le proxy gRPC cible :

    gcloud compute target-grpc-proxies create grpc-gke-proxy \
       --url-map grpc-gke-url-map --validate-for-proxyless
    
  4. Créez la règle de transfert :

    gcloud compute forwarding-rules create grpc-gke-forwarding-rule \
      --global \
      --load-balancing-scheme=INTERNAL_SELF_MANAGED \
      --address=0.0.0.0 \
      --target-grpc-proxy=grpc-gke-proxy \
      --ports 8000 \
      --network default
    

Configurer Traffic Director avec la sécurité gRPC sans proxy

Cet exemple montre comment configurer mTLS côté client et côté serveur.

Format des références aux règles

Le format suivant est requis pour faire référence aux règles TLS des serveurs et des clients :

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

Exemple :

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

Configurer mTLS côté serveur

Commencez par créer une règle TLS de serveur. La règle demande au serveur gRPC d'utiliser la configuration de plug-in certificateProvicerInstance identifiée par le nom google_cloud_private_spiffe pour le certificat d'identité, qui fait partie de serverCertificate. La section mtlsPolicy indique la sécurité mTLS et utilise le même google_cloud_private_spiffe que la configuration de plug-in pour clientValidationCa, qui est la spécification du certificat racine (de validation).

Ensuite, vous créez une règle de point de terminaison. Cela indique qu'un backend, par exemple un serveur gRPC, utilisant le port 50051 avec n'importe quel (ou aucun) libellé de métadonnées, reçoit la règle TLS du serveur associé nommée server-mtls-policy. Spécifiez les libellés de métadonnées à l'aide de MATCH_ALL. Créez une règle de point de terminaison avec un fichier temporaire ep-mtls-psms.yaml qui contient les valeurs de la ressource de règle de point de terminaison, à l'aide de la règle que vous avez déjà définie.

  1. Créez un fichier temporaire server-mtls-policy.yaml dans le répertoire actuel, avec les valeurs de la ressource de règle TLS du serveur :

    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. Créez une ressource de règle TLS de serveur appelée server-mtls-policy en important le fichier temporaire server-mtls-policy.yaml :

    gcloud network-security server-tls-policies import server-mtls-policy \
      --source=server-mtls-policy.yaml --location=global
    
  3. Créez la règle de point de terminaison en créant le fichier temporaire 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. Créez la règle de point de terminaison en important le fichier ep-mtls-psms.yaml :

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

Configurer mTLS côté client

La règle de sécurité côté client est associée au service de backend. Lorsqu'un client accède à un backend (le serveur gRPC) via le service de backend, la règle de sécurité associée côté client est envoyée au client.

  1. Créez le contenu de la ressource de règle TLS du client dans un fichier temporaire appelé client-mtls-policy.yaml dans le répertoire actuel :

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Créez la ressource de stratégie TLS client appelée client-mtls-policy en important le fichier temporaire client-mtls-policy.yaml :

    gcloud network-security client-tls-policies import client-mtls-policy \
      --source=client-mtls-policy.yaml --location=global
    
  3. Créez un extrait dans un fichier temporaire pour référencer cette règle et ajouter les détails pour subjectAltNames dans le message SecuritySettings, comme dans l'exemple suivant. Remplacez ${PROJECT_ID} par l'ID de votre projet, qui correspond à la valeur de la variable d'environnement ${PROJECT_ID} décrite ci-dessus. Notez que example-grpc-server dans subjectAltNames est le nom du compte de service Kubernetes utilisé pour le pod du serveur gRPC dans la spécification de déploiement.

    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. Ajoutez le message securitySettings au service de backend que vous avez déjà créé. Ces étapes permettent d'exporter le contenu du service de backend actuel, d'ajouter le message client securitySetting et de réimporter le nouveau contenu pour mettre à jour le service de backend.

    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
    

Vérifier la configuration

La configuration de Traffic Director est maintenant terminée, y compris la sécurité côté serveur et côté client. Vous allez ensuite préparer et exécuter les charges de travail du serveur et du client. Ceci conclut l'exemple.

Créer un client gRPC sans proxy

Cette étape est semblable à l'étape Créer un service gRPC sans proxy ci-dessus. Vous utilisez le client helloworld compatible xDS provenant du répertoire d'exemples xDS du dépôt grpc-java. Vous créez et exécutez le client dans un conteneur créé à partir d'une image openjdk:8-jdk. La spécification Kubernetes du client gRPC effectue les opérations suivantes.

  • Elle crée un compte de service Kubernetes example-grpc-client utilisé par le pod du client gRPC.
  • ${PROJNUM} représente le numéro de votre projet et doit être remplacé par le numéro réel.

Ajoutez l'annotation suivante à votre spécification de pod :

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

Lors de la création, chaque pod reçoit un volume à /var/run/secrets/workload-spiffe-credentials. Ce volume contient les éléments suivants :

  • private_key.pem est une clé privée générée automatiquement.
  • certificates.pem est un bundle de certificats au format PEM qui peuvent être présentés à un autre pod sous la forme d'une chaîne de certificats client, ou utilisés comme chaîne de certificats de serveur.
  • ca_certificates.pem est un bundle de certificats au format PEM à utiliser en tant qu'ancres de confiance pour valider la chaîne de certificats client présentée par un autre pod, ou la chaîne de certificats du serveur reçue lors de la connexion à un autre pod.

Notez que ca_certificates.pem contient les certificats racine du domaine de confiance local pour les charges de travail, qui correspond au pool de charges de travail du cluster.

Le certificat feuille dans certificates.pem contient l'assertion d'identité SPIFFE en texte brut suivante :

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

Dans cette assertion :

  • WORKLOAD_POOL est le nom du pool de charges de travail du cluster.
  • NAMESPACE est le nom de votre compte de service Kubernetes.
  • KUBERNETES_SERVICE_ACCOUNT est l'espace de noms de votre compte de service Kubernetes.

Les instructions suivantes propres à votre langage créent la spécification à utiliser dans cet exemple.

Java

  1. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification suivante :

    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.13.0
            imagePullPolicy: Always
            args:
            - --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. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification suivante :

    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.13.0
            imagePullPolicy: Always
            args:
            - --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. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification suivante :

    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.13.0
            imagePullPolicy: Always
            args:
            - --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
    

Go

  1. Exécutez la commande suivante pour vous assurer que le numéro de projet est correctement défini :

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Créez la spécification suivante :

    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.13.0
            imagePullPolicy: Always
            args:
            - --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
    

Suivez la procédure ci-dessous.

  1. Appliquez la spécification :

    kubectl apply -f example-grpc-client.yaml
    
  2. Attribuez les rôles requis au compte de service :

    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. Vérifiez que le pod client est en cours d'exécution :

    kubectl get pods
    

    La commande renvoie du texte semblable à ce qui suit :

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

Exécuter le serveur

Créez et exécutez le serveur helloworld compatible xDS dans le pod de serveur que vous avez créé précédemment.

Java

  1. Obtenez le nom du pod créé pour le service example-grpc-server :

    kubectl get pods | grep example-grpc-server
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Ouvrez une interface système sur le pod de serveur :

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. Dans le shell, vérifiez que le fichier d'amorçage /tmp/grpc-xds/td-grpc-bootstrap.json correspond au schéma décrit dans la section Fichier d'amorçage.

  4. Téléchargez la version 1.42.1 de Java gRPC, puis créez l'application de serveur 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. Exécutez le serveur avec l'option --xds-creds pour indiquer qu'il est compatible avec xDS, en utilisant 50051 comme port d'écoute et xds-server comme nom d'identification du serveur :

    ./build/install/example-xds/bin/xds-hello-world-server --xds-creds 50051 xds-server
    
  6. Une fois que le serveur a obtenu la configuration nécessaire auprès de Traffic Director, vous obtenez le résultat suivant :

    Listening on port 50051
    Plaintext health service listening on port 50052
    

C++

  1. Obtenez le nom du pod créé pour le service example-grpc-server :

    kubectl get pods | grep example-grpc-server
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Ouvrez une interface système sur le pod de serveur :

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. Dans l'interface système, vérifiez que le fichier d'amorçage /tmp/grpc-xds/td-grpc-bootstrap.json correspond au schéma décrit dans la section Fichier d'amorçage.

  4. Téléchargez C++ gRPC et créez l'application serveur 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. Exécutez le serveur en utilisant 50051 comme port d'écoute et xds_greeter_server comme nom d'identification du serveur :

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

    Pour exécuter le serveur sans identifiants, vous pouvez spécifier les éléments suivants :

    bazel-bin/examples/cpp/helloworld/xds_greeter_server --nosecure
    
  6. Une fois que le serveur a obtenu la configuration nécessaire auprès de Traffic Director, vous obtenez le résultat suivant :

    Listening on port 50051
    Plaintext health service listening on port 50052
    

Python

  1. Obtenez le nom du pod créé pour le service example-grpc-server :

    kubectl get pods | grep example-grpc-server
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Ouvrez une interface système sur le pod de serveur :

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. Dans l'interface système, vérifiez que le fichier d'amorçage /tmp/grpc-xds/td-grpc-bootstrap.json correspond au schéma décrit dans la section Fichier d'amorçage.

  4. Téléchargez la version 1.41.0 de Python gRPC et créez l'exemple d'application.

    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. Exécutez le serveur avec l'option --xds-creds pour indiquer la sécurité compatible avec xDS en utilisant 50051 comme port d'écoute.

    python3 server.py 50051 --xds-creds
    
  6. Une fois que le serveur a obtenu la configuration nécessaire auprès de Traffic Director, vous obtenez le résultat suivant :

    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
    

Go

  1. Obtenez le nom du pod créé pour le service example-grpc-server :

    kubectl get pods | grep example-grpc-server
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Ouvrez une interface système sur le pod de serveur :

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
    
  3. Dans l'interface système, vérifiez que le fichier d'amorçage /tmp/grpc-xds/td-grpc-bootstrap.json correspond au schéma décrit dans la section Fichier d'amorçage.

  4. Téléchargez la version 1.41.0 de Go gRPC et accédez au répertoire contenant l'application de serveur 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. Créez et exécutez le serveur avec l'option --xds_creds pour indiquer d'utiliser la sécurité compatible xDS, avec comme port d'écoute 50051 :

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY="info" \
      go run main.go \
      -xds_creds \
      -port 50051
    
  6. Une fois que le serveur a obtenu la configuration nécessaire auprès de Traffic Director, vous obtenez le résultat suivant :

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

Le processus de vérification d'état prend entre trois et cinq minutes pour indiquer que votre service est opérationnel après le démarrage du serveur.

Exécuter le client et vérifier la configuration

Créez et exécutez le client helloworld compatible xDS dans le pod client que vous avez créé précédemment.

Java

  1. Obtenez le nom du pod client :

    kubectl get pods | grep example-grpc-client
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Ouvrez un shell sur le pod client :

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Dans le shell de commande, téléchargez la version 1.42.1 de Java gRPC, puis créez l'application 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. Exécutez le client avec l'option --xds-creds pour indiquer la sécurité compatible avec xDS, le nom du client et la chaîne de connexion cible :

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

    Le résultat doit ressembler à ce qui suit :

    Greeting: Hello xds-client, from xds-server
    

C++

  1. Obtenez le nom du pod client :

    kubectl get pods | grep example-grpc-client
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Ouvrez une interface système sur le pod client :

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Une fois dans l'interface système, téléchargez C++ gRPC et créez l'application 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. Exécutez le client avec l'option --xds-creds pour indiquer la sécurité compatible avec xDS, le nom du client et la chaîne de connexion cible :

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

    Pour exécuter le client sans identifiants, procédez comme suit :

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

    Le résultat doit ressembler à ce qui suit :

    Greeter received: Hello world
    

Python

  1. Obtenez le nom du pod client :

    kubectl get pods | grep example-grpc-client
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Ouvrez une interface système sur le pod client :

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Une fois dans l'interface système, téléchargez la version 1.41.0 de Python gRPC et créez l'exemple d'application cliente.

    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. Exécutez le client avec l'option --xds-creds pour indiquer la sécurité compatible avec xDS, le nom du client et la chaîne de connexion cible :

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

    Le résultat doit ressembler à ce qui suit :

    Greeter client received: Hello you from example-host!
    

Go

  1. Obtenez le nom du pod client :

    kubectl get pods | grep example-grpc-client
    

    Vous obtenez un résultat semblable à celui-ci :

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Ouvrez un shell sur le pod client :

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
    
  3. Une fois dans le shell, téléchargez la version 1.42.0 de Go gRPC et accédez au répertoire contenant l'application 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. Créez et exécutez le client avec l'option --xds_creds afin d'indiquer l'utilisation de la sécurité compatible xDS, le nom du client et la chaîne de connexion cible :

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

    Le résultat doit ressembler à ce qui suit :

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

Configurer l'accès au niveau du service avec une règle d'autorisation

La compatibilité avec la règle gRFC A41 est requise pour la stratégie d'autorisation. Vous trouverez les versions de langages requises sur github.

Suivez ces instructions pour configurer l'accès au niveau du service avec des règles d'autorisation. Avant de créer des règles d'autorisation, lisez la précaution de restreindre l'accès à l'aide d'une autorisation.

Pour faciliter la vérification de la configuration, créez un nom d'hôte supplémentaire que le client peut utiliser pour faire référence au service helloworld-gke.

gcloud compute url-maps add-host-rule grpc-gke-url-map \
   --path-matcher-name grpc-gke-path-matcher \
   --hosts helloworld-gke-noaccess:8000

Les instructions suivantes créent une règle d'autorisation qui autorise les requêtes envoyées par le compte example-grpc-client dans lequel le nom d'hôte est helloworld-gke:8000 et le port est 50051.

gcloud

  1. Créez une règle d'autorisation en créant un fichier nommé 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. Importez la stratégie.

    gcloud network-security authorization-policies import \
      helloworld-gke-authz-policy \
      --source=helloworld-gke-authz-policy.yaml \
      --location=global
    
  3. Mettez à jour la règle de point de terminaison pour référencer la nouvelle règle d'autorisation en ajoutant les éléments suivants au fichier ep-mtls-psms.yaml.

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

    La règle de point de terminaison spécifie maintenant que mTLS et la règle d'autorisation doivent être appliqués aux requêtes entrantes vers les pods dont les fichiers d'amorçage gRPC contiennent le libellé app:helloworld.

  4. Importez la stratégie :

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

Valider la règle d'autorisation

Suivez ces instructions pour vérifier que la règle d'autorisation fonctionne correctement.

Java

  1. Ouvrez un shell sur le pod client que vous avez utilisé précédemment.

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. Dans le shell, exécutez les commandes suivantes pour valider la configuration.

    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
    

    Le résultat doit ressembler à ce qui suit :

    Greeting: Hello xds-client, from xds-server
    
  3. Exécutez à nouveau le client avec le nom de serveur alternatif. Notez qu'il s'agit d'un cas d'échec. La requête n'est pas valide car la règle d'autorisation n'autorise l'accès qu'au nom d'hôte helloworld-gke:8000.

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

    Le résultat doit ressembler à ce qui suit :

    WARNING: RPC failed: Status{code=PERMISSION_DENIED}
    

    Si vous n'obtenez pas ce résultat, il est possible que la règle d'autorisation ne soit pas encore utilisée. Attendez quelques minutes et relancez le processus de vérification.

Go

  1. Ouvrez un shell sur le pod client que vous avez utilisé précédemment.

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. Dans le shell, exécutez les commandes suivantes pour valider la configuration.

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

    Le résultat doit ressembler à ce qui suit :

    Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
    
  3. Exécutez à nouveau le client avec le nom de serveur alternatif. Notez qu'il s'agit d'un cas d'échec. La requête n'est pas valide car la règle d'autorisation n'autorise l'accès qu'au nom d'hôte helloworld-gke:8000.

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

    Le résultat doit ressembler à ce qui suit :

    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
    

    Si vous n'obtenez pas ce résultat, il est possible que la règle d'autorisation ne soit pas encore utilisée. Attendez quelques minutes et relancez le processus de vérification.

Utiliser TLS au lieu de mTLS

Dans cet exemple, utiliser TLS ne nécessite qu'une légère modification.

  1. Dans ServerTlsPolicy, supprimez mtlsPolicy :

    cat << EOF > server-tls-policy.yaml
    name: "server-tls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    EOF
    
  2. Utilisez plutôt cette règle dans 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. La règle ClientTlsPolicy pour mTLS fonctionne également dans le cas du protocole TLS, mais la section clientCertificate de la règle peut être supprimée car elle n'est pas requise pour TLS :

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

Utiliser la sécurité du service avec l'exemple de portefeuille

Cette section explique sans entrer dans les détails comment activer l'exemple de portefeuille avec la sécurité du service pour Java, C++ et Go.

Java

Vous trouverez l'exemple de code source pour Java sur github. Le code utilise déjà les identifiants XdsChannel et XdsServer lorsque vous configurez la sécurité sans proxy.

Ces instructions décrivent comment configurer l'exemple de portefeuille avec Go. Le processus est le même pour Java. Les instructions utilisent une image Docker préexistante que vous obtenez dans le dépôt de conteneurs Google Cloud.

Pour créer l'exemple, procédez comme suit :

  1. Clonez le dépôt et déplacez les fichiers dans le répertoire d'exemples gRPC.
  2. Modifiez le fichier 00-common-env.sh. Mettez en commentaire la ligne existante qui définit la valeur de WALLET_DOCKER_IMAGE sur l'image Docker Go et annulez la mise en commentaire de la ligne qui définit la valeur de WALLET_DOCKER_IMAGE sur l'image Docker Java.
  3. Créez et configurez des instances Cloud Router en suivant les instructions de la section Créer et configurer des instances Cloud Router ou en utilisant la fonction create_cloud_router_instances du script 10.apis.sh.
  4. Créez un cluster en suivant les instructions de l'exemple hello world ou en utilisant la fonction create_cluster du script 20-cluster.sh.
  5. Créez des autorités de certification privées en suivant les instructions de CA Service ou en utilisant le script 30-private-ca-setup.sh.
  6. Créez des ressources Kubernetes, y compris des comptes de service, des espaces de noms, des services Kubernetes, des NEG et un déploiement côté serveur pour tous les services : account, stats, stats_premium, wallet_v1 et wallet_v2 à l'aide du script 40-k8s-resources.sh.
  7. Pour chacun des services que vous avez créés, créez une vérification d'état et un service de backend en utilisant create_health_check et create_backend_service dans le script 50-td-components.sh.
  8. Créez les composants de routage Traffic Director à l'aide de create_routing_components dans le script 60-routing-components.sh.
  9. Créez les composants de sécurité Traffic Director pour chaque service de backend à l'aide de create_security_components dans le script 70-security-components.sh.
  10. Créez le déploiement du portefeuille client à l'aide de create_client_deployment dans le script 75-client-deployment.sh.
  11. Vérifiez la configuration en lançant le client, comme décrit dans la section Vérifier avec les clients grpc-wallet.

C++

Vous trouverez l'exemple de code source pour C++ sur github. Le code utilise déjà les identifiants XdsChannel et XdsServer lorsque vous configurez la sécurité sans proxy.

Ces instructions décrivent comment configurer l'exemple de portefeuille avec Go. Le processus est semblable pour C++. Les instructions utilisent une image Docker préexistante que vous obtenez dans le dépôt de conteneurs Google Cloud.

Pour créer l'exemple, procédez comme suit :

  1. Clonez le dépôt et déplacez les fichiers dans le répertoire d'exemples gRPC.
  2. Modifiez le fichier 00-common-env.sh. Mettez en commentaire la ligne existante qui définit la valeur de WALLET_DOCKER_IMAGE sur l'image Docker Go et annulez la mise en commentaire de la ligne qui définit la valeur de WALLET_DOCKER_IMAGE sur l'image Docker C++.
  3. Créez et configurez des instances Cloud Router en suivant les instructions de la section Créer et configurer des instances Cloud Router ou en utilisant la fonction create_cloud_router_instances du script 10.apis.sh.
  4. Créez un cluster en suivant les instructions de l'exemple hello world ou en utilisant la fonction create_cluster du script 20-cluster.sh.
  5. Créez des autorités de certification privées en suivant les instructions de CA Service ou en utilisant le script 30-private-ca-setup.sh.
  6. Créez des ressources Kubernetes, y compris des comptes de service, des espaces de noms, des services Kubernetes, des NEG et un déploiement côté serveur pour tous les services : account, stats, stats_premium, wallet_v1 et wallet_v2 à l'aide du script 40-k8s-resources.sh.
  7. Pour chacun des services que vous avez créés, créez une vérification d'état et un service de backend en utilisant create_health_check et create_backend_service dans le script 50-td-components.sh.
  8. Créez les composants de routage Traffic Director à l'aide de create_routing_components dans le script 60-routing-components.sh.
  9. Créez les composants de sécurité Traffic Director pour chaque service de backend à l'aide de create_security_components dans le script 70-security-components.sh.
  10. Créez le déploiement du portefeuille client à l'aide de create_client_deployment dans le script 75-client-deployment.sh.
  11. Vérifiez la configuration en lançant le client, comme décrit dans la section Vérifier avec les clients grpc-wallet.

Go

Vous trouverez un exemple de code source pour Go sur github. Le code utilise déjà les identifiants XdsChannel et XdsServer lorsque vous configurez la sécurité sans proxy.

Les instructions utilisent une image Docker préexistante que vous obtenez dans le dépôt de conteneurs Google Cloud.

Pour créer l'exemple, procédez comme suit :

  1. Clonez le dépôt et déplacez les fichiers dans le répertoire d'exemples gRPC.
  2. Modifiez le fichier 00-common-env.sh afin de définir les valeurs appropriées pour les variables d'environnement.
  3. Créez et configurez des instances Cloud Router en suivant les instructions de la section Créer et configurer des instances Cloud Router ou en utilisant la fonction create_cloud_router_instances du script 10.apis.sh.
  4. Créez un cluster en suivant les instructions de l'exemple hello world ou en utilisant la fonction create_cluster du script 20-cluster.sh.
  5. Créez des autorités de certification privées en suivant les instructions de CA Service ou en utilisant le script 30-private-ca-setup.sh.
  6. Créez des ressources Kubernetes, y compris des comptes de service, des espaces de noms, des services Kubernetes, des NEG et un déploiement côté serveur pour tous les services : account, stats, stats_premium, wallet_v1 et wallet_v2 à l'aide du script 40-k8s-resources.sh.
  7. Pour chacun des services que vous avez créés, créez une vérification d'état et un service de backend en utilisant create_health_check et create_backend_service dans le script 50-td-components.sh.
  8. Créez les composants de routage Traffic Director à l'aide de create_routing_components dans le script 60-routing-components.sh.
  9. Créez les composants de sécurité Traffic Director pour chaque service de backend à l'aide de create_security_components dans le script 70-security-components.sh.
  10. Créez le déploiement du portefeuille client à l'aide de create_client_deployment dans le script 75-client-deployment.sh.
  11. Vérifiez la configuration en lançant le client, comme décrit dans la section Vérifier avec les clients grpc-wallet.

Fichier d'amorçage

Le processus de configuration de ce guide utilise un générateur d'amorçage pour créer le fichier d'amorçage requis. Cette section fournit des informations de référence sur le fichier d'amorçage lui-même.

Le fichier d'amorçage contient les informations de configuration requises par le code gRPC sans proxy, y compris les informations de connexion pour le serveur xDS. Le fichier d'amorçage contient la configuration de sécurité requise par la fonctionnalité de sécurité gRPC sans proxy. Le serveur gRPC nécessite un champ supplémentaire, comme décrit ci-dessous. Voici un exemple de fichier d'amorçage :

{
  "xds_servers": [
    {
      "server_uri": "trafficdirector.googleapis.com:443",
      "channel_creds": [
        {
          "type": "google_default"
        }
      ],
      "server_features": [
        "xds_v3"
      ]
    }
  ],
  "node": {
    "cluster": "cluster",
    "id": "projects/9876012345/networks/default/nodes/client1",
    "metadata": {
      "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER": "9876012345",
      "TRAFFICDIRECTOR_NETWORK_NAME": "default",
      "INSTANCE_IP": "10.0.0.3"
    },
    "locality": {
      "zone": "us-central1-a"
    }
  },
  "server_listener_resource_name_template": "grpc/server?xds.resource.listening_address=%s",
  "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"
      }
    }
  }
}

Mises à jour du fichier d'amorçage pour le service de sécurité

Les champs suivants reflètent les modifications liées à la sécurité et à l'utilisation de xDS v3 :

Le champ id dans node fournit une identité unique pour le client gRPC de Traffic Director. Vous devez fournir le numéro de projet Google Cloud et le nom du réseau à l'aide de l'ID de nœud au format suivant :

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

Par exemple, pour le projet numéro 1234, le réseau par défaut est :

projects/1234/networks/default/nodes/client1

Le champ INSTANCE_IP correspond à l'adresse IP du pod, ou bien 0.0.0.0 correspond à INADDR_ANY. Ce champ est utilisé par le serveur gRPC pour récupérer la ressource d'écouteur de Traffic Director pour la sécurité côté serveur.

Champs de configuration de la sécurité dans le fichier d'amorçage

Clé JSON Type Valeur Notes
server_listener_resource_name_template String grpc/server?xds.resource.listening_address=%s Obligatoire pour les serveurs gRPC. gRPC utilise cette valeur pour composer le nom de la ressource permettant de récupérer la ressource "Écouteur" depuis Traffic Director pour la sécurité côté serveur et d'autres configurations. gRPC l'utilise pour former la chaîne de nom de ressource
certificate_providers Structure JSON google_cloud_private_spiffe Obligatoire. La valeur est une structure JSON représentant un mappage de noms à des instances de fournisseur de certificats. Une instance de fournisseur de certificats est utilisée pour récupérer les certificats d'identité et racine. L'exemple de fichier d'amorçage contient un nom : google_cloud_private_spiffe ayant comme valeur la structure JSON de l'instance du fournisseur de certificat. La structure JSON de chaque instance de fournisseur de certificats comporte deux champs :
  • plugin_name : valeur obligatoire qui identifie le plug-in du fournisseur de certificats à utiliser comme exigé par l'architecture de plug-ins de gRPC pour les fournisseurs de certificats. gRPC possède une compatibilité intégrée avec le plug-in d'observation des fichiers utilisé dans cette configuration. Le nom du plug-in est file_watcher.
  • config : valeur obligatoire qui identifie le blog de configuration JSON pour le plug-in file_watcher. Le schéma et le contenu dépendent du plug-in.

La structure JSON config du plug-in file_watcher est la suivante :

  • certificate_file : chaîne obligatoire. Cette valeur correspond à l'emplacement du certificat d'identité.
  • private_key_file : chaîne obligatoire. La valeur correspond à l'emplacement du fichier de clé privée, qui doit correspondre au certificat d'identité.
  • ca_certificate_file : chaîne obligatoire. La valeur correspond à l'emplacement du certificat racine, également appelé bundle d'approbations.
  • refresh_interval : chaîne facultative. La valeur indique l'intervalle d'actualisation, spécifié à l'aide de la représentation sous forme de chaîne du mappage JSON d'une durée. La valeur par défaut est "600s", soit une durée de 10 minutes.

Générateur d'amorçage

L'image de conteneur du générateur d'amorçage est disponible sur gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.13.0. Son code source est disponible à l'adresse https://github.com/GoogleCloudPlatform/traffic-director-grpc-bootstrap. Les options de ligne de commande les plus couramment utilisées sont les suivantes :

  • --output : utilisez cette option pour spécifier l'emplacement où le fichier d'amorçage de sortie est écrit. Par exemple, la commande --output /tmp/bootstrap/td-grpc-bootstrap.json génère le fichier d'amorçage pour /tmp/bootstrap/td-grpc-bootstrap.json dans le système de fichiers du pod.
  • --node-metadata : utilisez cette option pour renseigner les métadonnées du nœud dans le fichier d'amorçage. Cela est nécessaire lorsque vous utilisez des outils de mise en correspondance de libellés de métadonnées dans EndpointPolicy, où {td_name_short}} utilise les données de libellés fournies dans la section des métadonnées de nœud du fichier d'amorçage. L'argument est fourni au format clé=valeur, par exemple : --node-metadata version=prod --node-metadata type=grpc

Ce qui précède ajoute les éléments suivants dans la section des métadonnées du nœud du fichier d'amorçage :

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

Supprimer le déploiement

Vous pouvez éventuellement exécuter ces commandes pour supprimer le déploiement que vous avez créé à l'aide de ce guide.

Pour supprimer le cluster, exécutez la commande suivante :

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

Pour supprimer les ressources que vous avez créées, exécutez les commandes suivantes :

gcloud compute backend-services delete grpc-gke-helloworld-service --global --quiet
cloud 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

Dépannage

Utilisez ces instructions pour vous aider à résoudre les problèmes de déploiement de sécurité.

Les charges de travail ne parviennent pas à obtenir la configuration à partir de Traffic Director

Si vous voyez une erreur semblable à celle-ci :

PERMISSION_DENIED: Request had insufficient authentication scopes.

Assurez-vous que :

  • Vous avez créé votre cluster GKE avec l'argument --scopes=cloud-platform.
  • Vous avez attribué roles/trafficdirector.client à vos comptes de service Kubernetes.
  • Vous avez attribué le roles/trafficdirector.client à votre compte de service Google Cloud par défaut (${GSA_EMAIL} ci-dessus).
  • Vous avez activé le service trafficdirector.googleapis.com (API).

Votre serveur gRPC n'utilise pas le protocole TLS/mTLS, même avec la configuration Traffic Director appropriée

Assurez-vous de spécifier GRPC_SERVER dans la configuration de vos règles de point de terminaison. Si vous avez spécifié SIDECAR_PROXY, gRPC ignore la configuration.

Vous ne pouvez pas créer le cluster GKE avec la version de cluster demandée

La commande de création du cluster GKE peut échouer et renvoyer une erreur semblable à celle-ci :

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

Assurez-vous d'utiliser l'argument --release-channel rapid dans votre commande de création de cluster. Vous devez utiliser la version précoce pour obtenir la version appropriée.

Une erreur No usable endpoint s'affiche.

Si un client ne peut pas communiquer avec le serveur en raison d'une erreur No usable endpoint, il est possible que le vérificateur d'état ait signalé les backends du serveur comme non opérationnels. Pour vérifier l'état des backends, exécutez la commande gcloud suivante :

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

Si la commande renvoie l'état du backend non opérationnel, cela peut être dû à l'une des raisons suivantes :

  • Le pare-feu n'a pas été créé ou ne contient pas la plage d'adresses IP source appropriée.
  • Les tags cibles de votre pare-feu ne correspondent pas aux tags du cluster que vous avez créé.

Les charges de travail ne parviennent pas à communiquer dans la configuration de sécurité

Si vos charges de travail ne parviennent pas à communiquer après que vous avez configuré la sécurité de votre maillage de services sans proxy, suivez ces instructions pour en déterminer la cause.

  1. Désactivez la sécurité sans proxy et éliminez les problèmes dans les cas d'utilisation de l'équilibrage de charge du maillage de services sans proxy. Pour désactiver la sécurité dans le maillage, effectuez l'une des opérations suivantes :
    1. Utilisez des identifiants en texte brut côté client et serveur, OU
    2. Ne configurez pas la sécurité du service de backend et de la règle de point de terminaison dans la configuration de Traffic Director.

Suivez les étapes décrites dans la section Résoudre les problèmes de déploiement sans proxy de Traffic Director, car votre déploiement ne comporte aucune configuration de sécurité.

  1. Modifiez vos charges de travail de manière à utiliser des identifiants xDS avec des identifiants en texte brut ou non sécurisés comme identifiants de remplacement. Gardez la sécurité désactivée dans la configuration de Traffic Director comme indiqué ci-dessus. Dans ce cas, bien que gRPC autorise Traffic Director à configurer la sécurité, celui-ci n'envoie pas d'informations de sécurité. Dans ce cas, gRPC doit revenir à des identifiants en texte brut (ou non sécurisés), ce qui devrait fonctionner de manière similaire au premier cas ci-dessus. Si ce cas ne fonctionne pas, procédez comme suit :

    1. Augmentez le niveau de journalisation côté client et côté serveur afin de pouvoir voir les messages xDS échangés entre gRPC et Traffic Director.
    2. Assurez-vous que Traffic Director n'a pas la sécurité activée dans les réponses CDS et LDS envoyées aux charges de travail.
    3. Assurez-vous que les charges de travail n'utilisent pas les modes TLS ou mTLS dans leurs canaux. Si des messages de journal liés aux handshakes TLS s'affichent, vérifiez le code source de votre application et assurez-vous d'utiliser des identifiants de remplacement non sécurisés ou en texte brut. Si le code source de l'application est correct, il peut s'agir d'un bug dans la bibliothèque gRPC.
  2. Vérifiez que l'intégration du service CA avec GKE fonctionne correctement pour votre cluster GKE en suivant les étapes de dépannage décrites dans ce guide de l'utilisateur. Assurez-vous que les certificats et les clés fournis par cette fonctionnalité sont disponibles dans le répertoire spécifié, /var/run/secrets/workload-spiffe-credentials/.

  3. Activez TLS (au lieu de mTLS) dans votre réseau maillé, comme décrit ci-dessus, puis redémarrez vos charges de travail client et serveur.

    1. Augmentez le niveau de journalisation côté client et côté serveur afin de pouvoir voir les messages xDS échangés entre gRPC et Traffic Director.
    2. Assurez-vous que Traffic Director a bien activé la sécurité dans les réponses CDS et LDS envoyées aux charges de travail.

Le client échoue avec une erreur CertificateException et affiche un message Peer certificate SAN check failed

Cela indique un problème avec les valeurs subjectAltNames du message SecuritySettings. Notez que ces valeurs sont basées sur les services Kubernetes que vous avez créés pour votre service de backend. Chaque service Kubernetes que vous avez créé est associé à un ID SPIFFE, au format suivant :

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

Ces valeurs sont les suivantes :

  • WORKLOAD_POOL : pool de charges de travail du cluster, lui-même ${PROJECT_ID}.svc.id.goog
  • K8S_NAMESPACE : espace de noms Kubernetes que vous avez utilisé dans le déploiement du service
  • SERVICE_ACCOUNT : compte de service Kubernetes que vous avez utilisé dans le déploiement du service

Pour chaque service Kubernetes que vous avez associé à votre service de backend en tant que groupe de points de terminaison du réseau, assurez-vous que vous avez correctement calculé l'ID SPIFFE et que vous l'avez ajouté au champ subjectAltNames dans le message SecuritySettings.

Les applications ne peuvent pas utiliser les certificats mTLS avec votre bibliothèque gRPC

Si vos applications ne peuvent pas utiliser les certificats mTLS avec votre bibliothèque gRPC, procédez comme suit :

  1. Vérifiez que la spécification de pod contient l'annotation security.cloud.google.com/use-workload-certificates décrite dans la section Créer un service gRPC sans proxy avec des NEG.

  2. Vérifiez que les fichiers contenant la chaîne de certificats ainsi que le certificat feuille, la clé privée et les certificats CA approuvés sont accessibles depuis les chemins d'accès suivants à partir du pod :

    1. Chaîne de certificats avec le certificat feuille : "/var/run/secrets/workload-spiffe-credentials/certificates.pem"
    2. Clé privée : "/var/run/secrets/workload-spiffe-credentials/private_key.pem"
    3. Bundle CA : "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem"
  3. Si les certificats de l'étape précédente ne sont pas disponibles, procédez comme suit :

      gcloud privateca subordinates describe SUBORDINATE_CA_POOL_NAME 
    --location=LOCATION

    1. Vérifiez que le plan de contrôle de GKE dispose de la liaison de rôle IAM correcte, en lui accordant l'accès au service 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. Vérifiez que le certificat n'a pas expiré. Il s'agit de la chaîne de certificats et du certificat feuille à l'emplacement /var/run/secrets/workload-spiffe-credentials/certificates.pem. Pour vérifier cela, exécutez la commande suivante :

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

    3. Vérifiez que le type de clé est compatible avec votre application en exécutant la commande suivante :

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

    4. Vérifiez que votre application Java gRPC dispose de la propriété keyAlgorithm suivante dans le fichier YAML WorkloadCertificateConfig :

      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
  4. Vérifiez que l'autorité de certification utilise la même famille de clés que la clé de certificat.

Le certificat d'une application est refusé par le client, le serveur ou le pair

  1. Vérifiez que l'application similaire utilise le même bundle d'approbations pour valider le certificat.
  2. Vérifiez que le certificat utilisé n'a pas expiré (chaîne de certificats avec le certificat feuille : "/var/run/secrets/workload-spiffe-credentials/certificates.pem").

###

Si les pods restent en attente pendant l'installation, augmentez les ressources de processeur et de mémoire des pods dans la spécification de votre déploiement.

Impossible de créer un cluster avec l'option --enable-mesh-certificates

Vérifiez que vous exécutez la dernière version de gcloud CLI :

gcloud components update

Notez que l'option --enable-mesh-certificates ne fonctionne qu'avec gcloud beta.

Les pods ne démarrent pas

Les pods qui utilisent des certificats de maillage GKE peuvent ne pas démarrer en cas d'échec du provisionnement de certificats. Cela peut se produire dans les situations suivantes :

  • La configuration WorkloadCertificateConfig ou TrustConfig est mal configurée ou est manquante.
  • Les CSR (Certificats Signing Request, demande de signature de certificat) ne sont pas approuvés.

Vous pouvez vérifier si le provisionnement du certificat échoue en vérifiant les événements du pod.

  1. Vérifiez l'état de votre pod :

    kubectl get pod -n POD_NAMESPACE POD_NAME
    

    Remplacez les éléments suivants :

    • POD_NAMESPACE : espace de noms de votre pod.
    • POD_NAME : nom de votre pod.
  2. Vérifiez les événements récents pour votre pod :

    kubectl describe pod -n POD_NAMESPACE POD_NAME
    
  3. Si le provisionnement du certificat échoue, vous verrez un événement avec Type=Warning, Reason=FailedMount, From=kubelet et un champ Message commençant par MountVolume.SetUp failed for volume "gke-workload-certificates". Le champ Message contient des informations de dépannage.

    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. Suivez les étapes de dépannage suivantes si vos pods ne démarrent pas en raison d'objets mal configurés ou de requêtes de signature de certificat refusées.

WorkloadCertificateConfig ou TrustConfig est mal configuré

Assurez-vous que vous avez correctement créé les objets WorkloadCertificateConfig et TrustConfig. Vous pouvez diagnostiquer les erreurs de configuration de ces objets à l'aide de kubectl.

  1. Récupérer l'état actuel

    Pour WorkloadCertificateConfig :

    kubectl get WorkloadCertificateConfig default -o yaml
    

    Pour TrustConfig :

    kubectl get TrustConfig default -o yaml
    
  2. Inspectez le résultat de l'état. Un objet valide sera associé à une condition avec type: Ready et status: "True".

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

    Pour les objets non valides, status: "False" apparaît à la place. Le champ reason et message contiennent des informations de dépannage supplémentaires.

Les demandes de signature de certificat ne sont pas approuvées

Si une erreur se produit lors du processus d'approbation CSR, vous pouvez vérifier les détails de l'erreur dans les conditions type: Approved et type: Issued de la requête de signature de certificat.

  1. Répertoriez les requêtes de signature de certificat pertinentes à l'aide de kubectl :

    kubectl get csr \
      --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
    
  2. Choisissez une requête de signature de certificat qui soit Approved, et pas Issued, ou qui n'est pas Approved.

  3. Obtenez les détails de la requête de signature de certificat sélectionnée via kubectl :

    kubectl get csr CSR_NAME -o yaml
    

    Remplacez CSR_NAME par le nom de la requête de signature de certificat que vous avez choisie.

Une requête de signature de certificat valide comporte une condition avec type: Approved et status: "True", ainsi qu'un certificat valide dans le champ 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

Les informations de dépannage pour les requête de signature de certificat non valides apparaissent dans les champs message et reason.

Il manque des certificats dans les pods.

  1. Obtenez la spécification de pod de votre pod :

    kubectl get pod -n POD_NAMESPACE POD_NAME -o yaml
    

    Remplacez les éléments suivants :

    • POD_NAMESPACE : espace de noms de votre pod.
    • POD_NAME : nom de votre pod.
  2. Vérifiez que la spécification de pod contient l'annotation security.cloud.google.com/use-workload-certificates décrite dans la section Configurer les pods pour recevoir les identifiants mTLS.

  3. Vérifiez que le contrôleur d'admission des certificats de maillage GKE a injecté un volume de pilote CSI de type workloadcertificates.security.cloud.google.com dans la spécification de votre pod :

    volumes:
    ...
    -csi:
      driver: workloadcertificates.security.cloud.google.com
      name: gke-workload-certificates
    ...
    
  4. Vérifiez la présence d'un montage de volume dans chacun des conteneurs :

    containers:
    - name: ...
      ...
      volumeMounts:
      - mountPath: /var/run/secrets/workload-spiffe-credentials
        name: gke-workload-certificates
        readOnly: true
      ...
    
  5. Vérifiez que les groupes de certificats et la clé privée suivants sont disponibles aux emplacements suivants dans le pod :

    • Bundle de chaînes de certificats : /var/run/secrets/workload-spiffe-credentials/certificates.pem
    • Clé privée : /var/run/secrets/workload-spiffe-credentials/private_key.pem
    • Bundle d'ancrages de confiance CA : /var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
  6. Si les fichiers ne sont pas disponibles, procédez comme suit :

    1. Récupérez l'instance de service CA (Preview) du cluster :

      kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'
      
    2. Récupérez l'état de l'instance du service CA (Preview) :

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Remplacez les éléments suivants :

      • ISSUING_CA_TYPE : type d'autorité de certification émettrice, qui doit être subordinates ou roots.
      • ISSUING_CA_NAME : nom de l'autorité de certification émettrice.
      • ISSUING_CA_LOCATION : région de l'autorité de certification émettrice.
    3. Obtenez la stratégie IAM pour l'autorité de certification racine :

      gcloud privateca roots get-iam-policy ROOT_CA_NAME
      

      Remplacez ROOT_CA_NAME par le nom de votre autorité de certification racine.

    4. Dans la stratégie IAM, vérifiez que la liaison de stratégie privateca.auditor existe bien :

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

      Dans cet exemple, PROJECT_NUMBER est le numéro de projet de votre cluster.

    5. Obtenez la stratégie IAM pour l'autorité de certification subordonnée :

      gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAME
      

      Remplacez SUBORDINATE_CA_NAME par le nom de l'autorité de certification subordonnée.

    6. Dans la stratégie IAM, vérifiez que la liaison de stratégie privateca.certificateManager existe :

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

      Dans cet exemple, PROJECT_NUMBER est le numéro de projet de votre cluster.

Les applications ne peuvent pas utiliser les identifiants mTLS émis

  1. Vérifiez que le certificat n'a pas expiré :

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  2. Vérifiez que le type de clé que vous avez utilisé est compatible avec votre application.

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
    
  3. Vérifiez que l'autorité de certification émettrice utilise la même famille de clés que la clé de certificat.

    1. Obtenez l'état de l'instance du service CA (Preview) :

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Remplacez les éléments suivants :

      • ISSUING_CA_TYPE : type d'autorité de certification émettrice, qui doit être subordinates ou roots.
      • ISSUING_CA_NAME : nom de l'autorité de certification émettrice.
      • ISSUING_CA_LOCATION : région de l'autorité de certification émettrice.
    2. Vérifiez que keySpec.algorithm dans le résultat est le même algorithme de clé que vous avez défini dans le WorkloadCertificateConfig Fichier manifeste YAML. Le résultat ressemble à ceci :

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

Les certificats sont refusés

  1. Vérifiez que l'application similaire utilise le même bundle d'approbations pour valider le certificat.
  2. Vérifiez que le certificat n'a pas expiré :

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  3. Vérifiez que le code client, si vous n'utilisez pas l'API d'actualisation des identifiants gRPC Go, actualise régulièrement les identifiants depuis le système de fichiers.

  4. Vérifiez que vos charges de travail appartiennent au même domaine de confiance que votre autorité de certification. Les certificats de maillage GKE acceptent la communication entre les charges de travail d'un même domaine de confiance.

Limites

La sécurité du service Traffic Director n'est compatible qu'avec GKE. Vous ne pouvez pas déployer la sécurité des services avec Compute Engine.

Traffic Director n'est pas compatible avec les scénarios dans lesquels deux ressources de règles de point de terminaison ou plus correspondent à un même point de terminaison (par exemple, deux règles ayant les mêmes libellés et ports, ou bien deux règles ou plus ayant des libellés différents qui correspondent de manière identique aux libellés d'un point de terminaison). Pour en savoir plus sur la mise en correspondance des règles de point de terminaison avec les libellés d'un point de terminaison, consultez les API pour EndpointPolicy.EndpointMatcher.MetadataLabelMatcher. Dans de telles situations, Traffic Director ne génère aucune configuration de sécurité basée sur les règles en conflit.