Signaler les violations d'audit Policy Controller dans Security Command Center

Last reviewed 2023-04-17 UTC

Ce tutoriel montre aux administrateurs de sécurité des plates-formes comment afficher et gérer les cas de non-respect des règles pour les ressources Kubernetes, ainsi que d'autres résultats liés aux failles et à la sécurité dans Security Command Center. Dans ce tutoriel, vous pouvez utiliser Policy Controller ou Open Policy Agent (OPA) Gatekeeper.

Architecture

Policy Controller vérifie, audite et applique la conformité des ressources de vos clusters aux règles liées à la sécurité, aux réglementations ou aux règles métier. Policy Controller est conçu à partir du projet Open Source OPA Gatekeeper.

La fonctionnalité d'audit de Policy Controller et d'OPA Gatekeeper vous permet de mettre en œuvre des contrôles de détection qui évaluent périodiquement les ressources par rapport aux règles. Si un problème est détecté, les contrôles créent des violations pour les ressources qui ne sont pas conformes aux règles. Ces violations sont stockées dans le cluster. Vous pouvez les interroger à l'aide d'outils Kubernetes tels que kubectl.

Security Command Center permet de rendre ces violations visibles et vous aide à prendre des mesures. Security Command Center fournit un tableau de bord et des API permettant de repérer, de comprendre et d'éliminer les menaces pesant sur les données et la sécurité des ressources Google Cloud, des ressources Kubernetes, et des ressources hybrides ou multicloud au sein d'une organisation.

Security Command Center affiche les risques de sécurité potentiels et les cas de non-respect des règles, appelés résultats. Les résultats proviennent de sources, qui sont des mécanismes permettant de détecter et de signaler les risques et les violations. Security Command Center inclut des services intégrés, mais vous pouvez également ajouter des sources tierces et vos propres sources.

Ce tutoriel et le code source associé montrent comment créer une source et des résultats dans Security Command Center pour les cas de non-respect des règles Policy Controller et OPA Gatekeeper.

Le schéma suivant présente l'architecture mise en œuvre dans ce tutoriel :

Architecture avec source, contrôleur et synchronisation.

Comme le montre le schéma ci-dessus, ce tutoriel vous permet de créer une source dans Security Command Center à l'aide d'un outil de ligne de commande. Vous déployez un contrôleur sur un cluster Google Kubernetes Engine (GKE) afin de synchroniser les cas de non-respect des contraintes Policy Controller et OPA Gatekeeper avec les résultats dans Security Command Center.

Si vous souhaitez savoir comment synchroniser les cas de non-respect des règles pour les ressources Google Cloud, consultez notre tutoriel Créer des ressources Google Cloud conformes aux règles avec Config Connector et Policy Controller.

Objectifs

  • Créer une règle et une ressource qui l'enfreint
  • Créer une source dans Security Command Center
  • Créer un résultat dans Security Command Center à partir d'un cas de non-respect des règles OPA Gatekeeper à l'aide d'un outil de ligne de commande
  • Déployer un contrôleur sur le cluster GKE afin de synchroniser régulièrement les résultats dans Security Command Center à partir des cas de non-respect des règles OPA Gatekeeper
  • Afficher les résultats dans votre terminal et dans Google Cloud Console

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  2. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  3. Pour suivre ce tutoriel, vous devez disposer d'un rôle d'éditeur approprié pour Security Command Center au niveau de l'organisation, tel que le rôle Éditeur administrateur du centre de sécurité. L'administrateur de votre organisation peut vous attribuer ce rôle.
  4. Dans la console Google Cloud, activez Cloud Shell.

    Activer Cloud Shell

Préparer l'environnement

  1. Dans Cloud Shell, définissez le projet Google Cloud que vous souhaitez utiliser pour ce tutoriel :

    gcloud config set project PROJECT_ID
    

    Remplacez PROJECT_ID par l'ID de votre projet Google Cloud. Lorsque vous exécutez cette commande, Cloud Shell crée une variable d'environnement exportée nommée GOOGLE_CLOUD_PROJECT qui contient l'ID de votre projet.

  2. Activez les API Resource Manager, GKE, Security Command Center et Service Usage :

    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        securitycenter.googleapis.com \
        serviceusage.googleapis.com
    

Créer un cluster GKE

  1. Dans Cloud Shell, créez un cluster GKE sur lequel Workload Identity est activé :

    gcloud container clusters create gatekeeper-securitycenter-tutorial \
        --enable-ip-alias \
        --release-channel regular \
        --workload-pool $GOOGLE_CLOUD_PROJECT.svc.id.goog \
        --zone us-central1-f
    

    Cette commande crée le cluster dans la zone us-central1-f. Vous pouvez définir une zone ou une région différente.

  2. Accordez-vous le rôle de cluster cluster-admin :

    kubectl create clusterrolebinding cluster-admin-binding \
        --clusterrole cluster-admin \
        --user $(gcloud config get-value core/account)
    

    Vous aurez besoin de ce rôle ultérieurement pour créer certaines des ressources Kubernetes utilisées par le contrôleur. Vous en aurez également besoin si vous installez la distribution Open Source OPA Gatekeeper.

Installer l'outil de règle

Si vous disposez d'un cluster GKE géré, suivez les instructions pour installer Policy Controller. Sinon, installez la distribution OPA Gatekeeper.

Policy Controller

Installez Policy Controller en suivant les instructions d'installation.

Définissez un intervalle d'audit de 60 secondes.

OPA Gatekeeper

  1. Dans Cloud Shell, définissez la version d'OPA Gatekeeper que vous souhaitez installer :

    GATEKEEPER_VERSION=v3.10.0
    
  2. Installez OPA Gatekeeper :

    kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/$GATEKEEPER_VERSION/deploy/gatekeeper.yaml
    
  3. Vérifiez si OPA Gatekeeper est bien installé :

    kubectl rollout status deploy gatekeeper-controller-manager \
        -n gatekeeper-system
    

    Une fois l'installation terminée, la commande affiche deployment "gatekeeper-controller-manager" successfully rolled out.

Créer une règle

Dans Policy Controller et OPA Gatekeeper, une règle est composée d'un modèle de contrainte et d'une contrainte. Le modèle de contrainte contient la logique de la règle. La contrainte spécifie dans quel contexte la règle s'applique et les paramètres d'entrée associés à la logique de la règle.

Dans cette section, vous allez créer une règle pour les pods Kubernetes et un pod non conforme à cette règle.

  1. Dans Cloud Shell, clonez le dépôt de la bibliothèque OPA Gatekeeper, accédez au répertoire du dépôt et vérifiez un commit connu :

    git clone https://github.com/open-policy-agent/gatekeeper-library.git \
        ~/gatekeeper-library
    
    cd ~/gatekeeper-library
    
    git checkout 1da0facae99658accb73c291cb79f497fcddf641
    
  2. Créez un pod nommé nginx-disallowed dans l'espace de noms default :

    kubectl apply -f library/general/allowedrepos/samples/repo-must-be-openpolicyagent/example_disallowed.yaml
    

    Voici le fichier manifeste que vous appliquez pour créer le pod :

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-disallowed
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              cpu: "100m"
              memory: "30Mi"
    

    Ce pod utilise une image de conteneur issue d'un dépôt non approuvé par la règle.

  3. Créez un modèle de contrainte nommé k8sallowedrepos :

    kubectl apply -f library/general/allowedrepos/template.yaml
    

    Voici le fichier manifeste du modèle de contrainte :

    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: k8sallowedrepos
      annotations:
        description: >-
          Requires container images to begin with a string from the specified list.
    spec:
      crd:
        spec:
          names:
            kind: K8sAllowedRepos
          validation:
            # Schema for the `parameters` field
            openAPIV3Schema:
              type: object
              properties:
                repos:
                  description: The list of prefixes a container image is allowed to have.
                  type: array
                  items:
                    type: string
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package k8sallowedrepos
    
            violation[{"msg": msg}] {
              container := input.review.object.spec.containers[_]
              satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)]
              not any(satisfied)
              msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos])
            }
    
            violation[{"msg": msg}] {
              container := input.review.object.spec.initContainers[_]
              satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)]
              not any(satisfied)
              msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos])
            }
    
  4. Créez une contrainte nommée repo-is-openpolicyagent :

    kubectl apply -f library/general/allowedrepos/samples/repo-must-be-openpolicyagent/constraint.yaml
    

    Voici le fichier manifeste de la contrainte :

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sAllowedRepos
    metadata:
      name: repo-is-openpolicyagent
    spec:
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pod"]
        namespaces:
          - "default"
      parameters:
        repos:
          - "openpolicyagent/"
    

Auditer les contraintes

Le contrôleur d'audit de Policy Controller et d'OPA Gatekeeper évalue périodiquement les ressources vis-à-vis de leurs contraintes. Cet audit vous permet de détecter les cas de non-respect des règles pour les ressources créées avant la contrainte.

  1. Dans Cloud Shell, affichez les cas de non-respect associés à toutes les contraintes en interrogeant les données de la catégorie constraint :

    kubectl get constraint -o json | jq '.items[].status.violations'
    

    Le résultat est le suivant :

    [
      {
        "enforcementAction": "deny",
        "kind": "Pod",
        "message": "container <nginx> has an invalid image repo <nginx>, allowed repos are [\"openpolicyagent\"]",
        "name": "nginx-disallowed",
        "namespace": "default"
      }
    ]
    

    Un cas de non-respect est détecté pour le pod que vous avez créé avant la contrainte. Si vous voyez la valeur null au lieu de la sortie ci-dessus, cela signifie que l'audit Policy Controller ou OPA Gatekeeper n'a pas été exécuté depuis que vous avez créé la contrainte. Par défaut, l'audit est exécuté toutes les minutes. Patientez une minute, puis réessayez.

Créer une source Security Command Center

Security Command Center enregistre les résultats en fonction des sources. Procédez comme suit pour créer une source de résultats à partir de Policy Controller et d'OPA Gatekeeper :

  1. Dans Cloud Shell, créez un compte de service Google et stockez son nom dans une variable d'environnement :

    SOURCES_ADMIN_SA=$(gcloud iam service-accounts create \
        securitycenter-sources-admin \
        --display-name "Security Command Center sources admin" \
        --format 'value(email)')
    

    Le compte de service Google vous permet d'administrer les sources Security Command Center.

  2. Définissez une variable d'environnement contenant l'ID de votre organisation Google Cloud :

    ORGANIZATION_ID=$(gcloud projects get-ancestors $GOOGLE_CLOUD_PROJECT \
        --format json | jq -r '.[] | select (.type=="organization") | .id')
    
  3. Attribuez le rôle Administrateur des sources du centre de sécurité au compte de service Google de l'administrateur des sources au niveau de l'organisation :

    gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \
        --member "serviceAccount:$SOURCES_ADMIN_SA" \
        --role roles/securitycenter.sourcesAdmin
    

    Ce rôle fournit les autorisations securitycenter.sources.* requises pour administrer les sources.

  4. Attribuez le rôle Consommateur Service Usage au compte de service Google de l'administrateur des sources au niveau de l'organisation :

    gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \
        --member "serviceAccount:$SOURCES_ADMIN_SA" \
        --role roles/serviceusage.serviceUsageConsumer
    

    Ce rôle fournit l'autorisation serviceusage.services.use permettant d'utiliser des projets de l'organisation à des fins de quota et de facturation.

  5. Accordez le rôle Créateur de jetons du compte de service au compte de service Google de l'administrateur des sources :

    gcloud iam service-accounts add-iam-policy-binding \
        $SOURCES_ADMIN_SA \
        --member "user:$(gcloud config get-value account)" \
        --role roles/iam.serviceAccountTokenCreator
    

    Ce rôle autorise l'utilisateur à emprunter l'identité du compte de service Google ou à agir en son nom.

  6. Téléchargez la dernière version de l'outil de ligne de commande gatekeeper-securitycenter pour votre plate-forme, puis rendez-la exécutable :

    VERSION=v0.4.0
    
    curl -Lo gatekeeper-securitycenter "https://github.com/GoogleCloudPlatform/gatekeeper-securitycenter/releases/download/${VERSION}/gatekeeper-securitycenter_$(uname -s)_$(uname -m)"
    
    chmod +x gatekeeper-securitycenter
    
  7. Créez une source Security Command Center pour votre organisation à l'aide de l'outil gatekeeper-securitycenter. Enregistrez le nom complet de la source dans une variable d'environnement.

    export SOURCE_NAME=$(./gatekeeper-securitycenter sources create \
        --organization $ORGANIZATION_ID \
        --display-name "Gatekeeper" \
        --description "Reports violations from Policy Controller audits" \
        --impersonate-service-account $SOURCES_ADMIN_SA | jq -r '.name')
    

    Cette commande crée une source nommée Gatekeeper. Ce nom à afficher est visible dans Security Command Center. Vous pouvez indiquer une description et un nom à afficher différents.

    Si vous obtenez une réponse avec le message d'erreur The caller does not have permission, patientez une minute, puis réessayez. Cette erreur peut se produire si les liaisons IAM (Identity and Access Management) n'ont pas encore pris effet.

Créer des résultats avec la ligne de commande

Vous pouvez créer des résultats Security Command Center à partir des cas de non-respect des contraintes Policy Controller et OPA Gatekeeper à l'aide de l'outil gatekeeper-securitycenter dans le cadre d'un pipeline de compilation ou d'une tâche planifiée.

  1. Dans Cloud Shell, créez un compte de service Google et stockez son nom dans une variable d'environnement :

    FINDINGS_EDITOR_SA=$(gcloud iam service-accounts create \
        gatekeeper-securitycenter \
        --display-name "Security Command Center Gatekeeper findings editor" \
        --format 'value(email)')
    

    Le compte de service Google vous permet de créer les résultats de votre source Security Command Center.

  2. Attribuez le rôle Éditeur de résultats du centre de sécurité au compte de service Google pour la source :

    ./gatekeeper-securitycenter sources add-iam-policy-binding \
        --source $SOURCE_NAME \
        --member "serviceAccount:$FINDINGS_EDITOR_SA" \
        --role roles/securitycenter.findingsEditor \
        --impersonate-service-account $SOURCES_ADMIN_SA
    

    Ce rôle fournit les autorisations securitycenter.findings.* requises pour créer et modifier les résultats. Lorsque vous exécutez cette commande, vous empruntez l'identité du compte de service Google de l'administrateur des sources.

  3. Attribuez le rôle Consommateur Service Usage au compte de service Google de l'éditeur de résultats au niveau de l'organisation :

    gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \
        --member "serviceAccount:$FINDINGS_EDITOR_SA" \
        --role roles/serviceusage.serviceUsageConsumer
    
  4. Attribuez le rôle Créateur de jetons du compte de service au compte de service Google de l'éditeur de résultats :

    gcloud iam service-accounts add-iam-policy-binding \
        $FINDINGS_EDITOR_SA \
        --member "user:$(gcloud config get-value account)" \
        --role roles/iam.serviceAccountTokenCreator
    
  5. Imprimez les résultats sur le terminal au lieu de les créer dans Security Command Center :

    ./gatekeeper-securitycenter findings sync --dry-run=true
    

    Cette commande utilise le contexte kubeconfig actuel par défaut. Si vous souhaitez utiliser un autre fichier kubeconfig, utilisez l'option --kubeconfig.

    La sortie ressemble à ceci :

    [
      {
        "finding_id": "0be44bcf181ef03162eed40126a500a0",
        "finding": {
          "resource_name": "https://API_SERVER/api/v1/namespaces/default/pods/nginx-disallowed",
          "state": 1,
          "category": "K8sAllowedRepos",
          "external_uri": "https://API_SERVER/apis/constraints.gatekeeper.sh/v1beta1/k8sallowedrepos/repo-is-openpolicyagent",
          "source_properties": {
            "Cluster": "",
            "ConstraintName": "repo-is-openpolicyagent",
            "ConstraintSelfLink": "https://API_SERVER/apis/constraints.gatekeeper.sh/v1beta1/k8sallowedrepos/repo-is-openpolicyagent",
            "ConstraintTemplateSelfLink": "https://API_SERVER/apis/templates.gatekeeper.sh/v1beta1/constrainttemplates/k8sallowedrepos",
            "ConstraintTemplateUID": "e35b1c39-15f7-4a7a-afae-1637b44e81b2",
            "ConstraintUID": "b904dddb-0a23-4f4f-81bb-0103de838d3e",
            "Explanation": "container \u003cnginx\u003e has an invalid image repo \u003cnginx\u003e, allowed repos are [\"openpolicyagent\"]",
            "ProjectId": "",
            "ResourceAPIGroup": "",
            "ResourceAPIVersion": "v1",
            "ResourceKind": "Pod",
            "ResourceName": "nginx-disallowed",
            "ResourceNamespace": "default",
            "ResourceSelfLink": "https://API_SERVER/api/v1/namespaces/default/pods/nginx-disallowed",
            "ResourceStatusSelfLink": "",
            "ResourceUID": "8ddd752f-e620-43ea-b966-4ae2ae507c67",
            "ScannerName": "GATEKEEPER"
          },
          "event_time": {
            "seconds": 1606287680
          }
        }
      }
    ]
    

    Dans la sortie ci-dessus, API_SERVER correspond à l'adresse IP ou au nom d'hôte du serveur d'API de votre cluster GKE.

    Pour en savoir plus sur la signification des champs, consultez la page Ressource de résultat de l'API Security Command Center.

  6. Créez les résultats dans Security Command Center :

    ./gatekeeper-securitycenter findings sync \
        --source $SOURCE_NAME \
        --impersonate-service-account $FINDINGS_EDITOR_SA
    

    Lorsque vous exécutez cette commande, vous empruntez l'identité du compte de service Google de l'éditeur de résultats.

    La sortie inclut create finding, ce qui signifie que l'outil de ligne de commande gatekeeper-securitycenter a créé un résultat. L'attribut findingID de cette sortie contient le nom complet du résultat au format suivant :

    organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID
    

    Dans ce résultat :

    • ORGANIZATION_ID est l'ID de votre organisation Google Cloud.
    • SOURCE_ID est l'ID de votre source Security Command Center.
    • FINDING_ID est l'ID du résultat.

    Pour afficher les résultats, consultez la section Afficher les résultats.

    Si vous obtenez une réponse avec le message d'erreur The caller does not have permission, patientez une minute, puis réessayez. Cette erreur peut se produire si les liaisons IAM (Identity and Access Management) n'ont pas encore pris effet.

Créer des résultats avec un contrôleur Kubernetes

Vous pouvez déployer gatekeeper-securitycenter en tant que contrôleur dans votre cluster GKE. Ce contrôleur recherche régulièrement les cas de non-respect des contraintes et crée un résultat pour chacun d'eux dans Security Command Center.

Si la ressource devient conforme, le contrôleur définit l'état du résultat existant sur INACTIVE.

  1. Dans Cloud Shell, créez une liaison de stratégie IAM Workload Identity pour permettre au compte de service Kubernetes gatekeeper-securitycenter-controller de l'espace de noms gatekeeper-securitycenter d'emprunter l'identité du compte de service Google de l'éditeur de résultats :

    gcloud iam service-accounts add-iam-policy-binding \
        $FINDINGS_EDITOR_SA \
        --member "serviceAccount:$GOOGLE_CLOUD_PROJECT.svc.id.goog[gatekeeper-securitycenter/gatekeeper-securitycenter-controller]" \
        --role roles/iam.workloadIdentityUser
    

    Vous créez le compte de service et l'espace de noms Kubernetes lors du déploiement du contrôleur.

  2. Récupérez le package kpt pour le contrôleur gatekeeper-securitycenter :

    VERSION=v0.4.0
    
    kpt pkg get https://github.com/GoogleCloudPlatform/gatekeeper-securitycenter.git/manifests@$VERSION manifests
    

    Cette commande crée le répertoire manifests qui contient les fichiers manifestes des ressources du contrôleur.

    Kpt est un outil de ligne de commande qui vous permet de gérer, de modifier, de personnaliser et d'appliquer des ressources Kubernetes. Vous utiliserez kpt dans ce tutoriel pour personnaliser les fichiers manifestes des ressources de votre environnement.

  3. Définissez le nom de la source Security Command Center :

    kpt fn eval manifests \
        --image gcr.io/kpt-fn/apply-setters:v0.2 -- \
        "source=$SOURCE_NAME"
    
  4. Définissez le nom du cluster :

    kpt fn eval manifests \
        --image gcr.io/kpt-fn/apply-setters:v0.2 -- \
        "cluster=$(kubectl config current-context)"
    

    Le contrôleur ajoute le nom du cluster en tant que propriété source aux résultats qu'il crée dans Security Command Center. Si vous disposez de plusieurs clusters, ce nom vous aide à identifier le cluster auquel appartient un résultat.

  5. Pour associer le compte de service Kubernetes du contrôleur au compte de service Google de l'éditeur de résultats, ajoutez l'annotation Workload Identity :

    kpt fn eval manifests \
        --image gcr.io/kpt-fn/set-annotations:v0.1.4 \
        --match-kind ServiceAccount \
        --match-name gatekeeper-securitycenter-controller \
        --match-namespace gatekeeper-securitycenter -- \
        "iam.gke.io/gcp-service-account=$FINDINGS_EDITOR_SA"
    
  6. Initialisez le package du contrôleur :

    kpt live init manifests
    
  7. Appliquez les ressources du contrôleur à votre cluster :

    kpt live apply manifests --reconcile-timeout 3m --output table
    

    Cette commande crée les ressources suivantes dans votre cluster :

    • Un espace de noms appelé gatekeeper-securitycenter
    • Un compte de service appelé gatekeeper-securitycenter-controller
    • Un rôle de cluster fournissant les accès get et list à toutes les ressources des groupes d'API. Ce rôle est requis, car le contrôleur récupère les ressources qui ont entraîné le non-respect des règles.
    • Une liaison de rôle de cluster attribuant le rôle de cluster au compte de service
    • Un déploiement appelé gatekeeper-securitycenter-controller-manager
    • Un mappage de configuration appelé gatekeeper-securitycenter-config contenant les valeurs de configuration du déploiement

    La commande attend également que les ressources soient prêtes.

  8. Vérifiez que le contrôleur peut lire les cas de non-respect des contraintes et communiquer avec l'API Security Command Center en suivant le journal du contrôleur :

    kubectl logs deployment/gatekeeper-securitycenter-controller-manager \
        --namespace gatekeeper-securitycenter --follow --all-containers
    

    Les entrées de journal contenant le message syncing findings s'affichent.

    Pour arrêter de suivre le journal, appuyez sur Ctrl+C.

  9. Pour vérifier que le contrôleur peut créer des résultats, créez une règle et une ressource non conforme à cette règle. Le pod fait référence aux images de conteneurs à l'aide de condensés d'images.

    Accédez au répertoire du dépôt de la bibliothèque OPA Gatekeeper :

    cd ~/gatekeeper-library
    
  10. Créez un pod nommé opa-disallowed dans l'espace de noms default :

    kubectl apply --namespace default -f \
        library/general/imagedigests/samples/container-image-must-have-digest/example_disallowed.yaml
    

    Voici le fichier manifeste que vous appliquez pour créer le pod :

    apiVersion: v1
    kind: Pod
    metadata:
      name: opa-disallowed
    spec:
      containers:
        - name: opa
          image: openpolicyagent/opa:0.9.2
          args:
            - "run"
            - "--server"
            - "--addr=localhost:8080"
    

    Cette spécification de pod fait référence à une image de conteneur à l'aide d'un tag au lieu d'un condensé.

  11. Créez un modèle de contrainte nommé k8simagedigests :

    kubectl apply -f library/general/imagedigests/template.yaml
    

    Voici le fichier manifeste du modèle de contrainte :

    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: k8simagedigests
      annotations:
        description: >-
          Requires container images to contain a digest.
    
          https://kubernetes.io/docs/concepts/containers/images/
    spec:
      crd:
        spec:
          names:
            kind: K8sImageDigests
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package k8simagedigests
    
            violation[{"msg": msg}] {
              container := input.review.object.spec.containers[_]
              satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
              not all(satisfied)
              msg := sprintf("container <%v> uses an image without a digest <%v>", [container.name, container.image])
            }
    
            violation[{"msg": msg}] {
              container := input.review.object.spec.initContainers[_]
              satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
              not all(satisfied)
              msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image])
            }
    
  12. Créez une contrainte nommée container-image-must-have-digest :

    kubectl apply -f library/general/imagedigests/samples/container-image-must-have-digest/constraint.yaml
    

    Voici le fichier manifeste de la contrainte :

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sImageDigests
    metadata:
      name: container-image-must-have-digest
    spec:
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pod"]
        namespaces:
          - "default"
    

    Cette contrainte ne s'applique qu'à l'espace de noms default.

  13. Suivez le journal du contrôleur :

    kubectl logs deployment/gatekeeper-securitycenter-controller-manager \
        --namespace gatekeeper-securitycenter --follow --all-containers
    

    Au bout de quelques minutes, une entrée de journal contenant le message create finding s'affiche. Ce message signifie que le contrôleur gatekeeper-securitycenter a créé un résultat.

    Pour arrêter de suivre le journal, appuyez sur Ctrl+C.

  14. Pour vérifier que le contrôleur peut définir l'état du résultat sur INACTIVE lorsqu'un cas de non-respect n'est plus signalé par Policy Controller ou OPA Gatekeeper, supprimez le pod opa-disallowed de l'espace de noms default :

    kubectl delete pod opa-disallowed --namespace default
    
  15. Suivez le journal du contrôleur :

    kubectl logs deployment/gatekeeper-securitycenter-controller-manager \
        --namespace gatekeeper-securitycenter --follow --all-containers
    

    Au bout de quelques minutes, une entrée de journal contenant le message updating finding state et l'attribut "state":"INACTIVE" s'affiche. Ce message signifie que le contrôleur a défini l'état du résultat sur "inactif".

    Pour arrêter de suivre le journal, appuyez sur Ctrl+C.

Afficher les résultats

Vous pouvez afficher les résultats de Security Command Center sur le terminal et dans Google Cloud Console.

  1. Dans Cloud Shell, répertoriez les résultats de votre organisation et de votre source à l'aide de gcloud CLI :

    gcloud scc findings list $ORGANIZATION_ID \
        --source $(basename $SOURCE_NAME) \
        --format json
    

    Vous exécutez la commande basename pour obtenir l'ID numérique de la source à partir de son nom complet.

    La sortie ressemble à ceci :

    [
      {
        "finding": {
          "category": "K8sAllowedRepos",
          "createTime": "2020-11-25T06:58:47.213Z",
          "eventTime": "2020-11-25T06:58:20Z",
          "externalUri": "https://API_SERVER/apis/constraints.gatekeeper.sh/v1beta1/k8sallowedrepos/repo-is-openpolicyagent",
          "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID",
          "parent": "organizations/ORGANIZATION_ID/sources/SOURCE_ID",
          "resourceName": "https://API_SERVER/api/v1/namespaces/default/pods/nginx-disallowed",
          "securityMarks": {
            "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID/securityMarks"
          },
          "sourceProperties": {
            "Cluster": "cluster-name",
            "ConstraintName": "repo-is-openpolicyagent",
            "ConstraintSelfLink": "https://API_SERVER/apis/constraints.gatekeeper.sh/v1beta1/k8sallowedrepos/repo-is-openpolicyagent",
            "ConstraintTemplateSelfLink": "https://API_SERVER/apis/templates.gatekeeper.sh/v1beta1/constrainttemplates/k8sallowedrepos",
            "ConstraintTemplateUID": "e35b1c39-15f7-4a7a-afae-1637b44e81b2",
            "ConstraintUID": "b904dddb-0a23-4f4f-81bb-0103de838d3e",
            "Explanation": "container <nginx> has an invalid image repo <nginx>, allowed repos are [\"openpolicyagent\"]",
            "ProjectId": "",
            "ResourceAPIGroup": "",
            "ResourceAPIVersion": "v1",
            "ResourceKind": "Pod",
            "ResourceName": "nginx-disallowed",
            "ResourceNamespace": "default",
            "ResourceSelfLink": "https://API_SERVER/api/v1/namespaces/default/pods/nginx-disallowed",
            "ResourceStatusSelfLink": "",
            "ResourceUID": "8ddd752f-e620-43ea-b966-4ae2ae507c67",
            "ScannerName": "GATEKEEPER"
          },
          "state": "ACTIVE"
        },
        "resource": {
          "name": "https://API_SERVER/api/v1/namespaces/default/pods/nginx-disallowed"
        }
      },
      {
        "finding": {
          "category": "K8sImageDigests",
          [...]
      }
    ]
    

    Dans ce résultat :

    • API_SERVER est l'adresse IP ou le nom d'hôte du serveur d'API de votre cluster GKE.
    • ORGANIZATION_ID est l'ID de votre organisation Google Cloud.
    • SOURCE_ID est l'ID de votre source Security Command Center.
    • FINDING_ID est l'ID du résultat.

    Pour en savoir plus sur la signification des attributs de résultats, consultez la page Ressource de résultat de l'API Security Command Center.

  2. Pour afficher les résultats dans Google Cloud Console, accédez à l'onglet Résultats de Security Command Center.

    Accéder

  3. Sélectionnez votre organisation, puis cliquez sur Sélectionner.

  4. Cliquez sur Afficher par Type de source.

  5. Dans la liste Type de source, cliquez sur Gatekeeper. Si Gatekeeper ne figure pas dans la liste Type de source, effacez tous les filtres de la liste des résultats.

  6. Dans la liste des résultats, cliquez sur un résultat pour afficher ses attributs et ses propriétés sources.

    Si une ressource ne cause plus de violation due à une modification de la ressource ou de la règle, le contrôleur définit l'état du résultat sur inactif. L'affichage de cette modification dans Security Command Center peut prendre quelques minutes.

    Par défaut, Security Command Center affiche les résultats actifs. Pour afficher les résultats inactifs, cliquez sur Plus d'options, sélectionnez Inclure les résultats inactifs, puis cliquez sur OK.

Dépannage

  • Si Policy Controller ou OPA Gatekeeper ne signalent pas de cas de non-respect dans le champ status des objets de contrainte, affichez les journaux du contrôleur d'audit à l'aide de Cloud Shell :

    kubectl logs deployment/gatekeeper-audit --namespace gatekeeper-system \
        --all-containers
    
  • Si le contrôleur gatekeeper-securitycenter ne crée pas de résultats dans Security Command Center, vous pouvez afficher les journaux du gestionnaire de contrôleurs comme suit :

    kubectl logs deployment/gatekeeper-securitycenter-controller-manager \
        --namespace gatekeeper-securitycenter --all-containers
    
  • Si l'outil de ligne de commande gatekeeper-securitycenter signale des erreurs, vous pouvez augmenter la verbosité des résultats du journal en définissant la variable d'environnement DEBUG sur true avant d'exécuter la commande gatekeeper-securitycenter :

    export DEBUG=true
    
  • Lorsque vous utilisez l'outil de ligne de commande gatekeeper-securitycenter pour créer une source dans Security Command Center, vous pouvez obtenir un message d'erreur se terminant par le texte suivant :

    oauth2: cannot fetch token: 400 Bad Request
    Response: {
      "error": "invalid_grant",
      "error_description": "Bad Request"
    }
    

    Dans ce cas, obtenez de nouveaux identifiants à utiliser avec les identifiants par défaut de l'application :

    gcloud auth application-default login
    

    Utilisez les nouveaux identifiants pour réessayer de créer la source.

Si vous rencontrez d'autres problèmes avec ce tutoriel, nous vous recommandons de consulter les documents suivants :

Automatiser la configuration

Pour vos futurs déploiements, vous pouvez automatiser la procédure décrite dans ce tutoriel en suivant les instructions du dépôt GitHub gatekeeper-securitycenter.

Nettoyer

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez les ressources individuelles.

Supprimer les ressources individuelles

  1. Dans Cloud Shell, supprimez le cluster GKE :

    gcloud container clusters delete gatekeeper-securitycenter-tutorial \
        --zone us-central1-f --async --quiet
    
  2. Supprimez les fichiers gatekeeper-library :

    rm -rf ~/gatekeeper-library
    
  3. Supprimez les liaisons de stratégie IAM :

    GOOGLE_CLOUD_PROJECT=$(gcloud config get-value core/project)
    
    ORGANIZATION_ID=$(gcloud projects get-ancestors $GOOGLE_CLOUD_PROJECT \
        --format json | jq -r '.[] | select (.type=="organization") | .id')
    
    SOURCE_NAME=$(./gatekeeper-securitycenter sources list \
        --organization "$ORGANIZATION_ID" \
        --impersonate-service-account "securitycenter-sources-admin@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
        | jq -r ".[] | select (.display_name==\"Gatekeeper\") | .name")
    
    ./gatekeeper-securitycenter sources remove-iam-policy-binding \
        --source $SOURCE_NAME \
        --member "serviceAccount:gatekeeper-securitycenter@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
        --role roles/securitycenter.findingsEditor \
        --impersonate-service-account securitycenter-sources-admin@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    
    gcloud iam service-accounts remove-iam-policy-binding \
        gatekeeper-securitycenter@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
        --member "serviceAccount:$GOOGLE_CLOUD_PROJECT.svc.id.goog[gatekeeper-securitycenter/gatekeeper-securitycenter-controller]" \
        --role roles/iam.workloadIdentityUser
    
    gcloud iam service-accounts remove-iam-policy-binding \
        gatekeeper-securitycenter@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
        --member "user:$(gcloud config get-value account)" \
        --role roles/iam.serviceAccountTokenCreator
    
    gcloud organizations remove-iam-policy-binding $ORGANIZATION_ID \
        --member "serviceAccount:gatekeeper-securitycenter@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
        --role roles/serviceusage.serviceUsageConsumer
    
    gcloud iam service-accounts remove-iam-policy-binding \
        securitycenter-sources-admin@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
        --member "user:$(gcloud config get-value account)" \
        --role roles/iam.serviceAccountTokenCreator
    
    gcloud organizations remove-iam-policy-binding $ORGANIZATION_ID \
        --member "serviceAccount:securitycenter-sources-admin@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
        --role roles/serviceusage.serviceUsageConsumer
    
    gcloud organizations remove-iam-policy-binding $ORGANIZATION_ID \
        --member "serviceAccount:securitycenter-sources-admin@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
        --role roles/securitycenter.sourcesAdmin
    
  4. Supprimez les comptes de service Google :

    gcloud iam service-accounts delete --quiet \
        gatekeeper-securitycenter@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    
    gcloud iam service-accounts delete --quiet \
        securitycenter-sources-admin@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    

Étapes suivantes