Appliquer des règles de sécurité prédéfinies au niveau du pod à l'aide de PodSecurity


Cette page vous explique comment appliquer des contrôles de sécurité prédéfinis au niveau du pod dans vos clusters Google Kubernetes Engine (GKE) à l'aide du contrôleur d'admission PodSecurity.

Pour plus d'informations sur le fonctionnement de PodSecurity, reportez-vous à la section Admission de sécurité des pods.

Présentation

PodSecurity est un contrôleur d'admission Kubernetes qui vous permet d'appliquer les normes de sécurité des pods aux pods exécutés sur vos clusters GKE. Les normes de sécurité des pods sont des règles de sécurité prédéfinies qui répondent aux besoins de sécurité élevés des pods dans Kubernetes. Ces règles peuvent être très permissives ou très restrictives.

Vous pouvez appliquer les normes de sécurité de pod suivantes à vos clusters GKE :

  • Privilégiées : règle sans restriction qui fournit le niveau d'autorisation le plus large. Autorise les élévations des privilèges connues.
  • De référence : règle faiblement restrictive qui autorise la configuration de pod minimale par défaut. Empêche les élévations des privilèges connues.
  • Limitées : règle hautement restrictive qui suit les bonnes pratiques de renforcement des pods.

Vous pouvez utiliser le contrôleur d'admission PodSecurity pour appliquer les normes de sécurité des pods dans les modes suivants :

  • Application : tout non-respect des règles empêche la création de pods. Un événement d'audit est ajouté au journal d'audit.
  • Audit : tout non-respect des règles déclenche l'ajout d'un événement d'audit au journal d'audit. La création de pods est autorisée.
  • Avertissement : tout non-respect des règles déclenche un avertissement destiné à l'utilisateur. La création de pods est autorisée.

Le contrôleur d'admission PodSecurity intègre ces règles à l'API Kubernetes.

Si vous souhaitez créer et appliquer des règles de sécurité personnalisées au niveau du pod, envisagez plutôt d'utiliser le contrôleur d'admission Gatekeeper.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande gcloud components update.

Exigences

Le contrôleur d'admission PodSecurity est disponible et activé par défaut sur les clusters exécutant les versions GKE suivantes :

  • Version 1.25 ou ultérieure : version stable
  • Versions 1.23 et 1.24 : version bêta

Pour vérifier si une version de GKE est disponible et s'il s'agit de la version disponible par défaut, consultez le calendrier des versions.

Appliquer les normes de sécurité des pods à l'aide de PodSecurity

Pour utiliser le contrôleur d'admission PodSecurity, vous devez appliquer des normes de sécurité des pods spécifiques, dans des modes spécifiques, à des espaces de noms spécifiques. Pour ce faire, vous pouvez utiliser des libellés d'espaces de noms. Dans cet exercice, vous allez effectuer les opération suivantes :

  • Créer deux espaces de noms
  • Appliquer des règles de sécurité à chaque espace de noms
  • Tester les règles configurées

Dans les versions suivantes de GKE, GKE ignore les règles que vous appliquez à l'espace de noms kube-system :

  • 1.23.6-gke.1900 et versions ultérieures
  • 1.24.0-gke.1200 et versions ultérieures

Dans les versions antérieures de GKE, évitez d'appliquer des règles dans kube-system.

Créer des espaces de noms

Créez des espaces de noms dans votre cluster :

kubectl create ns baseline-ns
kubectl create ns restricted-ns

Cette commande crée les espaces de noms suivants :

  • baseline-ns : pour les charges de travail permissives
  • restricted-ns : pour les charges de travail hautement limitées

Utiliser des libellés pour appliquer des règles de sécurité

Appliquez les normes de sécurité des pods suivantes :

  • baseline : à appliquer à baseline-ns en mode warn
  • restricted : à appliquer à restricted-ns en mode enforce
kubectl label --overwrite ns baseline-ns pod-security.kubernetes.io/warn=baseline
kubectl label --overwrite ns restricted-ns pod-security.kubernetes.io/enforce=restricted

Ces commandes permettent d'obtenir le résultat suivant :

  • Les charges de travail de l'espace de noms baseline-ns qui ne respectent pas la règle baseline sont autorisées, et le client affiche un message d'avertissement.
  • Les charges de travail de l'espace de noms restricted-ns qui ne respectent pas la règle restricted sont rejetées, et GKE ajoute une entrée aux journaux d'audit.

Vérifiez que les libellés ont été ajoutés :

kubectl get ns --show-labels

Le résultat ressemble à ce qui suit :

baseline-ns       Active   74s   kubernetes.io/metadata.name=baseline-ns,pod-security.kubernetes.io/warn=baseline
restricted-ns     Active   18s   kubernetes.io/metadata.name=restricted-ns,pod-security.kubernetes.io/enforce=restricted
default           Active   57m   kubernetes.io/metadata.name=default
kube-public       Active   57m   kubernetes.io/metadata.name=kube-public
kube-system       Active   57m   kubernetes.io/metadata.name=kube-system

Tester les règles configurées

Pour vérifier que le contrôleur d'admission PodSecurity fonctionne comme prévu, déployez une charge de travail qui ne respecte pas les règles baseline et restricted sur les deux espaces de noms. L'exemple de fichier manifeste suivant déploie un conteneur nginx qui permet l'élévation des privilèges.

  1. Enregistrez le manifeste suivant sous le nom psa-workload.yaml :

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    
  2. Appliquez le fichier manifeste à l'espace de noms baseline-ns :

    kubectl apply -f psa-workload.yaml --namespace=baseline-ns
    

    Le résultat ressemble à ce qui suit :

    Warning: would violate PodSecurity "baseline:latest": privileged (container "nginx" must not set securityContext.privileged=true)
    

    La règle baseline permet au pod de se déployer dans l'espace de noms.

  3. Vérifiez que le pod a bien été déployé :

    kubectl get pods --namespace=baseline-ns -l=app=nginx
    
  4. Appliquez le fichier manifeste à l'espace de noms restricted-ns :

    kubectl apply -f psa-workload.yaml --namespace=restricted-ns
    

    Le résultat ressemble à ce qui suit :

    Error from server (Forbidden): error when creating "workload.yaml": pods "nginx"
    is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation
    != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false),
    unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]),
    runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true),
    seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type
    to "RuntimeDefault" or "Localhost")
    

    Le pod ne se déploie pas dans l'espace de noms. Une entrée d'audit est ajoutée au journal.

Afficher les violations des règles dans les journaux d'audit

Tout non-respect des règles en mode audit et enforce est enregistré dans les journaux d'audit de votre cluster. Vous pouvez afficher ces journaux à l'aide de l'explorateur de journaux de Google Cloud Console.

  1. Accédez à l'explorateur de journaux dans la console Google Cloud.

    Accéder à l'explorateur de journaux

  2. Dans le champ Requête, procédez comme suit pour récupérer les journaux d'audit en mode audit ou enforce :

    resource.type="k8s_cluster"
    protoPayload.resourceName:"/pods/nginx"
    protoPayload.methodName="io.k8s.core.v1.pods.create"
    (labels."pod-security.kubernetes.io/audit-violations":"PodSecurity" OR protoPayload.response.reason="Forbidden")
    
  3. Cliquez sur Exécuter la requête.

  4. Dans la section Résultats de la requête, développez l'entrée de journal Forbidden pour inspecter les journaux de rejet du mode enforce. Les informations se présentent comme suit :

    {
      ...
      protoPayload: {
        @type: "type.googleapis.com/google.cloud.audit.AuditLog"
        authenticationInfo: {1}
        authorizationInfo: [1]
        methodName: "io.k8s.core.v1.pods.create"
        request: {6}
        requestMetadata: {2}
        resourceName: "core/v1/namespaces/restricted-ns/pods/nginx"
        response: {
          @type: "core.k8s.io/v1.Status"
          apiVersion: "v1"
          code: 403
          details: {2}
          kind: "Status"
          message: "pods "nginx" is forbidden: violates PodSecurity "restricted:latest": privileged
                  (container "nginx" must not set securityContext.privileged=true),
                  allowPrivilegeEscalation != false (container "nginx" must set
                  securityContext.allowPrivilegeEscalation=false), unrestricted capabilities
                  (container "nginx" must set securityContext.capabilities.drop=["ALL"]),
                  runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true),
                  seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type
                  to "RuntimeDefault" or "Localhost")"
          metadata: {0}
          reason: "Forbidden"
          status: "Failure"
          }
          serviceName: "k8s.io"
          status: {2}
        }
      receiveTimestamp: "2022-02-01T19:19:25.353235326Z"
      resource: {2}
      timestamp: "2022-02-01T19:19:21.469360Z"
    }
    
  5. Développez l'entrée de journal audit-violations pour inspecter les journaux en mode audit. Le détail se présente comme suit :

    {
      ...
      labels: {
        ...
        pod-security.kubernetes.io/audit-violations: "would violate PodSecurity "baseline:latest": privileged
                                                    (container "nginx" must not set securityContext.privileged=true)"
        pod-security.kubernetes.io/enforce-policy: "privileged:latest"
      }
      operation: {4}
      protoPayload: {10}
      receiveTimestamp: "2023-12-26T05:18:04.533631468Z"
      resource: {2}
      timestamp: "2023-12-26T05:17:36.102387Z"
    }
    

Effectuer un nettoyage

Pour éviter que des frais ne soient facturés sur votre compte Google Cloud, supprimez les espaces de noms :

kubectl delete ns baseline-ns
kubectl delete ns restricted-ns

Alternatives à PodSecurity

Outre l'utilisation du contrôleur d'admission PodSecurity Kubernetes intégré pour appliquer les normes de sécurité des pods, vous pouvez également utiliserGatekeeper, un contrôleur d'admission basé sur l'agent Open Policy Agent (OPA) pour créer et appliquer des contrôles de sécurité personnalisés au niveau du pod.

Étape suivante