Créer et afficher des règles de stratégie de sécurité Cloud Armor

Chaque règle de stratégie de sécurité Google Cloud Armor comporte une priorité, une condition de correspondance et une action. Cloud Armor effectue l'action de la règle de priorité la plus élevée qui correspond à une requête. Les règles dont la priorité est inférieure à celle de la règle correspondante ayant la priorité la plus élevée ne sont pas évaluées, même si elles présentent les mêmes conditions de correspondance.

Chaque règle de stratégie de sécurité accepte deux types de conditions de correspondance :

  • Une condition de correspondance de base contient des listes d'adresses IP ou des listes de plages d'adresses IP. Les conditions de correspondance de base sont définies à l'aide du flag --src-ip-ranges lors de la création d'une règle à l'aide de la Google Cloud CLI.
  • Une condition de correspondance avancée contient une expression comprenant jusqu'à cinq sous-expressions qui peuvent correspondre à divers attributs d'une requête entrante. Les conditions de correspondance avancées sont définies à l'aide du flag --expression lors de la création d'une règle à l'aide de la Google Cloud CLI.

Cette page explique comment créer et afficher des règles de stratégie de sécurité, et fournit la documentation de référence sur le langage des règles personnalisées Cloud Armor que vous utilisez pour écrire des expressions dans des conditions de correspondance avancées. Le langage des règles personnalisées Cloud Armor est un sous-ensemble de Common Expression Language (CEL).

Les expressions écrites dans le langage de règles personnalisées Cloud Armor nécessitent deux composants :

  • L'attribut : les données à inspecter
  • L'opération : comment utiliser les données

Par exemple, l'expression suivante utilise les attributs origin.ip et 198.51.100.0/24 dans l'opération inIpRange. Dans ce cas, l'expression renvoie true si origin.ip est compris dans la plage d'adresses IP 198.51.100.0/24.

inIpRange(origin.ip, '198.51.100.0/24')

Même si l'expression de l'exemple précédent ne correspond qu'à l'adresse IP client, lorsque vous l'utilisez dans une règle de stratégie de sécurité Cloud Armor, la règle est considérée comme une règle avec des conditions de correspondance avancées du point de vue du quota. Pour en savoir plus, consultez Quotas et limites de Cloud Armor.

Créer des règles de stratégie de sécurité

Suivez les étapes de cette section pour ajouter des règles à une stratégie de sécurité Cloud Armor.

Console

  1. Dans la console Google Cloud , accédez à la page Stratégies Cloud Armor.

    Accéder à la page Stratégies Cloud Armor

  2. Cliquez sur le nom de la stratégie de sécurité pour ouvrir la page Détails de la stratégie, puis cliquez sur l'onglet Règles.

  3. Cliquez sur Ajouter une règle.

  4. Facultatif : saisissez une description de la règle.

  5. Sélectionnez le mode :

    • Mode de base : autorisez ou refusez le trafic en fonction d'adresses IP ou de plages d'adresses IP.
    • Mode avancé : autorisez ou refusez le trafic en fonction d'expressions de règle.
  6. Dans le champ Correspondance, spécifiez les conditions auxquelles la règle s'applique :

    • Mode de base : saisissez une à 10 plages d'adresses IP à mettre en correspondance avec la règle. Vous pouvez ajouter jusqu'à 10 plages d'adresses IP. Pour connaître les limites, consultez Quotas et limites de Cloud Armor.

    • Mode avancé :

      • Générateur de conditions de correspondance (preview) : utilisez le générateur visuel pour créer des expressions sans écrire de code CEL brut. Combinez et regroupez des conditions, et appliquez des transformations de chaînes. Consultez Utiliser le générateur de conditions de correspondance.
      • Éditeur de conditions de correspondance : saisissez une expression avec laquelle évaluer les requêtes entrantes. Pour en savoir plus, consultez Opérations et Attributs.
  7. Dans la liste Action, sélectionnez Autoriser ou Refuser.

  8. Si vous configurez une règle de refus, sélectionnez un code de réponse dans la liste Code de réponse.

  9. Pour activer le mode Aperçu pour la règle, sélectionnez Activer.

  10. Dans le champ Priorité, saisissez un entier compris entre 0 et 2 147 483 646. Cloud Armor évalue les règles par ordre de priorité, de 0 (priorité la plus élevée) à 2 147 483 647 (priorité la plus faible). La règle par défaut a une priorité de 2 147 483 647.

  11. Cliquez sur Ajouter.

gcloud

Exécutez la commande gcloud compute security-policies rules create PRIORITY. Remplacez PRIORITY par la priorité de la règle dans la stratégie :

gcloud compute security-policies rules create PRIORITY \
    --security-policy POLICY_NAME \
    --description DESCRIPTION \
    --src-ip-ranges IP_RANGES | --expression EXPRESSION \
    --action=[ allow | deny-403 | deny-404 | deny-502 ] \
    --preview

Par exemple, la commande suivante ajoute une règle avec une priorité de 1000 pour bloquer le trafic provenant des plages d'adresses IP 192.0.2.0/24 et 198.51.100.0/24 :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --description "block traffic from 192.0.2.0/24 and 198.51.100.0/24" \
    --src-ip-ranges "192.0.2.0/24","198.51.100.0/24" \
    --action "deny-403"

Utilisez le flag --expression pour spécifier une condition. La commande suivante ajoute une règle pour autoriser le trafic provenant de l'adresse IP 1.2.3.4 qui contient la chaîne example dans l'en-tête User-Agent :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')" \
    --action allow \
    --description "Block User-Agent 'example'"

La commande suivante ajoute une règle pour bloquer les requêtes si leur cookie contient une valeur spécifique :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "has(request.headers['cookie']) && request.headers['cookie'].contains('80=SomeValue')" \
    --action deny-403 \
    --description "Cookie Block"

La commande suivante ajoute une règle pour bloquer les requêtes provenant de la région AU :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "origin.region_code == 'AU'" \
    --action deny-403 \
    --description "AU block"

La commande suivante ajoute une règle pour bloquer les requêtes provenant de la région AU et non comprises dans la plage d'adresses IP spécifiée :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "origin.region_code == \"AU\" && !inIpRange(origin.ip, '1.2.3.0/24')" \
    --action deny-403 \
    --description "country and IP block"

La commande suivante ajoute une règle pour bloquer les requêtes dont l'URI correspond à une expression régulière :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "request.path.matches('/example_path/')" \
    --action deny-502 \
    --description "regex block"

La commande suivante ajoute une règle pour bloquer les requêtes si la valeur décodée en base64 de l'en-tête user-id contient une valeur spécifique :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')" \
    --action deny-403 \
    --description "country and IP block"

La commande suivante ajoute une règle qui utilise un ensemble d'expressions préconfiguré de l'ensemble des règles de base (CRS) OWASP 4.22 pour atténuer les attaques par injection SQL (SQLi) :

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "evaluatePreconfiguredWaf('sqli-v422-stable')" \
    --action deny-403

Utiliser le générateur de conditions de correspondance

Le générateur de conditions de correspondance est une interface visuelle de la console Google Cloud qui vous aide à créer des expressions de règle Cloud Armor complexes sans écrire de code CEL (Common Expression Language). Au lieu d'écrire du code, vous pouvez utiliser l'UI structurée du compilateur pour combiner des conditions et une logique de groupe, ce qui peut vous aider à éviter les erreurs de syntaxe et à mieux visualiser la structure de votre règle. Le compilateur accepte les listes plates et la logique imbriquée jusqu'à cinq niveaux d'expressions. Utilisez cet outil lorsque vous configurez des règles pour protéger des backends multicloud ou des déploiements hybrides, où vous devrez peut-être inspecter des attributs de requête spécifiques avant d'acheminer le trafic.

Fonctionnalités du générateur de conditions de correspondance

Le générateur de conditions de correspondance inclut les fonctionnalités suivantes :

  • Logique et imbrication : combinez plusieurs conditions à l'aide des opérateurs AND et OR. Le générateur permet de regrouper et d'imbriquer jusqu'à cinq expressions.
  • Transformations de chaînes : pour les attributs basés sur des chaînes (tels que request.path ou request.headers), appliquez des transformations pour normaliser les données avant l'évaluation. Les transformations prises en charge sont les suivantes :
    • Minuscules et majuscules
    • Décodage Base64
    • Décodage d'URL et Décodage d'URL (Unicode)
    • Convertir UTF-8 en Unicode
  • Analyse bidirectionnelle : basculez entre le générateur de conditions de correspondance visuel et l'éditeur de conditions de correspondance en texte brut. L'UI analyse automatiquement le code CEL brut pour le transformer en blocs visuels.
  • Compatibilité avec les fonctions : le compilateur fournit des commandes d'interface utilisateur pour les expressions basées sur des fonctions, telles que les règles WAF préconfigurées, les groupes d'adresses et les renseignements sur les menaces.

Limites

Le générateur de conditions de correspondance est l'interface par défaut pour la création de règles avancées. Si une expression contient une logique non compatible (comme des macros inconnues), le compilateur est désactivé. Dans ce cas, utilisez le texte brut dans l'éditeur de conditions de correspondance pour modifier la règle.

De plus, la disponibilité de certaines expressions dans le compilateur dépend du niveau Google Cloud Armor Enterprise de votre projet et du type de stratégie de sécurité.

Exemples d'expressions

Vous trouverez ci-dessous des exemples d'expressions. Pour en savoir plus sur les opérations et les attributs compatibles, consultez Opérations et Attributs.

Si votre règle ou expression utilise des codes de pays ou de région ISO 3166-1 alpha-2, Cloud Armor traite chaque code indépendamment. Les règles et expressions Cloud Armor utilisent ces codes pour autoriser ou refuser les requêtes.

  • L'expression suivante met en correspondance les requêtes provenant de l'adresse IP 1.2.3.4 qui contiennent la chaîne example dans l'en-tête User-Agent :

    inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')
    

    Vous pouvez également faire correspondre la plage d'adresses IP d'un en-tête d'adresse IP client personnalisé à l'aide de l'attribut origin.user_ip :

    inIpRange(origin.user_ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')
    
  • L'expression suivante met en correspondance les requêtes qui comportent un cookie ayant une valeur spécifique :

    has(request.headers['cookie']) && request.headers['cookie'].contains('cookie_name=cookie_value')
    
  • L'expression suivante met en correspondance les requêtes provenant de la région AU :

    origin.region_code == 'AU'
    
  • L'expression suivante met en correspondance les requêtes provenant de la région AU qui ne sont pas comprises dans la plage d'adresses IP spécifiée :

    origin.region_code == "AU" && !inIpRange(origin.ip, '1.2.3.0/24')
    
  • L'expression suivante met en correspondance les requêtes qui ont un chemin d'accès de variable numéroté vers un fichier spécifique si l'URI correspond à une expression régulière :

    request.path.matches('/path/[0-9]+/target_file.html')
    
  • L'expression suivante met en correspondance les requêtes si la valeur décodée en base64 de l'en-tête user-id contient une valeur spécifique :

    has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')
    
  • L'expression suivante utilise un ensemble d'expressions préconfiguré de l'ensemble de règles OWASP CRS 4.22 pour mettre en correspondance les attaques SQLi :

    evaluatePreconfiguredWaf('sqli-v422-stable')
    

Traversée de répertoire et normalisation

Normalisez le contenu de vos règles basées sur le chemin d'accès pour gérer les règles de traversée de chemin d'accès et d'encodage, et pour créer des règles généralisées qui évitent l'utilisation de majuscules ou l'encodage spécifique au contenu.

Lorsque vous écrivez des règles qui utilisent startsWith, endsWith ou contains pour établir une correspondance avec request.path, utilisez lower et urlDecode pour normaliser le chemin d'accès avant la mise en correspondance. Cela permet d'éviter les contournements qui utilisent l'encodage d'URL ou des variations de casse.

Par exemple, pour bloquer l'accès au répertoire /admin, utilisez l'expression suivante :

request.path.lower().urlDecode().startsWith('/admin')

Cette règle bloque les requêtes pour /admin, /Admin, /a%64min et d'autres variantes.

Lorsque vous écrivez des règles qui utilisent matches pour établir une correspondance avec request.path, tenez compte de la barre oblique inverse (\) dans votre expression régulière.

Par exemple, pour bloquer l'accès au répertoire /admin, utilisez l'expression suivante pour bloquer les contournements qui utilisent la barre oblique inverse (\) :

request.path.matches(r'^/\\*admin')

Combinez cette option avec urlDecode pour gérer à la fois l'encodage d'URL et les contournements du caractère antislash (\) :

request.path.urlDecode().matches(r'^/\\*admin')

Afficher les règles de stratégie de sécurité

Les sections suivantes expliquent comment lister les règles configurées dans une stratégie de sécurité et afficher les règles WAF préconfigurées disponibles.

Lister les règles d'une stratégie de sécurité

Suivez les étapes de cette section pour lister les règles d'une stratégie de sécurité Cloud Armor.

Console

  1. Dans la console Google Cloud , accédez à la page Stratégies Cloud Armor.

    Accéder à la page Stratégies Cloud Armor

  2. Cliquez sur le nom de la stratégie de sécurité spécifique. La page Détails de la stratégie affiche les règles de la stratégie dans l'onglet Règles.

gcloud

Utilisez la commande gcloud suivante pour lister toutes les règles d'une stratégie de sécurité :

gcloud compute security-policies describe NAME

Utilisez la commande gcloud suivante pour lister toutes les règles d'une seule stratégie de sécurité dans une région spécifiée, ainsi qu'une description de cette stratégie :

gcloud compute security-policies describe NAME \
  --region REGION

Utilisez la commande gcloud suivante pour décrire une règle :

gcloud compute security-policies rules describe PRIORITY \
    --security-policy POLICY_NAME

Par exemple, la commande suivante décrit la règle ayant la priorité 1000 dans la stratégie de sécurité my-policy :

gcloud compute security-policies rules describe 1000 \
    --security-policy my-policy

Résultat :

action: deny(403)
description: block traffic from 192.0.2.0/24 and 198.51.100.0/24
kind: compute#securityPolicyRule
match:
  srcIpRanges:
  - '192.0.2.0/24'
  - '198.51.100.0/24'
preview: false
priority: 1000

Pour en savoir plus, consultez la page gcloud compute security-policies describe.

Lister les règles préconfigurées disponibles

En plus des règles que vous configurez vous-même, Cloud Armor fournit des règles préconfigurées que vous pouvez utiliser dans vos stratégies de sécurité. Vous pouvez lister les règles préconfigurées pour afficher les signatures et les règles de protection des applications prédéfinies, par exemple l'ensemble de règles de base OWASP (CRS) fourni par Cloud Armor. Ces règles contiennent des signatures intégrées que Cloud Armor évalue par rapport aux requêtes entrantes. Pour ajouter ces règles préconfigurées à des règles nouvelles ou existantes, utilisez le langage des règles personnalisées. Nous vous recommandons d'utiliser la dernière version de la règle CRS dans la mesure du possible.

gcloud

  1. Exécutez la commande gcloud compute security-policies list-preconfigured-expression-sets :

    gcloud compute security-policies list-preconfigured-expression-sets
    

    L'exemple suivant montre comment se présente le résultat de la commande :

    EXPRESSION_SET
    expression-set-1
       RULE_ID                SENSITIVITY
       expression-set-1-id-1  sensitivity-value-1
       expression-set-1-id-2  sensitivity-value-2
    expression-set-2
       alias-1
       RULE_ID                SENSITIVITY
       expression-set-2-id-1  sensitivity-value-1
       expression-set-2-id-2  sensitivity-value-2
    

    L'exemple suivant inclut un extrait du résultat réel de la commande. Notez que le résultat réel inclut toutes les règles répertoriées dans Ajuster les règles WAF Cloud Armor.

    gcloud compute security-policies list-preconfigured-expression-sets
    
    EXPRESSION_SET
    sqli-canary
        RULE_ID                          SENSITIVITY
        owasp-crs-v042200-id942120-sqli  2
        …
    xss-canary
        RULE_ID                         SENSITIVITY
        owasp-crs-v042200-id941110-xss  1
        owasp-crs-v042200-id941120-xss  2
    …
    sourceiplist-fastly
    sourceiplist-cloudflare
    sourceiplist-imperva
    

Opérations

La documentation de référence suivante décrit les opérateurs que vous pouvez utiliser avec des attributs (représentés par x, y et k) pour définir des expressions de règle.

Opérations Expressions Description
Égalité x == y Renvoie true si x est égal à y.
Égalité, littéral de chaîne x == "foo" Renvoie true si x est égal au littéral de chaîne constante donné.
Égalité, littéral de chaîne brute x == R"fo'o" Renvoie true si x est égal au littéral de chaîne brute donné qui n'interprète pas les séquences d'échappement. Les littéraux de chaîne brute sont pratiques pour exprimer des chaînes qui doivent elles-mêmes utiliser des caractères de séquence d'échappement.
Logical NOT (Opérateur logique PAS) !x Renvoie true si la valeur booléenne x est false ou renvoie false si la valeur booléenne x est true.
Différent de x != y Renvoie true si x n'est pas égal à y.
Concaténation x + y Renvoie la chaîne concaténée xy.
Logical AND (Opérateur logique ET) x && y Renvoie true si x et y sont tous deux true.
Logical OR (Opérateur logique OU) x || y Renvoie true si x, y ou les deux sont true.
Contient une sous-chaîne x.contains(y) Renvoie true si la chaîne x contient la sous-chaîne y.
Commence par la sous-chaîne x.startsWith(y) Renvoie true si la chaîne x commence par la sous-chaîne y.
Se termine par une sous-chaîne x.endsWith(y) Renvoie true si la chaîne x se termine par la sous-chaîne y.
Correspondance d'expression régulière x.matches(y) Renvoie true si la chaîne x correspond partiellement au modèle y RE2 spécifié. Le modèle RE2 est compilé à l'aide de l'option RE2::Latin1 qui désactive les fonctionnalités Unicode.
Adresse IP dans la plage inIpRange(x, y) Renvoie true si l'adresse IP x est comprise dans la plage d'adresses IP y.
Minuscules x.lower() Renvoie la valeur en minuscules de la chaîne x.
Majuscules x.upper() Renvoie la valeur en majuscules de la chaîne x.
Valeur décodée en base64 x.base64Decode() Renvoie la valeur décodée en base64 de x. Le trait de soulignement (_) et le trait d'union (-) sont d'abord remplacés par une barre oblique (/) et un signe plus (+) respectivement. Renvoie "" (chaîne vide) si x n'est pas une valeur base64 valide.
Valeur de mappage des clés m['k'] Renvoie la valeur à la clé k dans le mappage chaîne à chaîne m si k est disponible. Sinon, renvoie une erreur. L'approche recommandée consiste à vérifier d'abord la disponibilité à l'aide de "has(m['k'])==true".
Vérifier la disponibilité des clés dans un mappage has(m['k']) Renvoie true si la clé k est disponible dans le mappage m.
Convertir en entier int(x) Convertit le résultat de chaîne de x en type int. Il peut ensuite être utilisé pour établir une comparaison d'entiers à l'aide d'opérateurs arithmétiques standards tels que ">" et "<=". Cela ne fonctionne que pour les valeurs qui sont supposées être des entiers.
Longueur size(x) Renvoie la longueur de la chaîne x.
Décoder l'URL x.urlDecode() Renvoie la valeur décodée par l'URL de x. Les séquences de caractères au format %## sont remplacées par des équivalents non-ASCII, et + par une espace. Les encodages non valides sont renvoyés tels quels.
Décoder l'URL (Unicode) x.urlDecodeUni() Renvoie la valeur décodée par l'URL de x. En plus de urlDecode(), cette fonction gère également les séquences de caractères Unicode au format %u###. Les encodages non valides sont renvoyés tels quels.
Convertir utf8 en Unicode x.utf8ToUnicode() Renvoie la représentation Unicode en minuscules d'une valeur x encodée en UTF-8.
Existe m.exists(k, expr) Renvoie true si au moins une entrée du mappage m satisfait expr, où k représente la clé de chaque entrée du mappage.
Existe au moins un m.exists_one(k, expr) Renvoie true si une seule entrée du mappage m satisfait expr, où k représente la clé de chaque entrée du mappage.
Tous m.all(k, expr) Renvoie true si toutes les entrées du mappage m satisfont à expr, où k représente la clé de chaque entrée de mappage.
Filtre m.filter(k, expr) Renvoie une carte contenant uniquement les entrées de la carte m où l'entrée satisfait expr, où k représente la clé de chaque entrée de la carte.
Carte m.map(k, expr) Renvoie une liste contenant le résultat de l'évaluation de expr pour chaque clé de la carte m, où k représente la clé de chaque entrée de la carte.

Attributs

Les attributs représentent des informations provenant d'une requête entrante, telles que l'adresse IP client ou le chemin d'URL demandé.

Champ Type Description du champ
origin.ip string Adresse IP du client qui a initié la requête.
origin.user_ip string Adresse IP du client d'origine, incluse dans HTTP-HEADER par un proxy en amont. Avant d'utiliser cet attribut, vous devez configurer l'option userIpRequestHeaders[] dans le champ advancedOptionsConfig de la stratégie de sécurité pour qu'elle corresponde à une source telle que True-Client-IP, X-Forwarded-For ou X-Real-IP. Pour en savoir plus, consultez Présentation des adresses IP des utilisateurs.

Si vous ne configurez pas l'option userIpRequestHeaders[], si l'en-tête configuré contient des valeurs d'adresse IP non valides ou si l'en-tête configuré n'est pas présent, origin.user_ip est défini par défaut sur origin.ip. Pour en savoir plus, consultez la documentation de référence sur la ressource securityPolicy.

origin.tls_ja4_fingerprint chaîne Empreinte TLS/SSL JA4 si le client se connecte à l'aide de HTTPS, HTTP/2 ou HTTP/3. Si elle n'est pas disponible, une chaîne vide est renvoyée.
origin.tls_ja3_fingerprint chaîne Empreinte TLS/SSL JA3 si le client se connecte à l'aide de HTTPS, HTTP/2 ou HTTP/3. Si elle n'est pas disponible, une chaîne vide est renvoyée.
request.headers mappage Mappage chaîne à chaîne des en-têtes de requête HTTP. Si un en-tête comporte plusieurs valeurs, la valeur correspondante dans ce mappage est une chaîne unique contenant toutes les valeurs, séparées par des virgules. Les clés de ce mappage sont toutes en minuscules. Les équilibreurs de charge d'application externes inspectent tous les en-têtes acceptés, et les mêmes limites s'appliquent.

Utilisez has() pour vérifier la disponibilité, par exemple has(request.headers['header-key']) && request.headers['header-key'] != 'header-value'.

Vous pouvez effectuer une itération sur la carte pour vérifier les clés et les valeurs. Toutefois, vous ne pouvez utiliser les opérateurs d'itération de carte (exists(), exists_one(), all(), filter() et map()) sur request.headers qu'en combinaison avec request.body ou request.params dans la même expression, par exemple request.body && request.headers.exists(k, k.lower().startsWith('header-prefix')).

request.body string Représente le corps de la requête sous forme de chaîne brute. Il peut représenter des données de n'importe quel Content-Type. Il stocke le contenu sous forme de chaîne sans analyse automatique.
request.params carte Mappage de paires clé/valeur ajoutées à l'URL ou incluses dans le corps des requêtes.
Requête URI : name1=value1&name2=value2
Corps de la requête JSON avec Content-Type: application/json :
{ "username": "johndoe", "email": "johndoe@example.com" }
Corps de la requête POST GraphQL avec Content-Type: application/graphql :
{ Username: "exampleUser", query: "/* other fields */" }
Corps de la requête POST de formulaire avec Content-Type: application/x-www-form-urlencoded :
"username=exampleUser&email=johndoe%40example.com"
request.method string Méthode de requête HTTP.
request.path string Chemin d'URL HTTP demandé. Lorsque vous écrivez des règles qui correspondent à request.path, nous vous recommandons de normaliser le chemin d'accès pour faciliter la syntaxe de correspondance en cas d'encodage d'URL, de variations de casse ou de barres obliques inverses. Pour en savoir plus et voir des exemples, consultez Traversée et normalisation des chemins d'accès.
request.scheme string Schéma d'URL HTTP, tel que http ou https. Les valeurs de cet attribut sont toutes en minuscules.
request.query chaîne Requête d'URL HTTP au format name1=value&name2=value2, telle qu'elle apparaît sur la première ligne de la requête HTTP. Aucun décodage n'est effectué
origin.region_code string Code pays Unicode associé à l'adresse IP du client, tel que US. Si vous créez une règle ou une expression qui utilise des codes de pays ou de région ISO 3166-1 alpha 2, Cloud Armor traite chaque code indépendamment. Les règles et expressions Cloud Armor utilisent explicitement ces codes de région pour autoriser ou refuser les requêtes.
origin.asn entier Numéro ASN (Autonomous System Number) associé à l'adresse IP du client. Le numéro ASN unique est déterminé en fonction de l'opérateur réseau qui accepte les préfixes d'adresse IP contenant l'adresse IP du client.

Exemples d'expressions

Pour chacune de ces expressions, l'action entreprise varie selon que l'expression est incluse dans une règle de refus ou d'autorisation.

Autoriser ou refuser l'accès en fonction d'une plage d'adresses IP en IPv4 ou IPv6

  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 198.51.100.0/24 :

    inIpRange(origin.ip, '198.51.100.0/24')
    
  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 2001:db8::/32 :

    inIpRange(origin.ip, '2001:db8::/32')
    

Autoriser ou refuser l'accès en fonction d'une plage d'adresses IP client personnalisée derrière un proxy en amont

Si vous avez configuré l'opérateur origin.user_ip, vous pouvez effectuer une mise en correspondance en fonction des valeurs d'en-tête que vous avez spécifiées dans votre champ advancedOptionsConfig.userIpRequestHeaders[].

  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 192.0.2.0/24 :

    inIpRange(origin.user_ip, '192.0.2.0/24')
    
  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 2001:db8::/32 :

    inIpRange(origin.user_ip, '2001:db8::/32')
    
  • L'expression suivante correspond aux requêtes qui présentent un cookie contenant 80=BLAH.

    has(request.headers['cookie']) && request.headers['cookie'].contains('80=BLAH')
    

Autoriser ou refuser le trafic avec un en-tête referer non vide

  • L'expression suivante correspond aux requêtes qui ont un en-tête referer non vide.

    has(request.headers['referer']) && request.headers['referer'] != ""
    

Autoriser ou refuser le trafic en fonction de l'en-tête de l'hôte

Vous pouvez autoriser ou refuser le trafic en fonction de la valeur de l'en-tête Host dans la requête.

  • L'expression suivante correspond aux requêtes adressées à une URL spécifique à l'aide de == :

    request.headers['host'].lower() == 'test.example.com'
    
  • L'expression suivante correspond aux requêtes adressées à une URL spécifique à l'aide de endsWith :

    request.headers['host'].lower().endsWith('.example.com')
    
  • L'expression suivante correspond aux requêtes adressées à une URL spécifique à l'aide de contains :

    request.headers['host'].lower().contains('test.example.com')
    
  • L'expression suivante correspond aux requêtes adressées à plusieurs domaines à l'aide de contains :

    request.headers['host'].lower().contains('test.example.com') || request.headers['host'].lower().contains('test22.example.com')
    
  • L'expression suivante met en correspondance les requêtes pour un domaine et ses sous-domaines à l'aide de matches :

    request.headers['host'].matches('(?i:(?:sub\.)?test\.example\.com)')
    

Autoriser ou refuser le trafic provenant d'une région spécifique

Si votre application Web n'est pas encore disponible dans la région AU, toutes les requêtes provenant de cette région doivent être bloquées.

  • Dans une règle de refus, utilisez l'expression suivante, qui correspond aux requêtes de la région AU :

    origin.region_code == 'AU'
    

Si votre application Web est exclusivement disponible dans la région AU, les requêtes provenant de toutes les autres régions doivent être bloquées.

  • Dans une règle de refus, utilisez l'expression suivante pour faire correspondre les requêtes de toutes les régions autres que la région AU :

    origin.region_code != 'AU'
    

Les codes de région sont basés sur les codes ISO 3166-1 alpha-2. Dans certains cas, une région correspond à un pays, mais ce n'est pas toujours le cas. Par exemple, le code US comprend tous les États des États-Unis, un district et six zones périphériques.

Autoriser ou refuser le trafic provenant d'un numéro ASN spécifique

Si votre application Web doit être bloquée pour les clients desservis par un opérateur réseau spécifique, vous pouvez utiliser le numéro ASN de l'opérateur réseau à bloquer.

  • Dans une règle de refus, utilisez l'expression suivante, qui identifie les requêtes provenant d'un numéro ASN spécifique :

    origin.asn == 123
    

Si votre application Web doit être exclusivement disponible pour les clients situés derrière un opérateur réseau spécifique, les requêtes de tous les autres opérateurs réseau doivent être bloquées.

  • Dans une règle de refus, utilisez l'expression suivante, qui identifie tous les autres opérateurs réseau autres que celui que vous souhaitez autoriser :

    origin.asn != 123
    

Expressions multiples

Pour inclure plusieurs conditions dans une seule règle, combinez plusieurs sous-expressions.

  • Dans l'exemple suivant, les requêtes provenant de 1.2.3.0/24 (comme vos testeurs alpha) dans la région AU correspondent à l'expression suivante :

    origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
    
  • L'expression suivante correspond aux requêtes provenant de 1.2.3.4 où un en-tête user-agent contient la chaîne WordPress :

    inIpRange(origin.ip, '1.2.3.4/32') &&
    has(request.headers['user-agent']) && request.headers['user-agent'].contains('WordPress')
    

Autoriser ou refuser le trafic pour un URI de requête qui correspond à une expression régulière

  • L'expression suivante correspond aux requêtes dont l'URI contient la chaîne /example_path/ :

    request.path.matches('/example_path/')
    
  • L'expression suivante correspond aux requêtes dont le champ d'en-tête User-Agent contient Chrome :

    request.headers['user-agent'].matches('Chrome')
    
  • L'expression suivante montre une correspondance non sensible à la casse pour l'en-tête User-Agent contenant wordpress. Elle correspond à User-Agent:WordPress/605.1.15, User-Agent:wordPress et d'autres variantes de wordpress :

    request.headers['user-agent'].matches('(?i:wordpress)')
    

Autoriser ou refuser le trafic contenant une valeur décodée en base64 spécifique

  • L'expression suivante correspond aux requêtes qui ont la valeur décodée en base64 myValue pour l'en-tête user-id :

    has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')
    

Autoriser ou refuser le trafic contenant une valeur de chaîne d'une longueur spécifique

  • L'expression suivante correspond aux requêtes dont l'URL comporte plus de 10 caractères :

    size(request.path) > 10
    
  • L'expression suivante correspond aux requêtes dont la longueur de l'en-tête x-data est supérieure ou égale à 1 024 caractères :

    size(request.headers['x-data']) >= 1024
    

Autoriser ou refuser le trafic dont le corps HTTP contient un en-tête content-length nul

  • L'expression suivante correspond aux requêtes dont le corps HTTP contient un en-tête content-length nul :

    int(request.headers["content-length"]) == 0
    

Autoriser ou refuser le trafic contenant une valeur encodée sous forme d'une URL spécifique

  • L'expression suivante correspond aux requêtes qui présentent un cookie contenant %3c :

    has(request.headers['cookie']) && request.headers['cookie'].urlDecode().contains('<')
    

Autoriser ou refuser le trafic contenant une valeur de chaîne Unicode encodée sous forme d'une URL spécifique

  • L'expression suivante correspond aux requêtes qui présentent une valeur de cookie égale à Match%2BValue ou Match%u002BValue :

    has(request.headers['cookie']) && request.headers['cookie'].urlDecodeUni() == 'Match+Value'
    

Autoriser ou refuser le trafic contenant une chaîne Unicode spécifique d'un texte UTF-8

  • L'expression suivante correspond aux requêtes qui présentent une valeur de cookie égale à ¬ :

    has(request.headers['cookie']) && request.headers['cookie'].utf8ToUnicode() == '%u00ac'
    

Autoriser ou refuser le trafic en fonction d'une empreinte JA4 connue

  • L'expression suivante correspond aux requêtes dont l'empreinte JA4 est égale à t13d1516h2_8daaf6152771_b186095e22b6 :

    origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
    

Autoriser ou refuser le trafic en fonction d'une liste d'empreintes JA4

  • L'expression suivante correspond aux requêtes dont l'empreinte JA4 est égale à l'une des empreintes JA4 suivantes :

    • t00d0000h0_000000000000_000000000000
    • t13d1516h2_8daaf6152771_b186095e22b6
    origin.tls_ja4_fingerprint == 't00d0000h0_000000000000_000000000000' || origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
    

Autoriser ou refuser le trafic en fonction du contenu du corps de la requête

  • L'expression suivante correspond aux requêtes POST qui contiennent malicious-value dans le corps de la requête :

    request.method == 'POST' && request.body.contains('malicious-value')
    
  • L'expression suivante correspond aux requêtes commençant par <!DOCTYPE html> :

    request.body.startsWith('<!DOCTYPE html>')
    
  • L'expression suivante correspond aux requêtes dont le corps correspond à l'expression régulière \w+@\w+.com :

    request.body.matches('\w+@\w+.com')
    

Autoriser ou refuser le trafic en fonction des paramètres de requête

  • L'expression suivante correspond aux requêtes qui ne contiennent pas de paramètre nommé category :

    !has(request.params.category)
    
  • L'expression suivante correspond aux requêtes dont le paramètre category est electronics :

    request.params.category == 'electronics'
    
  • L'expression suivante correspond aux requêtes dont toutes les valeurs de paramètre ne sont pas vides :

    request.params.all(k, request.params[k] != '')
    
  • L'expression suivante correspond aux requêtes dont un paramètre contient la chaîne admin :

    request.params.exists(k, request.params[k].contains('admin'))
    
  • L'expression suivante correspond aux requêtes dont un seul nom de paramètre contient admin :

    request.params.exists_one(k, k.contains('admin'))
    
  • L'expression suivante correspond aux requêtes dont au moins un nom de paramètre contient id :

    size(request.params.filter(k, k.contains('id'))) > 0
    
  • L'expression suivante correspond aux requêtes dont les valeurs de paramètre incluent la chaîne admin :

    request.params.map(k, request.params[k]).contains('admin')
    

Autoriser ou refuser le trafic en fonction des données structurées dans le corps de la requête

  • L'expression suivante correspond aux requêtes dont le champ password dans un corps de requête JSON contient 123 :

    has(request.params.password) && request.params.password.contains('123')
    
  • L'expression suivante correspond aux requêtes dont le champ city des données de formulaire est NewYork :

    has(request.params.city) && request.params.city == 'NewYork'
    
  • L'expression suivante correspond aux requêtes dont le champ newsletter imbriqué est true :

    has(request.params.preferences) && has(request.params.preferences.newsletter) && request.params.preferences.newsletter == true
    
  • L'expression suivante correspond aux requêtes dont le champ name du premier élément du tableau friends est johndoe :

    request.params['friends'][0]['name'] == 'johndoe'
    

Règles WAF préconfigurées

Les règles WAF préconfigurées utilisent des signatures statiques préconfigurées, des expressions régulières ou les deux pour mettre en correspondance le corps de la requête HTTP, les en-têtes de requête HTTP et les paramètres de requête. Les règles WAF préconfigurées disponibles sont basées sur l'ensemble de règles de base OWASP 4.22. Cloud Armor fournit plusieurs règles WAF préconfigurées. Pour obtenir la liste complète des règles WAF préconfigurées, consultez la présentation des règles WAF préconfigurées de Cloud Armor.

Pour répertorier toutes les règles WAF préconfigurées disponibles, consultez Lister les règles WAF préconfigurées disponibles.

Pour plus d'informations sur les règles WAF préconfigurées, consultez le cas d'utilisation Atténuer les attaques de couche d'application à l'aide de règles WAF préconfigurées.

Noms des règles WAF préconfigurées

Les noms des règles WAF préconfigurées sont au format <attack category>-<OWASP CRS version>-<version field>. La catégorie d'attaque spécifie le type d'attaques contre lesquelles vous souhaitez vous protéger, comme xss (script intersites) ou sqli (injection SQL).

Les champs Version pris en charge sont stable et canary. Les ajouts et changements effectués dans les règles sont d'abord publiés dans la version canary. Lorsque des ajouts et des changements sont considérés comme sûrs et stables, ils sont promus vers la version stable.

ID de membres de règles WAF préconfigurées

Une règle WAF préconfigurée contient plusieurs expressions, chacune ayant sa propre signature. Par exemple, la règle WAF préconfigurée xss-v422-stable inclut une expression appelée owasp-crs-v042200-id941100-xss, qui correspond à l'ID de règle id941100 pour la version 4.22. Vous pouvez utiliser les signatures pour empêcher l'utilisation d'expressions spécifiques, ce qui est utile si une expression particulière déclenche systématiquement un faux positif. Pour plus d'informations, consultez les informations de dépannage concernant les faux positifs.

Pour plus d'informations sur l'ensemble de règles de base et l'ajustement à différents niveaux de sensibilité, consultez la page Ajuster les règles WAF Cloud Armor.

Opérateur pour les règles WAF préconfigurées

Expressions Description
evaluatePreconfiguredWaf(string, MAP<string, dyn>) Renvoie true si l'une des signatures WAF figurant dans l'ensemble de règles WAF spécifié renvoie true. Le premier argument est le nom de l'ensemble de règles WAF, tel que xss-v422-stable. Le deuxième argument (facultatif) est un mappage dans lequel la clé est une chaîne et la valeur est typée de manière dynamique en fonction de la clé. L'objectif de cet argument est d'affiner les signatures WAF évaluées. Les clés acceptées sont les suivantes :
  • sensitivity : correspond au niveau de paranoïa de l'ensemble de règles de base OWASP, qui comprend quatre niveaux, compris entre 1 et 4. Sa valeur est un entier avec une plage valide comprise entre 0 et 4. Notez que 0 est réservé en tant que valeur valide lorsqu'il est utilisé en combinaison avec opt_in_rule_ids (décrit plus loin). Lorsque vous spécifiez une sensibilité de x (x >= 1), toutes les signatures WAF associées à une valeur de sensibilité comprise entre 1 et x sont évaluées. En cas d'omission, la valeur 4 est utilisée comme valeur de sensibilité.
  • opt_out_rule_ids : signatures WAF (représentées par des ID de règle) à désactiver de l'évaluation, où l'ensemble de base est déterminé par la valeur de sensibilité. Sa valeur est une liste de chaînes. Le nombre maximal d'ID de règles autorisé est de 128.
  • opt_in_rule_ids : signatures WAF (représentées par des ID de règle) à activer pour l'évaluation, où l'ensemble de base est vide. Sa valeur est une liste de chaînes. Le nombre maximal d'ID de règles autorisé est de 128. Lorsque vous utilisez cette option, une sensitivity de 0 doit être spécifiée.

Les clés opt_out_rule_ids et opt_in_rule_ids s'excluent mutuellement. Vous pouvez choisir d'utiliser opt_in_rule_ids si vous souhaitez examiner et activer manuellement les nouvelles signatures WAF qui seront ajoutées ultérieurement à un ensemble de règles existant.

evaluatePreconfiguredWaf(string, LIST)

Renvoie true si l'une des expressions figurant dans la règle WAF préconfigurée spécifiée renvoie true.

Le premier argument est le nom de la règle WAF préconfigurée, tel que xss-stable. Le deuxième argument (facultatif) est une liste d'ID sous forme de chaînes séparées par des virgules, qui doivent être exclues de l'évaluation. La liste d'exclusion est utile lorsqu'un membre donné de la règle WAF préconfigurée déclenche un faux positif.

Exemples de règles WAF préconfigurées

  • L'expression suivante utilise la règle WAF préconfigurée xss-v422-stable pour atténuer les attaques XSS :

    evaluatePreconfiguredWaf('xss-v422-stable')
    
  • L'expression suivante utilise toutes les expressions de la règle WAF préconfigurée xss-v422-stable, à l'exception des ID de membres 941100 et 941110 :

    evaluatePreconfiguredWaf('xss-v422-stable', {'opt_out_rule_ids': ['owasp-crs-v042200-id941100-xss',
    'owasp-crs-v042200-id941110-xss']})
    
  • L'expression suivante utilise une règle WAF préconfigurée pour atténuer les attaques par injection SQL à partir de la plage d'adresses IP 198.51.100.0/24 :

    inIpRange(origin.ip, '198.51.100.0/24') && evaluatePreconfiguredWaf('sqli-v422-stable')
    
  • L'expression suivante utilise la règle WAF préconfigurée xss-v422-stable pour atténuer les attaques XSS pour les requêtes adressées à example.com, à l'exclusion des chemins d'accès commençant par /login/api/ :

    request.headers['host'].lower() == 'example.com' && !request.path.startswith('/login/api/') && evaluatePreconfiguredWaf('xss-v422-stable')
    

Autres opérateurs

Expressions Description
evaluateThreatIntelligence(string)
evaluateThreatIntelligence(string, LIST)
evaluateThreatIntelligence(string, string, LIST)

Renvoie true si l'adresse IP client correspond à l'une des plages d'adresses IP de la liste d'adresses IP donnée, sauf si elle est explicitement exclue avec la liste d'exclusion.

Le premier argument est le nom du flux Google Threat Intelligence, tel que iplist-known-malicious-ips. Si le deuxième argument est une chaîne (facultatif), il détermine l'emplacement d'extraction de l'adresse IP. Il peut s'agir de origin.ip, de origin.user_ip ou d'un nom d'en-tête spécifique. Si le deuxième ou le troisième argument (facultatif) est une liste de chaînes séparées par des virgules, où chaque chaîne est une adresse IP ou une plage CIDR, celle-ci sera exclue de l'évaluation. La liste d'exclusion est utile lorsqu'un flux contient une adresse IP qui déclenche un faux positif.

evaluateAddressGroup(string, string)
evaluateAddressGroup(string, string, LIST)

evaluateOrganizationAddressGroup(string, string)
evaluateOrganizationAddressGroup(string, string, LIST)

Renvoie true si l'adresse IP client correspond à l'une des plages d'adresses IP du groupe d'adresses donné, sauf si elle est explicitement exclue de la liste d'exclusion.

Le premier argument est le nom du groupe d'adresses. Le deuxième argument détermine l'emplacement à partir duquel l'adresse IP est extraite. Il peut s'agir de origin.ip, de origin.user_ip ou d'un nom d'en-tête spécifique. Le troisième argument (facultatif) est une liste de chaînes séparées par des virgules, où chaque chaîne est une adresse IP ou une plage CIDR, qui sera exclue de l'évaluation. La liste d'exclusion est utile lorsqu'un groupe d'adresses contient des adresses IP qui déclenchent un faux positif.

evaluateAdaptiveProtection(string)

Renvoie true si la requête correspond à la signature d'attaque produite par Google Cloud Armor Adaptive Protection.

L'argument est l'ID d'une alerte spécifique générée par Adaptive Protection lors de la détection d'une attaque.

evaluateAdaptiveProtectionAutoDeploy()

Renvoie true si la requête provient d'une adresse IP "heavy hitter" qui correspond à la signature d'attaque d'une attaque en cours détectée par Adaptive Protection.

Exemples

  • L'expression suivante compare la requête entrante au flux iplist-known-malicious-ips Google Threat Intelligence pour la protéger de la liste connue des adresses IP malveillantes :

    evaluateThreatIntelligence('iplist-known-malicious-ips')
    
  • L'expression suivante met en correspondance la requête entrante avec le flux iplist-known-malicious-ips Google Threat Intelligence pour la protection contre la liste connue des adresses IP malveillantes, à l'exception des adresses IP dans 203.0.113.0/24 :

    evaluateThreatIntelligence('iplist-known-malicious-ips', ['203.0.113.0/24'])
    
  • L'expression suivante fait correspondre l'en-tête de requête personnalisé pour l'adresse IP de l'utilisateur au groupe d'adresses nommé my-own-list-of-bad-ips :

    evaluateAddressGroup('my-own-list-of-bad-ips', origin.user_ip)
    

Étapes suivantes