Configurer la sécurité du service avec Envoy

Suivez les instructions de ce guide pour configurer l'authentification et l'autorisation des services déployés avec Cloud Service Mesh et des proxys Envoy. Pour obtenir des informations complètes sur la sécurité du service Cloud Service Mesh, consultez la section Sécurité du service Cloud Service Mesh.

Conditions requises

Avant de configurer la sécurité du service pour Cloud Service Mesh avec Envoy, assurez-vous que votre configuration remplit les conditions préalables suivantes :

Préparer la configuration

Les sections suivantes décrivent les tâches que vous devez effectuer avant de configurer Service de sécurité Cloud Service Mesh Ces tâches sont les suivantes :

  • Mettre à jour Google Cloud CLI
  • Configurer des variables
  • Activer les API nécessaires au fonctionnement de Cloud Service Mesh Certificate Authority Service

Mettre à jour l'outil de ligne de commande gcloud

Pour mettre à jour Google Cloud CLI, exécutez la commande suivante sur votre ordinateur local :

gcloud components update

Configurer les variables

Définissez les variables suivantes pour pouvoir copier et coller du code avec des valeurs cohérentes, au fur et à mesure que vous suivez l'exemple de ce document. Utilisez les valeurs suivantes :

  • PROJECT_ID : substituez l'ID de votre projet
  • CLUSTER_NAME : remplacez le nom du cluster que vous souhaitez utiliser, par exemple, secure-td-cluster.
  • ZONE : remplacez la zone dans laquelle se trouve votre cluster.
  • GKE_CLUSTER_URL : remplacez https://container.googleapis.com/v1/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER_NAME
  • WORKLOAD_POOL : remplacez PROJECT_ID.svc.id.goog
  • K8S_NAMESPACE : remplacez default
  • DEMO_CLIENT_KSA : remplacez le nom du compte de service Kubernetes de votre client.
  • DEMO_SERVER_KSA : remplacez le nom du compte de service Kubernetes de votre serveur.
  • PROJNUM : remplacez le numéro de votre projet que vous pouvez déterminez à partir de Google Cloud Console ou de la commande suivante :

    gcloud projects describe PROJECT_ID --format="value(projectNumber)"
    
  • SA_GKE : remplacez service-PROJNUM@container-engine-robot.iam.gserviceaccount.com

  • CLUSTER_VERSION : substituez la version la plus récente disponible. Vous pouvez trouver cette information dans les notes de version de canal rapide. La version minimale requise est la version 1.21.4-gke.1801. Il s'agit de la version du cluster GKE à utiliser dans cet exemple.

Définissez les valeurs ici :

# Substitute your project ID
PROJECT_ID=PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME=CLUSTER_NAME
ZONE=ZONE

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

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

# Kubernetes namespace to run client and server demo.
K8S_NAMESPACE=K8S_NAMESPACE
DEMO_CLIENT_KSA=DEMO_CLIENT_KSA
DEMO_SERVER_KSA=DEMO_SERVER_KSA

# Compute other values
# Project number for your project
PROJNUM=PROJNUM

CLUSTER_VERSION=CLUSTER_VERSION
SA_GKE=service-PROJNUM@container-engine-robot.iam.gserviceaccount.com

Activer les API

Utilisez le gcloud services enable permettant d'activer toutes les API dont vous avez besoin pour configurer Cloud Service Mesh avec Certificate Authority Service.

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

Créer ou mettre à jour un cluster GKE

La sécurité du service Cloud Service Mesh dépend du service CA l'intégration à 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 la fédération d'identité de charge de travail pour GKE. Si vous mettez à jour un cluster existant, passez à l'étape suivante. La valeur que vous indiquez pour --tags doit correspondre au nom transmis à l'option --target-tags pour la commande firewall-rules create dans la section Configurer Cloud Service Mesh avec des composants d'équilibrage de charge Cloud.

    # 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 la fédération d'identité de charge de travail pour GKE et les certificats de maillage 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
    

Déployer dans un environnement multicluster

Si vous effectuez un déploiement dans un environnement multicluster, suivez la procédure générale décrite dans cette section. Dans ces instructions, nous partons du principe que les pods client s'exécutent dans un cluster et que les pods serveur s'exécutent dans l'autre cluster.

  1. Créez ou mettez à jour les clusters en suivant les instructions de la section précédente.

  2. Capturez les plages d'adresses IP des pods pour chaque cluster à l'aide de la commande suivante :

    gcloud compute firewall-rules list \
      --filter="name~gke-{CLUSTER_NAME}-[0-9a-z]*-all" \
      --format="value(sourceRanges)"
    

    Par exemple, pour les clusters appelés cluster-a et cluster-b, les commandes renvoient des résultats tels que ceux-ci :

    cluster-a, pod CIDR: 10.4.0.0/14, node network tag: gke-cluster-a-9cd18751-node
    cluster-b, pod CIDR: 10.8.0.0/14, node network tag: gke-cluster-b-acd14479-node
    
  3. Créez des règles de pare-feu VPC permettant aux clusters de communiquer entre eux. Par exemple, la commande suivante crée une règle de pare-feu permettant aux adresses IP des pods cluster-a de communiquer avec les nœuds cluster-b :

    gcloud compute firewall-rules create per-cluster-a-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-b-acd14479-node"
    

    La commande suivante crée une règle de pare-feu permettant aux adresses IP des pods cluster-b de communiquer avec les nœuds cluster-a :

    gcloud compute firewall-rules create per-cluster-b-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-a-9cd18751-node"
    

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
    

    comme suit :

    • CLUSTER_NAME : nom de votre cluster
    • ZONE : zone de votre cluster.
    • MANIFEST-FILE_NAME: chemin d'accès où ces commandes générer 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 Workoad Identity attribué par le parc, où PROJECT_ID est 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. Accorder à des personnes le rôle role/privateca.admin pour Certificate Authority Service qui doivent modifier les stratégies IAM, où MEMBER est un qui a besoin de cet accès, en particulier toute personne les étapes qui suivent pour accorder les autorisations privateca.auditor et Rôles 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 s'exécute votre cluster :
      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 s'exécute votre cluster :
      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
    

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

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.

Si ces autorisations sont appliquées à l'avenir et que vous utilisez le compute.NetworkAdmin, vous ne remarquerez aucun problème lors de cette vérification est appliquée.

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. Sinon, à l'avenir, il se peut que votre rôle personnalisé ne dispose pas des autorisations nécessaires pour faire référence à clientTlsPolicy ou serverTlsPolicy à partir du service de backend, ou stratégie des points de terminaison.

Les instructions suivantes permettent au compte de service par défaut d'accéder API Cloud Service Mesh Security et créer les comptes de service Kubernetes.

  1. Configurez IAM pour permettre au compte de service par défaut d'accéder à l'API de sécurité Cloud Service Mesh.

    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
    
  2. Configurez les comptes de service Kubernetes. Dans les sections suivantes, les déploiements client et serveur utilisent les noms "K" des comptes de service du serveur et du client Kubernetes.

    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_SERVER_KSA
    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_CLIENT_KSA
    
  3. Autorisez les comptes de service Kubernetes à emprunter l'identité du compte de service Compute Engine par défaut en créant une liaison de stratégie IAM entre eux. Cette liaison permet au compte de service Kubernetes d'agir en tant que compte de service Compute Engine par défaut.

    gcloud iam service-accounts add-iam-policy-binding  \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/DEMO_SERVER_KSA]" ${GSA_EMAIL}
    
    gcloud iam service-accounts add-iam-policy-binding  \
      --role roles/iam.workloadIdentityUser  \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/DEMO_CLIENT_KSA]" ${GSA_EMAIL}
    
  4. Annotez les comptes de service Kubernetes pour les associer au compte par défaut compte de service Compute Engine.

    kubectl annotate --namespace K8S_NAMESPACE \
      serviceaccount DEMO_SERVER_KSA \
      iam.gke.io/gcp-service-account=${GSA_EMAIL}
    
    kubectl annotate --namespace K8S_NAMESPACE \
      serviceaccount DEMO_CLIENT_KSA \
      iam.gke.io/gcp-service-account=${GSA_EMAIL}
    

Configurer Cloud Service Mesh

Suivez les instructions ci-dessous pour installer l'injecteur side-car, configurer un service de test et effectuer d'autres tâches de déploiement.

Installer l'injecteur side-car Envoy dans le cluster

Suivez les instructions des deux sections suivantes Configuration de Cloud Service Mesh pour les pods GKE avec injection Envoy automatique pour déployer et activer l'injection side-car Envoy dans votre cluster:

Veillez à suivre les deux ensembles d'instructions avant de configurer un service de test.

Configurer un service de test

Une fois que vous avez installé l'injecteur side-car Envoy, suivez les instructions ci-dessous pour configurer un service de test pour votre déploiement.

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/service_sample.yaml | sed -e s/DEMO_SERVER_KSA_PLACEHOLDER/DEMO_SERVER_KSA/g > service_sample.yaml

kubectl apply -f service_sample.yaml

Le fichier service_sample.yaml contient le podspec de votre application de serveur de démonstration. Certaines annotations sont spécifiques à la sécurité Cloud Service Mesh.

Métadonnées du proxy Cloud Service Mesh

Le podspec spécifie l'annotation proxyMetadata :

spec:
...
      annotations:
        cloud.google.com/proxyMetadata: '{"app": "payments"}'
...

Lorsque le pod est initialisé, le proxy side-car récupère cette annotation et la transmet à Cloud Service Mesh. Cloud Service Mesh peut alors utiliser Informations pour renvoyer la configuration filtrée:

  • Plus loin dans ce guide, notez que la règle de point de terminaison spécifie un outil de mise en correspondance des points de terminaison.
  • L'outil de mise en correspondance des points de terminaison spécifie que seuls les clients qui présentent une étiquette portant le nom app et la valeur payments reçoivent la configuration filtrée.

Utiliser des certificats et des clés de maillage signés par le service CA

Le podspec spécifie l'annotation enableManagedCerts :

spec:
...
      annotations:
        ...
        cloud.google.com/enableManagedCerts: "true"
...

Une fois le pod initialisé, CA Service a signé des certificats et sont automatiquement installées sur le système de fichiers du proxy side-car local.

Configurer le port d'interception du trafic entrant

Le podspec spécifie l'annotation includeInboundPorts :

spec:
...
      annotations:
        ...
        cloud.google.com/includeInboundPorts: "8000"
...

C'est le port sur lequel votre application de serveur écoute les connexions. Une fois le pod initialisé, le proxy side-car extrait cette annotation et la transmet à Cloud Service Mesh. Cloud Service Mesh peut ensuite utiliser ces informations pour renvoyer la configuration filtrée, qui intercepte tout le trafic entrant vers ce port et peut y appliquer des règles de sécurité.

Le port de la vérification d'état doit être différent du port de l'application. Dans le cas contraire, les mêmes règles de sécurité s'appliquent aux connexions entrantes vers le port de vérification d'état, ce qui peut entraîner le refus des connexions, ce qui entraîne que le serveur soit faussement indiqué comme étant non opérationnel.

Configurer des services GKE avec des NEG

Les services GKE doivent être exposés via des groupes de points de terminaison du réseau (NEG) afin de pouvoir les configurer en tant que backends d'un backend Cloud Service Mesh Google Cloud. Le package service_sample.yaml fourni avec ce guide de configuration utilise le nom NEG service-test-neg dans l'annotation suivante :

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "service-test-neg"}}}'
spec:
  ports:
  - port: 80
    name: service-test
    protocol: TCP
    targetPort: 8000

Vous n'avez pas besoin de modifier le fichier service_sample.yaml.

Enregistrer le nom du NEG

Enregistrez le nom du NEG dans la variable NEG_NAME:

NEG_NAME="service-test-neg"

Déployer une application cliente sur GKE

Exécutez la commande suivante pour lancer un client de démonstration avec un proxy Envoy en tant que side-car, dont vous avez besoin pour démontrer les fonctionnalités de sécurité.

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/client_sample.yaml | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_KSA/g > client_sample.yaml

kubectl apply -f client_sample.yaml

Le podspec du client n'inclut que l'annotation enableManagedCerts. Cette étape est nécessaire pour installer les volumes nécessaires pour les clés et certificats de maillage gérés par GKE signés par l'instance de service CA.

Configurer la vérification de l'état, la règle de pare-feu et les ressources du service de backend

Dans cette section, vous allez créer une vérification de l'état, une règle de pare-feu et un service de backend. pour Cloud Service Mesh.

  1. Créez la vérification d'état.

    gcloud compute health-checks create http td-gke-health-check \
      --use-serving-port
    
  2. Créez la règle de pare-feu pour autoriser les plages d'adresses IP du vérificateur d'état.

    gcloud compute firewall-rules create fw-allow-health-checks \
       --action ALLOW \
       --direction INGRESS \
       --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --rules tcp
    
  3. Créez le service de backend et associez la vérification d'état au service de backend.

    gcloud compute backend-services create td-gke-service \
      --global \
      --health-checks td-gke-health-check \
      --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  4. Ajoutez le NEG créé précédemment en tant que backend au service de backend.

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

Configurer les ressources Mesh et HTTPRoute

Dans cette section, vous allez créer des ressources Mesh et HTTPRoute.

  1. Créez la spécification de ressource Mesh et enregistrez-la dans un fichier nommé mesh.yaml.

    name: sidecar-mesh
    interceptionPort: 15001
    

    Le port d'interception est défini par défaut sur 15001 si vous ne le spécifiez pas dans le fichier mesh.yaml.

  2. Créez la ressource Mesh à l'aide de la spécification mesh.yaml.

    gcloud network-services meshes import sidecar-mesh \
      --source=mesh.yaml \
      --location=global
    
  3. Créez la spécification HTTPRoute et enregistrez-la dans un fichier nommé http_route.yaml.

    Vous pouvez utiliser PROJECT_ID ou PROJECT_NUMBER.

    name: helloworld-http-route
    hostnames:
    - service-test
    meshes:
    - projects/PROJNUM/locations/global/meshes/sidecar-mesh
    rules:
    - action:
       destinations:
       - serviceName: "projects/PROJNUM/locations/global/backendServices/td-gke-service"
    
  4. Créez la ressource HTTPRoute à l'aide de la spécification du fichier http_route.yaml.

    gcloud network-services http-routes import helloworld-http-route \
      --source=http_route.yaml \
      --location=global
    

La configuration de Cloud Service Mesh est terminée, et vous pouvez configurer d'authentification et d'autorisation.

Configurer la sécurité entre les services

Suivez les instructions des sections suivantes pour configurer la sécurité de service à service.

Activer l'authentification mTLS dans le réseau maillé

Pour configurer l'authentification mTLS dans votre réseau maillé, vous devez sécuriser le trafic sortant vers le service de backend et le trafic entrant vers le point de terminaison.

Format des références aux règles

Notez le format requis suivant pour faire référence aux règles TLS des serveurs, des clients et règles d'autorisation :

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

Exemple :

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

Sécuriser le trafic sortant vers le service de backend

Pour sécuriser le trafic sortant, vous devez d'abord créer une règle TLS client qui effectue les opérations suivantes :

  • Utilise google_cloud_private_spiffe comme plug-in pour clientCertificate, ce qui programme Envoy afin d'utiliser des certificats de maillage gérés par GKE comme identité client.
  • utilise google_cloud_private_spiffe comme plug-in pour serverValidationCa, qui programme Envoy pour utiliser les certificats de maillage gérés par GKE pour la validation du serveur.

Ensuite, vous associez la règle TLS du client au service de backend. Les opérations suivantes s'effectuent alors :

  • Applique la règle d'authentification de la règle TLS du client aux connexions sortantes vers les points de terminaison du service de backend.
  • SAN (Subject Alternative Names) demande au client de valider l'identité exacte du serveur auquel il se connecte.
  1. Créez la règle TLS du client dans un fichier client-mtls-policy.yaml :

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Importez la règle TLS du client :

    gcloud network-security client-tls-policies import client-mtls-policy \
        --source=client-mtls-policy.yaml --location=global
    
  3. Associez la règle TLS du client au service de backend. L'authentification mTLS est appliquée à toutes les requêtes sortantes du client vers ce service de backend.

    gcloud compute backend-services export td-gke-service \
        --global --destination=demo-backend-service.yaml
    

    Ajoutez les lignes suivantes à demo-backend-service.yaml :

    securitySettings:
      clientTlsPolicy: projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
      subjectAltNames:
        - "spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA"
    
  4. Importez les valeurs :

    gcloud compute backend-services import td-gke-service \
        --global --source=demo-backend-service.yaml
    
  5. Vous pouvez éventuellement exécuter la commande suivante pour vérifier si la requête échoue. Il s'agit d'un échec attendu, car le client attend des certificats du point de terminaison, mais le point de terminaison n'est pas programmé avec une règle de sécurité.

    # Get the name of the Podrunning Busybox.
    BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')
    
    # Command to execute that tests connectivity to the service service-test.
    TEST_CMD="wget -q -O - service-test; echo"
    
    # Execute the test command on the pod.
    kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"
    

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

    wget: server returned error: HTTP/1.1 503 Service Unavailable
    

Sécuriser le trafic entrant vers le point de terminaison

Pour sécuriser le trafic entrant, vous devez d'abord créer une règle TLS de serveur qui effectue les opérations suivantes :

  • Utilise google_cloud_private_spiffe comme plug-in pour serverCertificate, qui programme Envoy afin d'utiliser des certificats de maillage gérés par GKE comme identité de serveur.
  • utilise google_cloud_private_spiffe en tant que plug-in pour clientValidationCa, qui programme Envoy pour utiliser les certificats de maillage gérés par GKE pour la validation du client.
  1. Enregistrez les valeurs de la règle TLS du serveur dans un fichier nommé server-mtls-policy.yaml.

    name: "server-mtls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    mtlsPolicy:
      clientValidationCa:
      - certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
    
  2. Créez la règle TLS du serveur :

    gcloud network-security server-tls-policies import server-mtls-policy \
        --source=server-mtls-policy.yaml --location=global
    
  3. Créez un fichier nommé ep_mtls.yaml contenant la mise en correspondance des points de terminaison et associez la règle TLS du serveur.

    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: MATCH_ALL
        metadataLabels:
        - labelName: app
          labelValue: payments
    name: "ep"
    serverTlsPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy
    type: SIDECAR_PROXY
    
  4. Importez l'outil de mise en correspondance des points de terminaison.

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

Valider la configuration

Exécutez la commande curl suivante : Si la requête aboutit, le message x-forwarded-client-cert s'affiche dans le résultat. L'en-tête n'est imprimé que si la connexion est une connexion mTLS.

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

Vous obtenez le résultat similaire suivant : .

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: 10.48.0.6
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA

Notez que l'en-tête x-forwarded-client-cert est inséré par Envoy côté serveur et contient sa propre identité (serveur) et l'identité du client source. Comme nous voyons à la fois l'identité du client et du serveur, cela indique une connexion mTLS.

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

Ces instructions créent une règle d'autorisation qui autorise les requêtes envoyées par le compte DEMO_CLIENT_KSA dans lequel le nom d'hôte est service-test, le port est 8000 et la méthode HTTP est GET. Avant de créer des règles d'autorisation, lisez la précaution de restreindre l'accès à l'aide d'une autorisation.

  1. Créez une règle d'autorisation en créant un fichier nommé authz-policy.yaml.

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
      destinations:
      - hosts:
        - service-test
        ports:
        - 8000
        methods:
        - GET
    
  2. Importez la stratégie :

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

    authorizationPolicy: projects/PROJECT_ID/locations/global/authorizationPolicies/authz-policy
    

    La règle de point de terminaison spécifie désormais que mTLS et la règle d'autorisation doivent être appliqués aux requêtes entrantes vers les pods dont les proxys side-car Envoy présentent le libellé app:payments.

  4. Importez la stratégie :

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

Valider la configuration

Exécutez les commandes suivantes pour valider la configuration.

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
# This is a valid request and will be allowed.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

Le résultat attendu est semblable à ceci :

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: redacted
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA

Exécutez les commandes suivantes pour vérifier si la règle d'autorisation refuse correctement les requêtes non valides :

# Failure case
# Command to execute that tests connectivity to the service service-test.
# This is an invalid request and server will reject because the server
# authorization policy only allows GET requests.
TEST_CMD="wget -q -O - service-test --post-data='' ; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

Le résultat attendu est semblable à ceci :

<RBAC: access denied HTTP/1.1 403 Forbidden>

Configurer des règles d'autorisation sur les side-cars sur GKE

Cette section explique comment configurer différents types de stratégies d'autorisation sur les sidecars Cloud Service Mesh sur GKE.

Avant de pouvoir créer une règle d'autorisation, vous devez installer la CustomResourceDefinition (CRD) GCPAuthzPolicy :

curl https://github.com/GoogleCloudPlatform/gke-networking-recipes/blob/main/gateway-api/config/mesh/crd/experimental/gcpauthzpolicy.yaml \
| kubectl apply -f -

Règle d'autorisation pour refuser les requêtes

Lorsque votre charge de travail est censée n'effectuer que des appels sortants, job Cron, vous pouvez configurer une règle d'autorisation pour refuser toute demande HTTP à la charge de travail. L'exemple suivant refuse les requêtes HTTP entrantes vers la charge de travail example-app.

Pour créer et appliquer la règle de refus d'autorisation, procédez comme suit:

  1. Créez une règle personnalisée en créant un fichier nommé deny-all-authz-policy.yaml:

    cat >deny-all-authz-policy.yaml <<EOF
    apiVersion: networking.gke.io/v1
    kind: GCPAuthzPolicy
    metadata:
      name: my-workload-authz
      namespace: ns1
    spec:
    targetRefs:
    - kind: Deployment
      name: example-app
    httpRules:
    - to:
        operations:
        - paths:
          - type: Prefix
            value: "/"
    action: DENY
    EOF
    
  2. Appliquez la règle :

    kubectl apply -f deny-all-authz-policy.yaml
    

Stratégie d'autorisation pour autoriser les requêtes

Vous pouvez également configurer une règle d'autorisation qui n'autorise que les requêtes correspondant à des critères spécifiques tout en rejetant le reste. L'exemple suivant configure une stratégie d'autorisation sur le déploiement example-app pour n'autoriser que les requêtes mTLS provenant des pods avec l'identité spiffee://cluster.local/ns1/pod1.

Pour créer et appliquer la stratégie d'autorisation d'accès, procédez comme suit :

  1. Créez une règle personnalisée en créant un fichier nommé allow-authz-policy.yaml:

    cat >allow-authz-policy.yaml <<EOF
    apiVersion: networking.gke.io/v1
    kind: GCPAuthzPolicy
    metadata:
      name: my-workload-authz
      namespace: ns1
    spec:
    targetRefs:
    - kind: Deployment
      name: example-app
    httpRules:
    - from:
        sources:
        - principals:
          - type: Exact
            value: "spiffee://cluster.local/ns1/pod1"
    action: ALLOW
    EOF
    
  2. Appliquez la règle :

    kubectl apply -f allow-authz-policy.yaml
    

Configurer la sécurité de la passerelle d'entrée

Cette section suppose que vous avez terminé la section de sécurité de service à service, y compris la configuration de votre cluster GKE avec l'injecteur automatique side-car, la création d'une autorité de certification et la création d'une règle de point de terminaison.

Dans cette section, vous déployez un proxy Envoy en tant que passerelle d'entrée qui met fin aux connexions TLS et autorise les requêtes provenant des clients internes d'un cluster.

Arrêt de TLS sur une passerelle d&#39;entrée (cliquez pour agrandir)
Arrêt TLS au niveau d'une passerelle d'entrée (cliquez pour agrandir)

Pour configurer une passerelle d'entrée pour interrompre le protocole TLS, procédez comme suit :

  1. déployer un service Kubernetes accessible via une adresse IP interne de cluster ;
    1. Le déploiement consiste en un proxy Envoy autonome exposé en tant que service Kubernetes et se connecte à Cloud Service Mesh.
  2. Créez une règle TLS de serveur permettant d'arrêter TLS.
  3. Créez une règle d'autorisation pour autoriser les requêtes entrantes.

Déployer un service de passerelle d'entrée sur GKE

Exécutez la commande suivante pour déployer le service de passerelle d'entrée sur GKE :

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/gateway_sample_xdsv3.yaml | sed -e s/PROJECT_NUMBER_PLACEHOLDER/PROJNUM/g | sed -e s/NETWORK_PLACEHOLDER/default/g | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_KSA/g > gateway_sample.yaml

kubectl apply -f gateway_sample.yaml

Le fichier gateway_sample.yaml correspond à la spécification de la passerelle d'entrée. Les sections suivantes décrivent certaines ajouts à la spécification.

Désactiver l'injection side-car Cloud Service Mesh

La spécification gateway_sample.yaml déploie un proxy Envoy en tant que conteneur unique. Lors des étapes précédentes, Envoy a été injecté en tant que side-car dans un conteneur d'applications. Pour éviter que plusieurs services Envoy gèrent les requêtes, vous pouvez désactiver l'injection side-car pour ce service Kubernetes à l'aide de l'instruction suivante :

sidecar.istio.io/inject: "false"

Installer le volume approprié

La spécification gateway_sample.yaml installe le volume gke-workload-certificates. Ce volume est également utilisé dans le déploiement side-car, mais il est automatiquement ajouté par l'injecteur side-car lorsqu'il voit l'annotation cloud.google.com/enableManagedCerts: "true". Le volume gke-workload-certificates contient les certificats et clés SPIFFE gérés par GKE et signés par l'instance de service CA que vous avez configurée.

Définir l'adresse IP interne du cluster

Configurez la passerelle d'entrée avec un service de type ClusterInternal. Cela crée un nom d'hôte DNS pouvant être résolu en interne pour mesh-gateway. Lorsqu'un client envoie une requête à mesh-gateway:443, Kubernetes l'achemine immédiatement vers le port 8080 du déploiement Envoy de la passerelle d'entrée.

Activer TLS sur une passerelle d'entrée

Suivez ces instructions pour activer TLS sur une passerelle d'entrée.

  1. Créez une ressource de règle TLS de serveur pour interrompre les connexions TLS, avec les valeurs dans un fichier appelé server-tls-policy.yaml :

    description: tls server policy
    name: server-tls-policy
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Importez la règle TLS du serveur :

    gcloud network-security server-tls-policies import server-tls-policy \
        --source=server-tls-policy.yaml --location=global
    
  3. Créez une cible Gateway et enregistrez-la dans le fichier td-gke-gateway.yaml. Cela associe la règle TLS du serveur et configure la passerelle d'entrée du proxy Envoy pour qu'elle mette fin au trafic TLS entrant.

    name: td-gke-gateway
    scope: gateway-proxy
    ports:
    - 8080
    type: OPEN_MESH
    serverTLSPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
    
  4. Importez la passerelle :

    gcloud network-services gateways import td-gke-gateway \
      --source=td-gke-gateway.yaml \
      --location=global
    
  5. Créez et enregistrez un nouvel élément HTTPRoute appelé td-gke-route, qui référence la passerelle et achemine toutes les requêtes vers td-gke-service.

    name: td-gke-route
    hostnames:
    - mesh-gateway
    gateways:
    - projects/PROJECT_NUMBER/locations/global/gateways/td-gke-gateway
    rules:
    - action:
        destinations:
        - serviceName: "projects/PROJECT_NUMBER/locations/global/backendServices/td-gke-service"
    
  6. Importez HTTPRoute :

    gcloud network-services httproutes import td-gke-route \
      --source=td-gke-route.yaml \
      --location=global
    
    
  7. Vous pouvez éventuellement mettre à jour la règle d'autorisation sur les backends pour autoriser les requêtes lorsque toutes les conditions suivantes sont remplies :

    • Requêtes envoyées par DEMO_CLIENT_KSA (Le déploiement de la passerelle d'entrée utilise le compte de service DEMO_CLIENT_KSA.)
    • Requêtes avec l'hôte mesh-gateway ou service-test
    • Port : 8000

    Vous n'avez pas besoin d'exécuter ces commandes, sauf si vous avez configuré une règle d'autorisation pour vos backends. S'il n'y a pas de règle d'autorisation sur le point de terminaison ou s'il ne contient pas de correspondance principale hôte ou source dans la stratégie d'autorisation, la requête est autorisée sans cette étape. Ajoutez ces valeurs à authz-policy.yaml.

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
      destinations:
      - hosts:
        - service-test
        - mesh-gateway
        ports:
        - 8000
        methods:
        - GET
    
  8. Importez la stratégie :

    gcloud network-security authorization-policies import authz-policy \
      --source=authz-policy.yaml \
      --location=global
    

Valider le déploiement de la passerelle d'entrée

Utilisez un nouveau conteneur appelé debug pour envoyer des requêtes à la passerelle d'entrée afin de valider le déploiement.

Dans la spécification suivante, l'annotation "sidecar.istio.io/inject":"false" conserve l'injecteur side-car Cloud Service Mesh d'injecter automatiquement un side-car proxy. Il n'y a pas de side-car pour aider le conteneur debug dans le routage des requêtes. Le conteneur doit se connecter à la passerelle d'entrée pour le routage.

La spécification inclut l'indicateur --no-check-certificate, qui ignore la validation du certificat serveur. Le conteneur debug ne dispose pas des certificats de validation d'autorité de certification nécessaires pour les certificats valides signés par le service CA, qui sont utilisés par la passerelle d'entrée pour interrompre le protocole TLS.

Dans un environnement de production, nous vous recommandons de télécharger le certificat de validation du service CA, puis de l'installer sur votre client. Après avoir installé le certificat de validation, supprimez l'option --no-check-certificate de la commande wget.

Exécutez la commande suivante :

kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway; echo"

Un résultat semblable à celui-ci s'affiche :

GET / HTTP/1.1
Host: 10.68.7.132
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
x-envoy-expected-rq-timeout-ms: 15000
x-envoy-internal: true
x-request-id: 5ae429e7-0e18-4bd9-bb79-4e4149cf8fef
x-forwarded-for: 10.64.0.53
x-forwarded-proto: https
content-length: 0
user-agent: Wget

Exécutez la commande de test négatif suivante :

# Negative test
# Expect this to fail because gateway expects TLS.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - http://mesh-gateway:443/headers; echo"

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

wget: error getting response: Connection reset by peer

Exécutez la commande de test négatif suivante :

# Negative test.
# AuthorizationPolicy applied on the endpoints expect a GET request. Otherwise
# the request is denied authorization.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway --post-data=''; echo"

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

HTTP/1.1 403 Forbidden
wget: server returned error: HTTP/1.1 403 Forbidden

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 td-gke-service --global --quiet
cloud compute network-endpoint-groups delete service-test-neg --zone ZONE --quiet
gcloud compute firewall-rules delete fw-allow-health-checks --quiet
gcloud compute health-checks delete td-gke-health-check --quiet
gcloud network-services endpoint-policies delete ep \
    --location=global --quiet
gcloud network-security authorization-policies delete authz-gateway-policy \
   --location=global --quiet
gcloud network-security authorization-policies delete 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

Limites

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

Dépannage

Cette section explique comment résoudre les problèmes que vous rencontrez lors de la configuration du service de sécurité.

Échecs de connexion

Si la connexion échoue avec une erreur upstream connect ou une erreur disconnect/reset before headers, examinez les journaux Envoy, qui peuvent contenir l'un des messages de journal suivants :

gRPC config stream closed: 5, Requested entity was not found

gRPC config stream closed: 2, no credential token is found

Si ces erreurs apparaissent dans le journal Envoy, il est probable que le jeton du compte de service soit mal installé, qu'il utilise un autre audience, ou les deux.

Pour en savoir plus, consultez la section Les messages d'erreur dans les journaux Envoy indiquent un problème de configuration.

Pods non créés

Pour résoudre ce problème, consultez la page Résoudre des problèmes de déploiement automatique pour les pods GKE.

Envoy ne s'authentifie pas avec Cloud Service Mesh

Lorsque Envoy (envoy-proxy) se connecte à Cloud Service Mesh pour récupérer le xDS utilise la fédération d'identité de charge de travail pour GKE et la VM Compute Engine le compte de service par défaut (sauf si le démarrage a été modifié). Si l'authentification échoue, Envoy ne passe pas à l'état prêt.

Impossible de créer un cluster avec --workload-identity-certificate-authority flag

Si cette erreur s'affiche, assurez-vous que vous exécutez la version la plus récente de Google Cloud CLI :

gcloud components update

Les pods restent à l'état "en attente"

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 l'élément suivant :

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

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 l'élément suivant :

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