Cómo codificar un módulo personalizado para las estadísticas del estado de la seguridad

En esta página, se explica cómo codificar una definición de módulo personalizada con Common Expression Language (CEL) y YAML.

Usa Google Cloud CLI para subir tus definiciones de módulos personalizados a Security Health Analytics.

En el archivo YAML, una definición de módulo personalizado consiste en un conjunto estructurado de propiedades que usas para definir los siguientes elementos de un módulo personalizado de Security Health Analytics:

  • Los recursos que se analizarán.
  • La lógica de detección que se usará.
  • La información que debes proporcionar a tus equipos de seguridad para que puedan comprender, clasificar y resolver rápidamente el problema detectado

Las propiedades específicas obligatorias y opcionales que conforman una definición de YAML se describen en Pasos de codificación.

Evita crear detectores redundantes

Para controlar el volumen de resultados, evita crear y ejecutar módulos que contengan funcionalidad redundante.

Por ejemplo, si creas un módulo personalizado que compruebe si hay claves de encriptación que no se rotan después de 30 días, considera inhabilitar el detector KMS_KEY_NOT_ROTATED incorporado de las estadísticas de estado de seguridad, ya que su verificación, que usa un valor de 90 días, sería superflua.

Para obtener más información sobre cómo inhabilitar detectores, consulta Habilita e inhabilita los detectores.

Pasos de codificación

Programa la definición de un módulo personalizado para Security Health Analytics como una serie de propiedades YAML, algunas de las cuales contienen expresiones CEL.

Para codificar un módulo de definición personalizado, sigue estos pasos:

  1. Crea un archivo de texto con la extensión de nombre de archivo yaml.

  2. En el archivo de texto, crea una propiedad resource_selector y especifica de uno a cinco tipos de recursos para que el módulo personalizado analice. No se puede especificar un tipo de recurso más de una vez en una definición de módulo personalizado. Por ejemplo:

    resource_selector:
     resource_types:
     ‐ cloudkms.googleapis.com/CryptoKey

    Los tipos de recursos que especifiques deben ser compatibles con Security Command Center. Para obtener una lista de los tipos de recursos admitidos, consulta Tipos de recursos admitidos.

  3. Crea una propiedad predicate y especifica una o más expresiones CEL que verifiquen las propiedades de los tipos de recursos que se analizarán. Todas las propiedades a las que hagas referencia en las expresiones de CEL deben existir en la definición de la API de Google Cloud de cada tipo de recurso que especifiques en resource_selector. Para activar un hallazgo, la expresión debe resolverse en TRUE. Por ejemplo, en la siguiente expresión, solo los valores de rotationPeriod mayores que 2592000s activan un hallazgo.

    predicate:
     expression: resource.rotationPeriod > duration("2592000s")

    Para obtener ayuda con la escritura de expresiones CEL, consulta los siguientes recursos:

  4. Crea una propiedad description que explique la vulnerabilidad o la configuración incorrecta que detecta el módulo personalizado. Esta explicación aparece en cada instancia de hallazgo para ayudar a los investigadores a comprender el problema detectado. El texto debe estar entre comillas. Por ejemplo:

    description: "The rotation period of
     the identified cryptokey resource exceeds 30 days, the
     maximum rotation period that our security guidelines allow."
  5. Crea una propiedad recommendation que explique cómo corregir el problema detectado. Gcloud CLI requiere un carácter de escape antes de ciertos caracteres, como las comillas. En el siguiente ejemplo, se muestra el uso de la barra invertida para escapar cada conjunto de comillas:

    recommendation: "To fix this issue go to
      https://console.cloud.google.com/security/kms. Click the key-ring that
      contains the key. Click the key. Click \"Edit rotation period\". Then
      set the rotation period to at most 30 days."
    

    Si creas o actualizas un módulo personalizado con la consola de Google Cloud, no se requieren caracteres de escape.

  6. Crea una propiedad severity y especifica la gravedad predeterminada para los hallazgos que crea este módulo. Los valores más usados para la propiedad severity son LOW, MEDIUM, HIGH y CRITICAL. Por ejemplo:

    severity: MEDIUM
  7. De manera opcional, crea una propiedad custom_output y especifica información adicional para mostrar con cada hallazgo. Especifica la información que se mostrará como uno o más pares nombre-valor. Puedes mostrar el valor de una propiedad del recurso analizado o una cadena literal. Las propiedades deben especificarse como resource.PROPERTY_NAME. Las cadenas literales deben estar entre comillas. En el siguiente ejemplo, se muestra una definición de custom_output que muestra un valor de propiedad, el valor de rotationPeriod en el recurso CryptoKey analizado y una cadena de texto, "Excessive rotation period for CryptoKey":

     custom_output:
       properties:
         - name: duration
           value_expression:
             expression: resource.rotationPeriod
         - name: note
           value_expression:
             expression: "Excessive rotation period for CryptoKey"
    
  8. Guarda el archivo en una ubicación a la que gcloud CLI pueda acceder.

  9. Sube la definición a Security Health Analytics con el siguiente comando:

     gcloud scc custom-modules sha create \
         --organization=organizations/ORGANIZATION_ID \
         --display-name="MODULE_DISPLAY_NAME" \
         --enablement-state="ENABLED" \
         --custom-config-from-file=DEFINITION_FILE_NAME.yaml
    

    Reemplaza los siguientes valores:

    • ORGANIZATION_ID por el ID de la organización superior del módulo personalizado o reemplaza la marca --organization por --folders o --project y especifica el ID de la carpeta o el proyecto superior.
    • MODULE_DISPLAY_NAME con un nombre para mostrarse como la categoría de resultado cuando el módulo personalizado muestre resultados. El nombre debe tener entre 1 y 128 caracteres, comenzar con una letra minúscula y contener solo caracteres alfanuméricos o guiones bajos.
    • DEFINITION_FILE_NAME con la ruta de acceso y el nombre del archivo del archivo YAML que contiene la definición del módulo personalizado.

    Para obtener más información sobre cómo trabajar con módulos personalizados de Security Health Analytics, consulta Cómo usar módulos personalizados para Security Health Analytics.

Cómo analizar latencias para módulos personalizados nuevos

Crear un módulo personalizado no activa un nuevo análisis.

Las estadísticas del estado de la seguridad no comienzan a usar un nuevo módulo personalizado hasta que se produce una de las siguientes situaciones:

  • El primer análisis por lotes después de crear el módulo personalizado Según el momento en que crees un módulo personalizado en tu programación de análisis por lotes, es posible que debas esperar hasta 24 horas antes de que las estadísticas del estado de la seguridad comiencen a usar el módulo personalizado.
  • Un cambio en un recurso de destino activa un análisis en tiempo real.

Ejemplo de definición de módulo personalizado

En el siguiente ejemplo, se muestra una definición de módulo personalizado completa que activa un hallazgo si el valor de la propiedad rotationPeriod de un recurso cloudkms.googleapis.com/CryptoKey es superior a 2,592,000 segundos (30 días). El ejemplo muestra dos valores opcionales en la sección custom_output: el valor de resource.rotationPeriod y una nota como una cadena de texto.

En el ejemplo, ten en cuenta los siguientes elementos:

  • El tipo de activo o recurso que se debe verificar se indica en la sección resource_selector en resource_types.
  • La verificación que realiza el módulo en los recursos, su lógica de detección, se define en la sección predicate precedida por expression.
  • En la sección custom_output, se definen dos propiedades de fuente personalizadas, duration y violation.
  • La explicación del problema que se detectó se especifica en la propiedad description.
  • La guía para solucionar el problema detectado se especifica en la propiedad recommendation. Debido a que aparecen comillas en la guía, se requiere un carácter de escape de barra invertida antes de cada comilla.
severity: HIGH
description: "Regular key rotation helps provide protection against
compromised keys, and limits the number of encrypted messages available
to cryptanalysis for a specific key version."
recommendation: "To fix this issue go to
https://console.cloud.google.com/security/kms. Click the key-ring that
contains the key. Click the key. Click \"Edit rotation period\". Then
set the rotation period to at most 30 days."
resource_selector:
  resource_types:
  - cloudkms.googleapis.com/CryptoKey
predicate:
  expression: resource.rotationPeriod > duration("2592000s")
custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.rotationPeriod
    - name: violation
      value_expression:
        expression:
          "Excessive rotation period for CryptoKey"

Cómo hacer referencia a propiedades de recursos y políticas en módulos personalizados

Independientemente del método que uses para crear un módulo personalizado (con la consola de Google Cloud o escribiendo la definición por tu cuenta), debes poder buscar las propiedades que puedes evaluar en el módulo personalizado. También debes saber cómo hacer referencia a esas propiedades en una definición de módulo personalizado.

Busca las propiedades de un recurso o una política

Las propiedades de un recurso de Google Cloud se definen en la definición de la API del recurso. Para encontrar esta definición, haz clic en el nombre del recurso en Tipos de recursos admitidos.

Puedes encontrar las propiedades de una política en la documentación de referencia de la API de IAM. Para conocer las propiedades de una política, consulta Política.

Cómo hacer referencia a una propiedad de recurso en una definición de módulo personalizado

Cuando creas un módulo personalizado, todas las referencias directas a la propiedad de un recurso analizado deben comenzar con resource, seguidas de cualquier propiedad superior y, por último, la propiedad de destino. Las propiedades se separan con un punto, con una notación de punto de estilo JSON.

Los siguientes son ejemplos de propiedades de recursos y cómo se pueden recuperar:

  • resourceName: Almacena el nombre completo de un recurso en Cloud Asset Inventory, por ejemplo, //cloudresourcemanager.googleapis.com/projects/296605646631.
  • resource.rotationPeriod: En la que rotationPeriod es una propiedad de resource.
  • resource.metadata.name: En la que name es una subpropiedad de metadata, que es una subpropiedad de resource.

Consulta las propiedades de la política de IAM

Puedes crear expresiones CEL que evalúen la política de IAM de un recurso haciendo referencia a las propiedades de la política de IAM del recurso. Las únicas propiedades disponibles son las vinculaciones y los roles dentro de las vinculaciones.

Cuando se hace referencia a las propiedades de la política de IAM, policy es la propiedad de nivel superior.

Los siguientes son ejemplos de propiedades de la política de IAM y cómo se pueden recuperar:

  • policy.bindings, en el que bindings es una propiedad de policy.
  • policy.version, en el que version es una propiedad de policy.

Para ver más ejemplos, consulta Expresiones de CEL de ejemplo.

Para obtener información sobre las propiedades de una política, consulta Política.

Cómo escribir expresiones CEL

Cuando creas un módulo personalizado, usas expresiones en CEL para evaluar las propiedades del recurso analizado. De manera opcional, también puedes usar expresiones de CEL para definir pares name-value personalizados que devuelvan información adicional con tus hallazgos.

Ya sea que crees un módulo personalizado en la consola de Google Cloud o escribas tu definición de módulo personalizado en un archivo YAML, las expresiones de CEL que definas serán las mismas.

Expresiones CEL para la lógica de detección

Para codificar la lógica de detección de un módulo personalizado, usa expresiones en CEL con operadores estándar de CEL para evaluar las propiedades de los recursos analizados.

Tus expresiones pueden ser verificaciones simples de un solo valor o expresiones compuestas más complejas que verifican varios valores o condiciones. De cualquier manera, la expresión debe resolverse en un true booleano para activar un hallazgo.

Si creas un módulo personalizado en la consola de Google Cloud, debes escribir estas expresiones en el Editor de expresiones de la página Configurar módulo.

Si codificas un módulo personalizado en un archivo YAML, agrega estas expresiones debajo de la propiedad predicate.

Independientemente de si usas la consola de Google Cloud o un archivo YAML, las expresiones CEL que evalúan propiedades de recursos deben cumplir con las siguientes reglas:

  • Las propiedades que especifiques en una expresión CEL deben ser propiedades del recurso analizado, como se define en la definición de la API del tipo de recurso.
  • Si un módulo personalizado evalúa varios tipos de recursos, las propiedades que especifiques en las expresiones CEL deben ser comunes a cada tipo de recurso que evalúe el módulo personalizado.

    Por ejemplo, si defines un módulo personalizado llamado invalid_cryptokey que verifica dos tipos de recursos: cloudkms.googleapis.com/CryptoKey y cloudkms.googleapis.com/CryptoKeyVersion, puedes escribir la siguiente expresión, ya que los tipos de recursos CryptoKey y CryptoKeyVersion incluyen la propiedad name:

    predicate:
    resource.name.matches("projects/project1/locations/us-central1/keyRings/keyring1/cryptoKeys/.*")

    Sin embargo, no puedes especificar la siguiente expresión en el módulo personalizado invalid_cryptokey porque las propiedades importTime y rotationPeriod que evalúa la expresión no se comparten entre ambos tipos de recursos:

    predicate:
    resource.importTime >= timestamp("2022-10-02T15:01:23Z") || resource.rotationPeriod > duration("2592000s")
  • Todas las enums en una expresión CEL deben representarse como cadenas. Por ejemplo, la siguiente es una expresión válida para el tipo de recurso cloudkms.googleapis.com/CryptoKeyVersion:

    resource.state = "PENDING_GENERATION"
  • El resultado de las expresiones CEL que definas en la propiedad predicate debe ser un valor booleano. Un hallazgo se activa solo si el resultado es true.

Para obtener más información sobre CEL, consulta lo siguiente:

Expresiones de CEL de ejemplo

En la siguiente tabla, se enumeran algunas expresiones de CEL que se pueden usar para evaluar las propiedades de los recursos. Puedes usar estos comandos en la console de Google Cloud y en las definiciones de módulos personalizados de YAML.

Tipo de recurso Explicación Expresión CEL
Cualquier recurso con una política de IAM Verificación de la política de IAM para identificar miembros de dominios externos !policy.bindings.all(binding, binding.members.all(m ,!m.endsWith('@gmail.com')))
cloudkms.googleapis.com/CryptoKey Verificación del período de rotación de claves de Cloud KMS has(resource.rotationPeriod) && resource.rotationPeriod > duration('60h')
Varios tipos de recursos con una sola política Verifica si el nombre del recurso comienza con dev o devAccess según el tipo de recurso (resource.type == 'compute.googleapis.com/Disk' && resource.name.startsWith('projects/PROJECT_ID/regions/ REGION/disks/devAccess')) || (resource.type == 'compute.googleapis.com/Instance ' && resource.name.startsWith('projects/PROJECT_ID/zones/REGION/instances/dev-'))
compute.googleapis.com/Network Regla de vinculación de nube privada virtual para que coincida con los pares de red resource.selfLink.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/default') || resource.peerings.exists(p, p.network.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/shared$'))
cloudfunctions.googleapis.com/CloudFunction Permite solo el tráfico de entrada interno para la función de Cloud Run has(resource.ingressSettings) && resource.ingressSettings.matches('ALLOW_INTERNAL_ONLY')
compute.googleapis.com/Instance El nombre del recurso coincide con el patrón resource.name.matches('^gcp-vm-(linux|windows)-v\\d+$')
serviceusage.googleapis.com/Service Permitir que solo se habiliten las APIs relacionadas con el almacenamiento resource.state == 'ENABLED' && !( resource.name.matches('storage-api.googleapis.com') || resource.name.matches('bigquery-json.googleapis.com') || resource.name.matches('bigquery.googleapis.com') || resource.name.matches('sql-component.googleapis.com') || resource.name.matches('spanner.googleapis.com'))
sqladmin.googleapis.com/Instance Solo se permiten las IP públicas incluidas en la lista de entidades permitidas (resource.instanceType == 'CLOUD_SQL_INSTANCE' && resource.backendType == 'SECOND_GEN' && resource.settings.ipConfiguration.ipv4Enabled ) && !(resource.ipAddresses.all(ip, ip.type != 'PRIMARY' || ip.ipAddress.matches('IP_ADDRESS'))))
dataproc.googleapis.com/Cluster Verifica si los IDs de proyecto de un clúster de Dataproc contienen las substrings de prueba o desarrollo. has(resource.projectId) && resource.projectId.contains('testing') || resource.projectId.contains('development')

Expresiones CEL para propiedades de resultados personalizadas

De manera opcional, para mostrar información adicional con cada hallazgo que se puede usar en las consultas de búsqueda, puedes definir hasta diez propiedades personalizadas para mostrar con los hallazgos que generan tus módulos personalizados.

Las propiedades personalizadas aparecen en las propiedades de origen del hallazgo en su archivo JSON y en la pestaña Source properties de los detalles del hallazgo en la consola de Google Cloud.

Las propiedades personalizadas se definen como pares name-value.

Si creas un módulo personalizado en la consola de Google Cloud, debes definir los pares name-value en la sección Custom finding properties de la página Define finding details.

Si codificas un módulo personalizado en un archivo YAML, enumeras los pares name-value como properties en la propiedad custom_output.

Independientemente de si usas la consola de Google Cloud o un archivo YAML, se aplican las siguientes reglas:

  • Especifica name como una cadena de texto sin comillas.
  • Especifica value como una de las siguientes opciones:

    • Para mostrar el valor de una propiedad, especifícala en el siguiente formato:

      RESOURCE_TYPE.PROPERTY.PROPERTY_TO_RETURN

    En el ejemplo:

    • Puede ser RESOURCE_TYPE, resource o policy.
    • PROPERTY Una o más propiedades superiores de la propiedad que contiene el valor que se mostrará.
    • PROPERTY_TO_RETURN es la propiedad que contiene el valor que se mostrará.

    • Para mostrar una cadena de texto, enciérrala entre comillas.

En el siguiente ejemplo, se muestran dos pares name-value definidos correctamente en custom_output en un archivo YAML:

custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.name
    - name: property_with_text
      value_expression:
        expression: "Note content"

¿Qué sigue?

Para probar, enviar, ver y actualizar módulos personalizados, consulta las siguientes páginas: