Informar incumplimientos de auditoría de Policy Controller en el Security Command Center

En este instructivo, se muestra a los administradores de seguridad de la plataforma cómo ver y administrar los incumplimientos de política para los recursos de Kubernetes junto con otros hallazgos de seguridad y vulnerabilidades en Security Command Center. En este instructivo, puedes usar Policy Controller o Open Policy Agent (OPA) Gatekeeper.

Arquitectura

Policy Controller verifica, audita y aplica el cumplimiento de las políticas de recursos de tu clúster de Kubernetes con las políticas relacionadas con las reglas de seguridad, las normativas o las reglas empresariales. El Policy Controller se compila a partir del proyecto de código abierto OPA Gatekeeper.

La funcionalidad de auditoría en el Policy Controller y OPA Gatekeeper te permite implementar controles de detección que evalúan los recursos de manera periódica para determinar las políticas. Si se detecta un problema, los controles crean incumplimientos para los recursos que no cumplen con las políticas. Estos incumplimientos se almacenan en el clúster y puedes consultarlas con herramientas de Kubernetes como kubectl.

Para mostrar estas incumplimientos y ayudarte a tomar medidas, puedes usar el Security Command Center. Security Command Center proporciona un panel y las API para exponer, comprender y solucionar los riesgos de seguridad y datos en una organización para los recursos de Google Cloud, los recursos de Kubernetes y los recursos híbridos o de múltiples nubes.

Security Command Center muestra los posibles riesgos de seguridad y los incumplimientos de políticas, llamados resultados. Los resultados provienen de fuentes, que son mecanismos que pueden detectar e informar riesgos e incumplimientos. Security Command Center incluye servicios integrados, y puedes agregar fuentes de terceros y propias.

En este instructivo y en el código fuente asociado, se muestra cómo crear una fuente y encontrar los hallazgos en Security Command Center para el Policy Controller y los incumplimientos de las políticas de OPA Gatekeeper.

En el siguiente diagrama, se muestra la arquitectura que se implementa en este instructivo:

Arquitectura con una fuente, un controlador y una sincronización

Como se muestra en el diagrama anterior, en este instructivo, crearás una fuente en Security Command Center mediante una herramienta de línea de comandos. Implementa un controlador en un clúster de Google Kubernetes Engine (GKE) para sincronizar las políticas de OPA y Gatekeeper con los resultados en Security Command Center.

Si quieres ver cómo sincronizar los incumplimientos de política para los recursos de Google Cloud, prueba nuestro instructivo sobre cómo crear recursos de Google Cloud que cumplen con las políticas mediante Config Connector y Policy Controller.

Objetivos

  • Crea una política y un recurso que infrinjan la política.
  • Crea una fuente en Security Command Center.
  • Crea un hallazgo en Security Command Center a partir de un incumplimiento de la política de OPA Gatekeeper con una herramienta de línea de comandos.
  • Implementa un controlador en el clúster de GKE para sincronizar de forma periódica los hallazgos en Security Command Center desde incumplimientos de políticas OPA Gatekeeper.
  • Visualiza los hallazgos en tu terminal y en Cloud Console.

Costos

En este instructivo, se usan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando finalices este instructivo, podrás borrar los recursos creados para evitar que se te siga facturando. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

  1. En la página del selector de proyectos de Google Cloud Console, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  2. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Descubre cómo confirmar que tienes habilitada la facturación en un proyecto.

  3. A fin de completar este instructivo, debes tener una función de editor adecuada para el nivel de organización de Security Command Center, como Editor administrador del centro de seguridad. El administrador de la organización puede otorgar esta función.
  4. En Cloud Console, activa Cloud Shell.

    Activar Cloud Shell

Prepara el entorno

  1. En Cloud Shell, configura el proyecto de Cloud que deseas usar para este instructivo:

    gcloud config set project PROJECT_ID
    

    Reemplaza PROJECT_ID por el ID del proyecto de Cloud. Cuando ejecutas este comando, Cloud Shell crea una variable de entorno exportada llamada GOOGLE_CLOUD_PROJECT que contiene el ID del proyecto.

  2. Habilita las API de GKE, Security Command Center y Service Usage:

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

Crea un clúster de GKE

  1. En Cloud Shell, crea un clúster de GKE con Workload Identity habilitado:

    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
    

    Este comando crea el clúster en la zona us-central1-f. Puedes usar una zona o región diferente.

  2. Otórgate la función de clúster cluster-admin:

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

    Necesitarás esta función más adelante para crear algunos de los recursos de Kubernetes que usa el controlador. También la necesitarás si instalas la distribución de OPA Gatekeeper de código abierto.

Instala la herramienta de políticas

Si tienes un clúster de Anthos administrado, sigue las instrucciones para instalar el Policy Controller; de lo contrario, instala la distribución de OPA Gatekeeper.

Policy Controller

Instala el Policy Controller según las instrucciones de instalación.

Usa un intervalo de auditoría de 60 segundos.

OPA Gatekeeper

  1. En Cloud Shell, define la versión de OPA Gatekeeper que deseas instalar:

    GATEKEEPER_VERSION=v3.7.0
    
  2. Instala OPA Gatekeeper:

    kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/$GATEKEEPER_VERSION/deploy/gatekeeper.yaml
    
  3. Verifica que OPA Gatekeeper esté instalado:

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

    Cuando se complete la instalación, el resultado mostrará deployment "gatekeeper-controller-manager" successfully rolled out.

Crea una política

Una política de Policy Controller y Gatekeeper consta de una plantilla de restricciones y una restricción. La plantilla de restricciones contiene la lógica de políticas. La restricción especifica dónde se aplica la política y los parámetros de entrada para la lógica de la política.

En esta sección, crearás una política para los pods de Kubernetes y un Pod que la infrinja.

  1. En Cloud Shell, clona el repositorio de la biblioteca de OPA Gatekeeper, ve al directorio del repositorio y consulta una confirmación conocida:

    git clone https://github.com/open-policy-agent/gatekeeper-library.git \
        ~/gatekeeper-library
    
    cd ~/gatekeeper-library
    
    git checkout 1da0facae99658accb73c291cb79f497fcddf641
    
  2. Crea un pod llamado nginx-disallowed en el espacio de nombres default:

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

    A continuación, se muestra el manifiesto que aplicas para crear el pod:

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

    Este pod usa una imagen de contenedor de un repositorio que la política no aprueba.

  3. Crea una plantilla de restricciones llamada k8sallowedrepos:

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

    El siguiente es el manifiesto de la planilla de restricción:

    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. Crea una restricción llamada repo-is-openpolicyagent:

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

    El siguiente es el manifiesto de restricción:

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

Auditoría de restricciones

El controlador de auditoría del Controlador de políticas y Gatekeeper evalúa de forma periódica los recursos según las restricciones. Esta auditoría te permite detectar recursos que infringen las políticas y que se crearon antes de crear la restricción.

  1. En Cloud Shell, observa los incumplimientos de todas las restricciones mediante una consulta con la categoría constraint:

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

    Este es el resultado:

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

    Hay una infracción en el Pod que creaste antes de crear la restricción. Si ves null en lugar del resultado anterior, la auditoría de Policy Controller o de OPA Gatekeeper no se ejecutó desde que creaste la restricción. De forma predeterminada, la auditoría se ejecuta cada minuto. Espera un minuto y vuelve a intentarlo.

Crea una fuente de Security Command Center

Security Command Center registra los hallazgos en las fuentes. Sigue estos pasos a fin de crear una fuente para los hallazgos desde el Policy Controller y OPA Gatekeeper:

  1. En Cloud Shell, crea una cuenta de servicio de Google y almacena el nombre de la cuenta de servicio en una variable de entorno de la siguiente manera:

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

    Usa esta cuenta de servicio de Google para administrar las fuentes de Security Command Center.

  2. Define una variable de entorno que contenga el ID de tu organización de Google Cloud:

    ORGANIZATION_ID=$(gcloud projects get-ancestors $GOOGLE_CLOUD_PROJECT \
        --format json | jq -r '.[] | select (.type=="organization") | .id')
    
  3. Otorga la función de administrador de fuentes de Security Center a la cuenta de servicio de administrador de fuentes de Google a nivel de la organización:

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

    Esta función proporciona los permisos securitycenter.sources.* necesarios para administrar las fuentes.

  4. Otorga la función de consumidor de Service Usage a la cuenta de servicio de Google del administrador de fuentes a nivel de la organización:

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

    Esta función proporciona el permiso serviceusage.services.use para usar los proyectos de la organización con fines de cuota y facturación.

  5. Otorga la función de Creador de tokens de cuenta de servicio para la cuenta de servicio de administrador de fuentes de Google:

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

    Esta función permite a tu identidad de usuario robar la identidad de Google o actuar como la cuenta de servicio de Google.

  6. Descarga la última versión de la herramienta de línea de comandos gatekeeper-securitycenter de tu plataforma y haz que sea ejecutable:

    VERSION=v0.2.6
    
    curl -Lo gatekeeper-securitycenter "https://github.com/GoogleCloudPlatform/gatekeeper-securitycenter/releases/download/${VERSION}/gatekeeper-securitycenter_$(uname -s)_$(uname -m)"
    
    chmod +x gatekeeper-securitycenter
    
  7. Usa la herramienta de gatekeeper-securitycenter a fin de crear una fuente de Security Command Center para tu organización. Captura el nombre de la fuente completo en una variable de entorno.

    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')
    

    Este comando crea una fuente con el nombre visible Gatekeeper. Este nombre visible se puede ver en Security Command Center. Puedes usar un nombre visible y una descripción diferentes.

    Si recibes una respuesta con el mensaje de error The caller does not have permission, espera un minuto y vuelve a intentarlo. Este error puede ocurrir si aún no se aplicaron las vinculaciones de administración de identidades y accesos (IAM).

Crea hallazgos con la línea de comandos

Puedes crear hallazgos de Security Command Center desde el Policy Controller y los incumplimientos de restricciones de OPA Gatekeeper con la herramienta gatekeeper-securitycenter como parte de una canalización de compilación o una tarea programada.

  1. En Cloud Shell, crea una cuenta de servicio de Google y almacena el nombre de la cuenta de servicio en una variable de entorno de la siguiente manera:

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

    Usa esta cuenta de servicio de Google a fin de crear hallazgos para tu fuente de Security Command Center.

  2. Otorga la función Editor de hallazgos del centro de seguridad a la cuenta de servicio de Google para la fuente:

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

    Esta función proporciona los permisos securitycenter.findings.* necesarios para crear y editar hallazgos. Cuando ejecutas este comando, roba la identidad de la cuenta de servicio de Google del administrador.

  3. Otorga la función Consumidor de Service Usage a la cuenta de servicio de Google del editor de hallazgos a nivel de la organización:

    gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \
        --member "serviceAccount:$FINDINGS_EDITOR_SA" \
        --role roles/serviceusage.serviceUsageConsumer
    
  4. Otorga a tu identidad de usuario la función de creador de tokens de cuentas de servicio para la cuenta de servicio de Google del editor de hallazgos:

    gcloud iam service-accounts add-iam-policy-binding \
        $FINDINGS_EDITOR_SA \
        --member "user:$(gcloud config get-value account)" \
        --role roles/iam.serviceAccountTokenCreator
    
  5. Muestra los hallazgos en la terminal en lugar de crearlos en Security Command Center:

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

    Este comando usa tu contexto de kubeconfig actual de forma predeterminada. Si deseas usar un archivo kubeconfig diferente, usa la marca --kubeconfig.

    El resultado es similar al siguiente:

    [
      {
        "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
          }
        }
      }
    ]
    

    En el resultado anterior, API_SERVER es la dirección IP o el nombre de host del servidor de API de tu clúster de GKE.

    Para obtener más información sobre el significado de los campos, consulta la página Buscar un recurso de la API de Security Command Center.

  6. Crea hallazgos en Security Command Center:

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

    Cuando ejecutas este comando, actúas en nombre de la cuenta de servicio de Google del editor de hallazgos.

    El resultado incluye create finding, lo que significa que la herramienta de línea de comandos de gatekeeper-securitycenter creó un hallazgo. El atributo findingID de ese resultado contiene el nombre completo del hallazgo en el formato:

    organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID
    

    En este resultado, se ilustra lo siguiente:

    • ORGANIZATION_ID es el ID de la organización de Google Cloud.
    • SOURCE_ID es el ID de la fuente de Security Command Center.
    • FINDING_ID es el ID del hallazgo

    Para ver el hallazgo, consulta la sección Visualiza los hallazgos.

    Si recibes una respuesta con el mensaje de error The caller does not have permission, espera un minuto y vuelve a intentarlo. Este error puede ocurrir si aún no se aplicaron las vinculaciones de administración de identidades y accesos (IAM).

Crea hallazgos con un controlador de Kubernetes

Puedes implementar gatekeeper-securitycenter como un controlador en el clúster de GKE. Este controlador verifica de forma periódica si existen incumplimientos de restricciones y crea un resultado en Security Command Center para cada incumplimiento.

Si el recurso cumple con los requisitos, el controlador establece el estado del hallazgo existente en INACTIVE.

  1. En Cloud Shell, crea una vinculación de política de IAM de Workload Identity para permitir que la gatekeeper-securitycenter-controller cuenta de servicio de Kubernetes del espacio de nombres gatekeeper-securitycenter robe la identidad de la cuenta de servicio de Google del editor de hallazgos:

    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
    

    Debes crear la cuenta de servicio y el espacio de nombres de Kubernetes cuando implementes el controlador.

  2. Recupera el paquete kpt para el controlador gatekeeper-securitycenter:

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

    Con este comando, se crea un directorio llamado manifests que contiene los archivos de manifiesto del recurso para el controlador.

    kpt es una herramienta de línea de comandos que te permite administrar, manipular, personalizar y aplicar recursos de Kubernetes. En este instructivo, usas kpt para personalizar los manifiestos de recursos de tu entorno.

  3. Configura el nombre de la fuente de Security Command Center:

    kpt fn eval manifests \
        --image gcr.io/kpt-fn/apply-setters:v0.2 -- \
        "source=$SOURCE_NAME"
    
  4. Configura el nombre del clúster:

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

    El controlador agrega el nombre del clúster como una propiedad de origen a los hallazgos que crea en Security Command Center. Si tienes varios clústeres, este nombre te ayuda a encontrar a qué clúster pertenece un hallazgo.

  5. Para vincular la cuenta de servicio del controlador de Kubernetes a la cuenta de servicio de Google del editor de hallazgos, agrega la anotación Workload Identity:

    kustomize cfg annotate manifests \
        --kind ServiceAccount \
        --name gatekeeper-securitycenter-controller \
        --namespace gatekeeper-securitycenter \
        --kv "iam.gke.io/gcp-service-account=$FINDINGS_EDITOR_SA"
    
  6. Inicializa el paquete del controlador:

    kpt live init manifests
    
  7. Aplica los recursos del controlador al clúster:

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

    Con este comando, se crean los siguientes recursos en tu clúster:

    • Un espacio de nombres llamado gatekeeper-securitycenter
    • Una cuenta de servicio llamada gatekeeper-securitycenter-controller
    • Una función de clúster que proporcione acceso a get y list a todos los recursos en todos los grupos de API. Esta función es obligatoria porque el controlador recupera los recursos que generaron incumplimientos de políticas.
    • Una vinculación de función de clúster que otorga la función de clúster a la cuenta de servicio.
    • Una implementación llamada gatekeeper-securitycenter-controller-manager
    • Un mapa de configuración llamado gatekeeper-securitycenter-config que contiene los valores de configuración de la implementación.

    El comando también espera a que los recursos estén listos.

  8. Verifica que el controlador pueda leer los incumplimientos de restricciones y comunicarse con la API de Security Command Center mediante el registro del controlador:

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

    Verás entradas de registro con el mensaje syncing findings.

    Para dejar de seguir el registro, presiona Ctrl+C.

  9. Para verificar que el controlador pueda crear resultados nuevos, crea una política y un recurso que la infrinja. El Pod usa los resúmenes de imágenes para hacer referencia a las imágenes de contenedor.

    Ve al directorio del repositorio de la biblioteca de OPA Gatekeeper:

    cd ~/gatekeeper-library
    
  10. Crea un pod llamado opa-disallowed en el espacio de nombres default:

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

    A continuación, se muestra el manifiesto que aplicas para crear el 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"
    

    Esta especificación de Pod hace referencia a una imagen de contenedor por etiqueta en lugar de por resumen.

  11. Crea una plantilla de restricciones llamada k8simagedigests:

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

    El siguiente es el manifiesto de la planilla de restricción:

    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. Crea una restricción llamada container-image-must-have-digest:

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

    El siguiente es el manifiesto de restricción:

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

    Esta restricción solo se aplica al espacio de nombres default.

  13. Sigue el registro del controlador:

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

    Después de unos minutos, verás una entrada de registro con el mensaje create finding. Este mensaje significa que el controlador gatekeeper-securitycenter creó un resultado.

    Para dejar de seguir el registro, presiona Ctrl+C.

  14. Para verificar que el controlador pueda establecer el estado del hallazgo en INACTIVE cuando Policy Controller o OPA Gatekeeper ya no informen incumplimiento, borra el pod llamado opa-disallowed en el espacio de nombres default:

    kubectl delete pod opa-disallowed --namespace default
    
  15. Sigue el registro del controlador:

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

    Después de unos minutos, verás una entrada de registro con el mensaje updating finding state y el atributo "state":"INACTIVE". Este mensaje significa que el controlador configuró el estado de búsqueda como inactivo.

    Para dejar de seguir el registro, presiona Ctrl+C.

Visualiza los hallazgos

Puedes ver los hallazgos de Security Command Center en la terminal y en Google Cloud Console.

  1. En Cloud Shell, usa la herramienta de gcloud a fin de enumerar los hallazgos para la organización y la fuente:

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

    Usa el comando basename para obtener el ID numérico de la fuente del nombre completo de la fuente.

    El resultado es similar al siguiente:

    [
      {
        "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",
          [...]
      }
    ]
    

    En este resultado, se ilustra lo siguiente:

    • API_SERVER es la dirección IP o el nombre de host de tu servidor de API del clúster de GKE.
    • ORGANIZATION_ID es el ID de la organización de Google Cloud.
    • SOURCE_ID es tu ID de la fuente del Security Command Center.
    • FINDING_ID es el ID del hallazgo

    Para obtener información sobre el significado de los atributos de búsqueda, consulta el recurso de hallazgos en la API de Security Command Center.

  2. Para ver los hallazgos en Cloud Console, ve a la pestaña hallazgos de Security Command Center.

    Ir a hallazgos

  3. Selecciona tu organización y haz clic en Seleccionar.

  4. Haz clic en Ver por Tipo de fuente.

  5. En la lista Tipo de origen, haz clic en Gatekeeper. Si Gatekeeper no está en la lista Tipo de origen, borra los filtros de la lista de resultados.

  6. En la lista de hallazgos, haz clic en uno para ver los atributos de hallazgo y las propiedades de origen.

    Si un recurso ya no causa un incumplimiento debido a un cambio en el recurso o la política, el controlador establece el estado del hallazgo en inactivo. Este cambio puede tardar unos minutos en aparecer en Security Command Center.

    Según la configuración predeterminada, Security Command Center muestra los hallazgos activos. Para ver los resultados inactivos, haz clic en Más opciones, selecciona Incluir resultados inactivos y, luego, en Aceptar.

Soluciona problemas

  • Si el Policy Controller o el OPA Gatekeeper no informa incumplimientos en el campo status de los objetos de restricción, usa Cloud Shell para ver los registros del controlador de auditoría:

    kubectl logs deployment/gatekeeper-audit --namespace gatekeeper-system \
        --all-containers
    
  • Si el controlador gatekeeper-securitycenter no crea hallazgos en Security Command Center, puedes ver los registros del administrador de controladores:

    kubectl logs deployment/gatekeeper-securitycenter-controller-manager \
        --namespace gatekeeper-securitycenter --all-containers
    
  • Si la herramienta de línea de comandos gatekeeper-securitycenter informa los errores, puedes aumentar la verbosidad del resultado del registro configurando la variable de entorno DEBUG como true antes de ejecutargatekeeper-securitycenter:

    export DEBUG=true
    

Si tienes otros problemas con este instructivo, te recomendamos que revises los siguientes documentos:

Automatiza la configuración

Para implementaciones futuras, puedes automatizar los pasos de este instructivo si sigues las instrucciones en el repositorio de GitHub gatekeeper-securitycenter.

Limpia

Para evitar que se apliquen cargos adicionales a tu cuenta de Google Cloud por los recursos que se usaron en este instructivo, borra los recursos individuales.

Borra los recursos individuales

  1. En Cloud Shell, borra el clúster de GKE:

    gcloud container clusters delete gatekeeper-securitycenter-tutorial \
        --zone us-central1-f --async --quiet
    
  2. Borra los archivos gatekeeper-library:

    rm -rf ~/gatekeeper-library
    
  3. Borra las vinculaciones de políticas de 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. Borra las cuentas de servicio de 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
    

¿Qué sigue?