Protéger les métadonnées d'un cluster

Présentation

GKE utilise des métadonnées d'instance pour configurer les machines virtuelles des nœuds, mais certaines de ces métadonnées sont potentiellement sensibles et doivent être protégées des charges de travail exécutées sur le cluster.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

Configurez les paramètres gcloud par défaut à l'aide de l'une des méthodes suivantes :

  • Utilisez gcloud init pour suivre les instructions permettant de définir les paramètres par défaut.
  • Utilisez gcloud config pour définir individuellement l'ID, la zone et la région de votre projet.

Utiliser gcloud init

Si le message d'erreur One of [--zone, --region] must be supplied: Please specify location s'affiche, effectuez les tâches ci-dessous.

  1. Exécutez gcloud init et suivez les instructions :

    gcloud init

    Si vous utilisez SSH sur un serveur distant, utilisez l'option --console-only pour empêcher la commande d'ouvrir un navigateur :

    gcloud init --console-only
  2. Suivez les instructions pour autoriser gcloud à utiliser votre compte Google Cloud.
  3. Créez ou sélectionnez une configuration.
  4. Choisissez un projet Google Cloud.
  5. Choisissez une zone Compute Engine par défaut.

Utiliser gcloud config

  • Définissez votre ID de projet par défaut :
    gcloud config set project project-id
  • Si vous utilisez des clusters zonaux, définissez votre zone de calcul par défaut :
    gcloud config set compute/zone compute-zone
  • Si vous utilisez des clusters régionaux, définissez votre région de calcul par défaut :
    gcloud config set compute/region compute-region
  • Mettez à jour gcloud vers la dernière version :
    gcloud components update

Configurer le compte de service des nœuds

Étant donné que les identifiants du compte de service de chaque nœud continueront à être exposés aux charges de travail, vous devez prendre soin de configurer un compte de service ne détenant que les autorisations minimales requises. Associez ensuite ce compte de service à vos nœuds, de sorte qu'un hacker ne puisse pas contourner les protections de métadonnées de GKE en utilisant l'API Compute Engine pour accéder directement aux instances de nœud.

N'utilisez pas de comptes de service dotés de l'autorisation compute.instances.get, du rôle "Administrateur d'instances Compute", ni d'autres autorisations comparables, car cela donnerait aux éventuels pirates informatiques la possibilité d'obtenir des métadonnées d'instance via l'API Compute Engine. La bonne pratique consiste à restreindre les autorisations d'une VM de nœud en utilisant des autorisations de compte de service, et non des niveaux d'accès. Pour plus d'informations, consultez la documentation sur les comptes de service Compute Engine.

Si vous ne possédez pas de compte de service de nœud, vous pouvez en créer un à l'aide des commandes suivantes :

export NODE_SA_NAME=gke-node-sa
gcloud iam service-accounts create $NODE_SA_NAME \
  --display-name "Node Service Account"
export NODE_SA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \
  --filter='displayName:Node Service Account')

Pour configurer ce compte de service avec les rôles et les autorisations nécessaires, exécutez les commandes suivantes, où PROJECT correspond à l'ID de votre projet :

export PROJECT=$(gcloud config get-value project)

gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/monitoring.metricWriter
gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/monitoring.viewer
gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/logging.logWriter

De plus, si votre cluster extrait des images privées de Container Registry, ajoutez le rôle storage.objectViewer :

gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/storage.objectViewer

Désactiver les anciennes API de métadonnées et effectuer une migration

Les points de terminaison du serveur de métadonnées v1beta1 et v0.1 de Compute Engine sont obsolètes et doivent être arrêtés. Veillez à mettre à jour toutes les requêtes de sorte qu'elles utilisent le point de terminaison v1.

Le serveur de métadonnées d'instance de Compute Engine expose les anciens points de terminaison v0.1 et v1beta1, qui n'assurent pas l'application forcée des en-têtes de requête de métadonnées. Il s'agit d'une fonctionnalité des API v1, qui rend plus difficile la récupération de métadonnées d'instance par un éventuel pirate informatique. À moins qu'elles ne soient spécifiquement requises, nous vous recommandons de désactiver ces anciennes API.

La prochaine section explique comment effectuer les tâches suivantes :

  • Identifier les nœuds qui accèdent aux points de terminaison obsolètes. S'ils utilisent les points de terminaison obsolètes, vous devez migrer ces nœuds.

  • Créer un cluster ou un pool de nœuds avec les anciens points de terminaison du serveur de métadonnées désactivés pour les nœuds concernés.

Identifier des nœuds à l'aide des anciens points de terminaison du serveur de métadonnées

L'outil check-legacy-endpoint-access vous permet d'identifier les nœuds Kubernetes Engine qui utilisent les anciens points de terminaison du serveur de métadonnées. Lorsqu'il est appliqué dans votre cluster, cet outil enregistre toutes les cinq minutes l'intégralité des requêtes envoyées par vos nœuds aux points de terminaison v0.1 et v1beta1. Cet outil permet également d'identifier, de déboguer et de valider l'utilisation des anciens points de terminaison dans Kubernetes Engine.

Pour configurer l'outil check-legacy-endpoint-access, procédez comme suit :

  1. Dans chacun de vos clusters, exécutez la commande suivante :

    kubectl apply -f \
    https://raw.githubusercontent.com/GoogleCloudPlatform\
    /k8s-node-tools/master/check-legacy-endpoint-access/check-legacy-endpoint-access.yaml
  2. Interrogez les journaux collectés à l'aide des informations d'utilisation de l'ancien point de terminaison. Pour interroger les journaux, dans chaque cluster, exécutez la commande suivante :

    kubectl -n kube-system logs -l \
    app=check-legacy-endpoint-access | grep "access count"

Vous pouvez également consulter les journaux collectés dans Stackdriver Logging.

  1. Accédez à la page Stackdriver Logging > Journaux (Visionneuse de journaux) dans Cloud Console :

    Accéder à la page Visionneuse de journaux

  2. Appliquez le filtre suivant :

    resource.type="container"
    resource.labels.namespace_id="kube-system"
    logName:"/check-legacy-endpoint-access"

    Accéder à la vue filtrée

  3. Après avoir identifié les nœuds, vous devez déterminer les processus qui utilisent ces points de terminaison. Pour en savoir plus sur l'identification de ces processus, consultez la section Identifier les processus.

  4. Migrez ces processus de manière à utiliser le point de terminaison du serveur de métadonnées v1. Pour en savoir plus sur la migration de vos nœuds Compute Engine et sur les différences de points de terminaison, consultez la section Migrer vers le point de terminaison du serveur de métadonnées v1.

  5. Supprimez le DaemonSet check-legacy-endpoint-access :

    kubectl delete daemonset check-legacy-endpoint-access -n kube-system

Créer un pool de nœuds en désactivant les anciennes API de métadonnées

Après avoir créé un compte de service, vous pouvez créer un pool de nœuds (ou un pool de nœuds par défaut dans un nouveau cluster) dans lequel les anciennes API de métadonnées sont désactivées, à l'aide de l'outil de ligne de commande gcloud.

Pour créer un pool de nœuds en désactivant les anciennes API de métadonnées, utilisez l'option --metadata disable-legacy-endpoints=true. Exemple :

gcloud container node-pools create pool-name \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true

Ce même indicateur vous permet de créer un cluster dans lequel les anciennes API de métadonnées sont désactivées au sein du pool de nœuds par défaut. Exemple :

gcloud container clusters create cluster-name \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true

Mettre à jour un cluster existant pour désactiver les anciennes API de métadonnées

Après avoir créé un pool de nœuds dans lequel les anciennes API de métadonnées sont désactivées, vous pouvez mettre à jour un cluster existant de sorte qu'il utilise ce pool de nœuds, en procédant comme indiqué dans le guide de migration des pools de nœuds.

Vérifier que les anciennes API de métadonnées sont désactivées

Lorsque les anciennes API de métadonnées d'instance sont désactivées, les requêtes envoyées aux points de terminaison de serveur de métadonnées /0.1/ et /v1beta1/ renvoient l'erreur 403 Forbidden.

Pour vérifier que les anciennes API de métadonnées ont bien été désactivées, vous pouvez exécuter une commande curl depuis un pod :

root@pod-name# curl -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/attributes/disable-legacy-endpoints'
true
root@pod-name# curl 'http://metadata.google.internal/computeMetadata/v1beta1/instance/id'
... Error 403 (Forbidden) ... Legacy metadata endpoint accessed: /computeMetadata/v1beta1/instance/id Legacy metadata endpoints are disabled. Please use the /v1/ endpoint. ...

Dissimuler des métadonnées

La fonctionnalité de dissimulation de métadonnées de GKE permet de protéger certaines métadonnées système potentiellement sensibles contre les charges de travail d'utilisateur exécutées sur votre cluster.

Dans Kubernetes version 1.9.3 ou ultérieure, vous pouvez activer la dissimulation de métadonnées pour empêcher les pods des utilisateurs d'accéder à certaines métadonnées de VM se rapportant aux nœuds de votre cluster, telles que les identifiants Kubelet et les informations sur les instances de VM. Plus précisément, la dissimulation de métadonnées protège l'accès à kube-env (qui contient les identifiants Kubelet) et au jeton d'identité d'instance.

La dissimulation de métadonnées joue le rôle de pare-feu n'autorisant que les requêtes sécurisées dans le trafic allant des pods d'utilisateur (c'est-à-dire les pods non exécutés sur HostNetwork) au serveur de métadonnées du cluster. Ce pare-feu empêche les pods d'utilisateur d'exploiter les identifiants Kubelet pour des attaques d'élévation des privilèges, ou les identifiants de la VM pour des attaques d'élévation d'instance.

Limites

  • La dissimulation de métadonnées ne protège l'accès qu'à kube-env et au jeton d'identité d'instance du nœud.
  • La dissimulation de métadonnées ne limite pas l'accès au compte de service du nœud.
  • La dissimulation de métadonnées ne limite pas l'accès à d'autres métadonnées d'instance associées.
  • La dissimulation de métadonnées ne limite pas l'accès à d'autres anciennes API de métadonnées.

Créer un cluster ou un pool de nœuds avec dissimulation de métadonnées

Après avoir créé un compte de service, vous pouvez créer un cluster avec la fonctionnalité de dissimulation de métadonnées activée, à l'aide de l'outil de ligne de commande gcloud.

Pour créer un cluster avec la dissimulation de métadonnées activée, exécutez la commande suivante dans la fenêtre de votre interface système ou de votre terminal :

gcloud beta container clusters create cluster-name \
  --workload-metadata-from-node=SECURE \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true \
  [additional parameters and flags omitted]

où :

  • cluster-name est le nom du cluster à créer.
  • --workload-metadata-from-node est défini sur SECURE. Le fait de définir cette option sur EXPOSED ou UNSPECIFIED désactive la dissimulation de métadonnées.

Vérifier que les métadonnées de jeton d'identité sont dissimulées pour la charge de travail du cluster

Lorsque vous dissimulez des métadonnées, il ne doit pas être possible de demander une signature via le jeton d'identité d'instance du nœud. Pour vous assurer que les requêtes informent explicitement les utilisateurs du fait que des métadonnées sont dissimulées, vous pouvez exécuter une commande curl depuis un pod :

root@pod-name# curl -H "Metadata-Flavor: Google" \
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://www.example.com'
This metadata endpoint is concealed.