Coder un module personnalisé pour Security Health Analytics

Cette page explique comment coder une définition de module personnalisé à l'aide du langage CEL (Common Expression Language) et YAML.

Utilisez la Google Cloud CLI pour importer vos définitions de modules personnalisés dans Security Health Analytics.

Dans le fichier YAML, une définition de module personnalisé consiste en un ensemble structuré de propriétés que vous utilisez pour définir les éléments suivants d'un module personnalisé de Security Health Analytics:

  • Ressources à analyser.
  • Logique de détection à utiliser.
  • Informations à fournir à vos équipes de sécurité afin qu'elles puissent rapidement comprendre, trier et résoudre le problème détecté.

Les propriétés spécifiques obligatoires et facultatives qui constituent une définition YAML sont abordées dans la section Étapes de codage.

Éviter de créer des détecteurs redondants

Pour contrôler le volume des résultats, évitez de créer et d'exécuter des modules contenant des fonctionnalités redondantes.

Par exemple, si vous créez un module personnalisé qui vérifie les clés de chiffrement qui ne sont pas alternées après 30 jours, envisagez de désactiver le détecteur intégré d'analyse de l'état de la sécurité KMS_KEY_NOT_ROTATED, car sa vérification, qui utilise une valeur de 90 jours, serait superflue.

Pour plus d'informations sur la désactivation des détecteurs, consultez la page Activer et désactiver les détecteurs.

Étapes de codage

Vous codez la définition d'un module personnalisé pour Security Health Analytics sous la forme d'une série de propriétés YAML, dont certaines contiennent des expressions CEL.

Pour coder un module de définition personnalisé, procédez comme suit:

  1. Créez un fichier texte avec l'extension de nom de fichier yaml.

  2. Dans le fichier texte, créez une propriété resource_selector et spécifiez un à cinq types de ressources que le module personnalisé doit analyser. Un type de ressource ne peut pas être spécifié plusieurs fois dans une définition de module personnalisé. Exemple :

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

    Les types de ressources que vous spécifiez doivent être compatibles avec Security Command Center. Pour obtenir la liste des types de ressources acceptés, consultez la page Types de ressources acceptés.

  3. Créez une propriété predicate et spécifiez une ou plusieurs expressions CEL qui vérifient les propriétés des types de ressources à analyser. Toutes les propriétés que vous référencez dans les expressions CEL doivent exister dans la définition de l'API Google Cloud de chaque type de ressource spécifié sous resource_selector. Pour déclencher un résultat, l'expression doit renvoyer TRUE. Par exemple, dans l'expression suivante, seules les valeurs rotationPeriod supérieures à 2592000s déclenchent un résultat.

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

    Pour obtenir de l'aide sur l'écriture d'expressions CEL, consultez les ressources suivantes:

  4. Créez une propriété description qui explique la faille ou la mauvaise configuration détectée par le module personnalisé. Cette explication apparaît dans chaque instance de résultat pour aider les enquêteurs à comprendre le problème détecté. Le texte doit être placé entre guillemets. Exemple :

    description: "The rotation period of
     the identified cryptokey resource exceeds 30 days, the
     maximum rotation period that our security guidelines allow."
  5. Créez une propriété recommendation qui explique comment résoudre le problème détecté. La gcloud CLI nécessite un caractère d'échappement avant certains caractères, comme les guillemets. L'exemple suivant montre comment la barre oblique inverse est utilisée pour échapper chaque ensemble de guillemets:

    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 vous créez ou mettez à jour un module personnalisé à l'aide de la console Google Cloud, les caractères d'échappement ne sont pas requis.

  6. Créez une propriété severity et spécifiez le niveau de gravité par défaut des résultats créés par ce module. Les valeurs couramment utilisées pour la propriété severity sont LOW, MEDIUM, HIGH et CRITICAL. Par exemple :

    severity: MEDIUM
  7. Si vous le souhaitez, créez une propriété custom_output et spécifiez des informations supplémentaires à renvoyer avec chaque résultat. Spécifiez les informations à renvoyer sous la forme d'une ou plusieurs paires nom/valeur. Vous pouvez renvoyer la valeur d'une propriété de la ressource analysée ou une chaîne littérale. Les propriétés doivent être spécifiées en tant que resource.PROPERTY_NAME. Les chaînes littérales doivent être placées entre guillemets. L'exemple suivant montre une définition custom_output qui renvoie à la fois une valeur de propriété, la valeur de rotationPeriod dans la ressource CryptoKey analysée et une chaîne de texte, "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. Enregistrez le fichier dans un emplacement auquel votre gcloud CLI peut accéder.

  9. Importez la définition dans Security Health Analytics à l'aide de la commande suivante:

     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
    

    Remplacez les valeurs suivantes :

    • ORGANIZATION_ID par l'ID de l'organisation parente du module personnalisé, ou remplacez l'option --organization par --folders ou --project et spécifiez l'ID du dossier ou du projet parent.
    • MODULE_DISPLAY_NAME avec un nom à afficher en tant que catégorie de résultats lorsque le module personnalisé renvoie des résultats. Le nom doit comporter entre 1 et 128 caractères, commencer par une lettre minuscule et ne contenir que des caractères alphanumériques et des traits de soulignement.
    • DEFINITION_FILE_NAME par le chemin d'accès et le nom du fichier YAML contenant la définition du module personnalisé.

    Pour en savoir plus sur l'utilisation des modules personnalisés de Security Health Analytics, consultez la page Utiliser des modules personnalisés pour Security Health Analytics.

Latences d'analyse pour les nouveaux modules personnalisés

La création d'un module personnalisé ne déclenche pas de nouvelle analyse.

Security Health Analytics ne commence à utiliser un nouveau module personnalisé qu'après avoir effectué l'une des opérations suivantes:

  • Première analyse par lot après la création du module personnalisé. Selon le moment où vous créez un module personnalisé dans la planification des analyses par lot, vous devrez peut-être attendre jusqu'à 24 heures avant que Security Health Analytics ne commence à utiliser le module personnalisé.
  • La modification d'une ressource cible déclenche une analyse en temps réel.

Exemple de définition de module personnalisé

L'exemple suivant montre une définition de module personnalisé terminée qui déclenche un résultat si la valeur de la propriété rotationPeriod d'une ressource cloudkms.googleapis.com/CryptoKey est supérieure à 2 592 000 secondes (30 jours). L'exemple renvoie deux valeurs facultatives dans la section custom_output: la valeur de resource.rotationPeriod et une note sous forme de chaîne de texte.

Dans l'exemple, notez les éléments suivants:

  • Le type d'élément ou de ressource à vérifier est indiqué dans la section resource_selector sous resource_types.
  • La vérification que le module effectue sur les ressources, c'est-à-dire sa logique de détection, est définie dans la section predicate, précédée de expression.
  • Deux propriétés sources personnalisées, duration et violation, sont définies dans la section custom_output.
  • L'explication du problème détecté est spécifiée dans la propriété description.
  • Les conseils pour résoudre le problème détecté sont spécifiés dans la propriété recommendation. Étant donné que les guillemets apparaissent dans les conseils, un caractère d'échappement à barre oblique inverse est requis avant chacun d'eux.
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"

Référencer des propriétés de ressource et de stratégie dans des modules personnalisés

Quelle que soit la méthode utilisée pour créer un module personnalisé (à l'aide de la console Google Cloud ou en écrivant la définition vous-même), vous devez être en mesure de rechercher les propriétés que vous pouvez évaluer dans le module personnalisé. Vous devez également savoir comment référencer ces propriétés dans une définition de module personnalisé.

Trouver les propriétés d'une ressource ou d'une règle

Les propriétés d'une ressource Google Cloud sont définies dans la définition d'API de la ressource. Pour trouver cette définition, cliquez sur le nom de la ressource dans Types de ressources acceptés.

Vous trouverez les propriétés d'une stratégie dans la documentation de référence de l'API IAM. Pour connaître les propriétés d'une stratégie, consultez la section Policy.

Référencer une propriété de ressource dans une définition de module personnalisé

Lorsque vous créez un module personnalisé, toutes les références directes à la propriété d'une ressource analysée doivent commencer par resource, suivi des propriétés parentes et, enfin, de la propriété cible. Les propriétés sont séparées par un point, au moyen d'une notation par points de style JSON.

Voici des exemples de propriétés de ressources et la façon dont elles peuvent être récupérées:

  • resourceName: stocke le nom complet d'une ressource dans l'inventaire des éléments cloud, par exemple //cloudresourcemanager.googleapis.com/projects/296605646631.
  • resource.rotationPeriod: où rotationPeriod est une propriété de resource.
  • resource.metadata.name: où name est une sous-propriété de metadata, qui est une sous-propriété de resource.

Propriétés de la stratégie IAM de référence

Vous pouvez créer des expressions CEL qui évaluent la stratégie IAM d'une ressource en référençant les propriétés de la stratégie IAM de la ressource. Les seules propriétés disponibles sont les liaisons et les rôles dans les liaisons.

Lorsque vous faites référence aux propriétés d'une stratégie IAM, policy est la propriété de premier niveau.

Voici des exemples de propriétés de stratégie IAM et la manière dont elles peuvent être récupérées:

  • policy.bindings, où bindings est une propriété de policy.
  • policy.version, où version est une propriété de policy.

Pour plus d'exemples, consultez la section Exemples d'expressions CEL.

Pour en savoir plus sur les propriétés d'une stratégie, consultez la section Policy.

Écrire des expressions CEL

Lorsque vous créez un module personnalisé, vous utilisez des expressions CEL pour évaluer les propriétés de la ressource analysée. Vous pouvez également utiliser des expressions CEL pour définir des paires name-value personnalisées qui renvoient des informations supplémentaires avec vos résultats.

Que vous créiez un module personnalisé dans la console Google Cloud ou que vous écriviez vous-même la définition de ce module dans un fichier YAML, les expressions CEL que vous définissez sont identiques.

Expressions CEL pour la logique de détection

Vous codez la logique de détection d'un module personnalisé en utilisant des expressions CEL avec des opérateurs CEL standards afin d'évaluer les propriétés des ressources analysées.

Vos expressions peuvent être de simples vérifications d'une valeur unique ou des expressions composées plus complexes qui vérifient plusieurs valeurs ou conditions. Dans les deux cas, l'expression doit renvoyer une valeur booléenne true pour déclencher un résultat.

Si vous créez un module personnalisé dans la console Google Cloud, écrivez ces expressions dans l'éditeur d'expressions de la page Configurer le module.

Si vous codez un module personnalisé dans un fichier YAML, vous ajoutez ces expressions sous la propriété predicate.

Que vous utilisiez la console Google Cloud ou un fichier YAML, les expressions CEL qui évaluent les propriétés de ressources doivent respecter les règles suivantes:

  • Les propriétés que vous spécifiez dans une expression CEL doivent être des propriétés de la ressource analysée, comme défini dans la définition d'API du type de ressource.
  • Si un module personnalisé évalue plusieurs types de ressources, les propriétés que vous spécifiez dans les expressions CEL doivent être communes à chaque type de ressource évalué par le module personnalisé.

    Par exemple, si vous définissez un module personnalisé appelé invalid_cryptokey qui vérifie deux types de ressources : cloudkms.googleapis.com/CryptoKey et cloudkms.googleapis.com/CryptoKeyVersion, vous pouvez écrire l'expression suivante, car les types de ressources CryptoKey et CryptoKeyVersion incluent la propriété name:

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

    Toutefois, vous ne pouvez pas spécifier l'expression suivante dans le module personnalisé invalid_cryptokey, car les propriétés importTime et rotationPeriod évaluées par l'expression ne sont pas partagées par les deux types de ressources:

    predicate:
    resource.importTime >= timestamp("2022-10-02T15:01:23Z") || resource.rotationPeriod > duration("2592000s")
  • Toutes les énumérations d'une expression CEL doivent être représentées par des chaînes. Par exemple, l'expression suivante est valide pour le type de ressource cloudkms.googleapis.com/CryptoKeyVersion:

    resource.state = "PENDING_GENERATION"
  • Le résultat des expressions CEL que vous définissez dans la propriété predicate doit être une valeur booléenne. Un résultat n'est déclenché que si le résultat est true.

Pour en savoir plus sur le CEL, consultez les pages suivantes:

Exemples d'expressions CEL

Le tableau suivant répertorie certaines expressions CEL pouvant être utilisées pour évaluer les propriétés de ressources. Vous pouvez les utiliser à la fois dans la console Google Cloud et dans les définitions de module personnalisé YAML.

Type de ressource Explication Expression CEL
Toute ressource avec une stratégie IAM Vérification des règles IAM pour identifier les membres extérieurs au domaine !policy.bindings.all(binding, binding.members.all(m ,!m.endsWith('@gmail.com')))
cloudkms.googleapis.com/CryptoKey Vérification de la période de rotation des clés Cloud KMS has(resource.rotationPeriod) && resource.rotationPeriod > duration('60h')
Plusieurs types de ressources avec une seule règle Vérifiez si le nom de la ressource commence par dev ou devAccess selon le type de ressource (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 Règle d'appairage de cloud privé virtuel pour faire correspondre les pairs du réseau 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 N'autoriser que le trafic d'entrée interne pour la fonction Cloud has(resource.ingressSettings) && resource.ingressSettings.matches('ALLOW_INTERNAL_ONLY')
compute.googleapis.com/Instance Le nom de la ressource correspond au modèle resource.name.matches('^gcp-vm-(linux|windows)-v\\d+$')
serviceusage.googleapis.com/Service Autoriser uniquement l'activation des API liées au stockage 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 Seules les adresses IP publiques figurant sur la liste d'autorisation sont autorisées (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 Vérifier si les ID de projet d'un cluster Dataproc contiennent les sous-chaînes "Testing" ou "Development" has(resource.projectId) && resource.projectId.contains('testing') || resource.projectId.contains('development')

Expressions CEL pour les propriétés de résultat personnalisées

Si vous souhaitez renvoyer des informations supplémentaires pour chaque résultat pouvant être utilisées dans les requêtes de recherche, vous pouvez définir jusqu'à 10 propriétés personnalisées à renvoyer avec les résultats générés par vos modules personnalisés.

Les propriétés personnalisées apparaissent dans les propriétés sources du résultat dans son fichier JSON et dans l'onglet Propriétés sources des détails du résultat dans la console Google Cloud.

Vous définissez les propriétés personnalisées sous forme de paires name-value.

Si vous créez un module personnalisé dans la console Google Cloud, vous devez définir les paires name-value dans la section Propriétés de résultat personnalisées de la page Définir les détails du résultat.

Si vous codez un module personnalisé dans un fichier YAML, répertoriez les paires name-value en tant que properties dans la propriété custom_output.

Que vous utilisiez la console Google Cloud ou un fichier YAML, les règles suivantes s'appliquent:

  • Spécifiez name en tant que chaîne de texte sans guillemets.
  • Spécifiez value comme suit:

    • Pour renvoyer la valeur d'une propriété, spécifiez-la au format suivant:

      RESOURCE_TYPE.PROPERTY.PROPERTY_TO_RETURN

    Dans l'exemple :

    • RESOURCE_TYPE peut être resource ou policy.
    • PROPERTY : une ou plusieurs propriétés parentes de la propriété contenant la valeur à renvoyer.
    • PROPERTY_TO_RETURN est la propriété qui contient la valeur à renvoyer.

    • Pour renvoyer une chaîne de texte, placez-la entre guillemets.

L'exemple suivant montre deux paires name-value correctement définies sous custom_output dans un fichier YAML:

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

Étapes suivantes

Pour tester, envoyer, afficher et mettre à jour des modules personnalisés, consultez les pages suivantes: