Collecter les journaux Cloudflare
Ce document explique comment ingérer des journaux Cloudflare dans Google Security Operations à l'aide d'un webhook (destination HTTP) ou de Google Cloud Storage. Cloudflare génère des données opérationnelles sous forme de journaux pour DNS, HTTP, Audit, Zero Trust et CASB. Cette intégration vous permet d'envoyer ces journaux à Google SecOps pour analyse et surveillance. L'analyseur initialise d'abord un ensemble de champs vides, puis analyse les journaux Cloudflare au format JSON, en supprimant tous les messages qui ne sont pas au format JSON valide. Le code utilise ensuite une logique conditionnelle basée sur la présence et les valeurs de champs spécifiques pour déterminer le produit et le type d'événement Cloudflare, en remplissant les champs du modèle de données unifié (UDM) en conséquence.
Avant de commencer
Assurez-vous de remplir les conditions suivantes :
- Instance Google SecOps.
- Un compte Cloudflare Enterprise avec LogPush activé.
- Pour la méthode Webhook : accès privilégié à la console Google Cloud .
- Pour la méthode Google Cloud Storage : accès privilégié à Google Cloud Storage.
Méthode 1 : Configurer l'exportation des journaux Cloudflare à l'aide d'un webhook (destination HTTP)
Cette méthode vous permet de diffuser des journaux Cloudflare directement vers Google SecOps sans stockage intermédiaire.
Configurer un flux Webhook dans Google SecOps
- Accédez à Paramètres SIEM> Flux.
- Cliquez sur Ajouter.
- Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple,
Cloudflare Webhook
). - Sélectionnez Webhook comme type de source.
- Sélectionnez Cloudflare comme type de journal.
- Cliquez sur Suivant.
- Spécifiez les valeurs des paramètres d'entrée suivants :
- Délimiteur de fractionnement :
\n
. - Espace de noms de l'élément : espace de noms de l'élément.
- Libellés d'ingestion : libellé à appliquer aux événements de ce flux.
- Délimiteur de fractionnement :
- Cliquez sur Suivant.
- Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.
- Cliquez sur Générer une clé secrète pour générer une clé secrète permettant d'authentifier ce flux.
- Copiez et enregistrez la clé secrète, car vous ne pourrez plus l'afficher.
- Accédez à l'onglet Détails.
- Copiez l'URL du point de terminaison du flux à partir du champ Informations sur le point de terminaison.
- Cliquez sur OK.
Créer une clé API pour le flux Webhook
- Accédez à Google Cloud console > API et services > Identifiants.
- Cliquez sur Créer des identifiants, puis sélectionnez Clé API.
- Cliquez sur Modifier la clé API.
- Sous Restrictions relatives aux API, sélectionnez Restreindre la clé.
- Sélectionnez API Google SecOps dans la liste.
- Cliquez sur Enregistrer.
- Copiez la valeur de la clé API.
Configurer la destination HTTP Cloudflare LogPush
- Connectez-vous au tableau de bord Cloudflare.
- Sélectionnez le compte Enterprise ou le domaine que vous souhaitez utiliser avec LogPush.
- Accédez à Analytics & Logs > Logpush.
- Cliquez sur Create a Logpush job (Créer un job Logpush).
- Dans Sélectionner une destination, choisissez Destination HTTP.
Saisissez l'URL du point de terminaison HTTP avec les paramètres d'authentification :
<ENDPOINT_URL>?header_X-goog-api-key=<API_KEY>&header_X-Webhook-Access-Key=<SECRET_KEY>
Remplacez les éléments suivants :
<ENDPOINT_URL>
: URL du point de terminaison du flux de Google SecOps.<API_KEY>
: clé API de la console Google Cloud (encodée au format URL si elle contient des caractères spéciaux).<SECRET_KEY>
: clé secrète du flux Webhook (encodée au format URL si elle contient des caractères spéciaux).
Cliquez sur Continuer.
Sélectionnez l'ensemble de données à transférer (par exemple, Requêtes HTTP, DNS, Audit, Zero Trust ou CASB).
Configurez votre tâche logpush :
- Saisissez le nom de la tâche.
- (Facultatif) Sous Si les journaux correspondent, configurez les filtres.
- Dans Envoyer les champs suivants, sélectionnez les champs à inclure.
- Choisissez le format de l'horodatage (RFC3 339 recommandé).
- Configurez le taux d'échantillonnage si nécessaire.
Cliquez sur Envoyer pour créer la tâche logpush.
Valider l'intégration du webhook
Une fois la configuration effectuée, les journaux devraient apparaître dans Google SecOps en quelques minutes. Pour effectuer la validation, procédez comme suit :
- Accédez à Investigation > Recherche SIEM.
- Recherchez les journaux portant le libellé d'ingestion que vous avez configuré.
- Vérifiez que les journaux Cloudflare sont analysés correctement.
Méthode 2 : Configurer l'exportation des journaux Cloudflare à l'aide de Google Cloud Storage
Configurez Cloudflare pour qu'il envoie les journaux à Google Cloud, ce qui implique d'accorder à Cloudflare les autorisations nécessaires.
Créer un bucket Google Cloud
- Connectez-vous à la consoleGoogle Cloud .
- Accédez à la page Buckets Cloud Storage.
- Cliquez sur Créer.
- Sur la page Créer un bucket, saisissez les informations concernant votre bucket :
- Nom : saisissez un nom unique qui répond aux exigences de dénomination des buckets (par exemple,
cloudflare-data
). - Type d'emplacement : sélectionnez un type d'emplacement et une région.
- Pour activer l'espace de noms hiérarchique, cliquez sur la flèche d'expansion pour développer Optimiser pour les charges de travail orientées fichiers et à forte intensité de données, puis sélectionnez Activer l'espace de noms hiérarchique sur ce bucket.
- Nom : saisissez un nom unique qui répond aux exigences de dénomination des buckets (par exemple,
- Cliquez sur Créer.
Accorder des autorisations au bucket
- Dans la console Cloud Storage, sélectionnez le bucket que vous avez créé précédemment.
- Cliquez sur l'onglet Autorisations.
- Cliquez sur Accorder l'accès.
- Ajoutez le compte
logpush@cloudflare-data.iam.gserviceaccount.com
avec l'autorisation Administrateur des objets Storage. - Cliquez sur Enregistrer.
Configurer Cloudflare LogPush pour Google Cloud Storage
- Connectez-vous au tableau de bord Cloudflare.
- Sélectionnez le compte Enterprise ou le domaine que vous souhaitez utiliser avec LogPush.
- Accédez à Analytics & Logs > Logpush.
- Cliquez sur Create a Logpush job (Créer un job Logpush).
- Dans Sélectionner une destination, choisissez Google Cloud Storage.
- Saisissez le chemin d'accès à votre bucket Google Cloud Storage (par exemple,
gs://cloudflare-data/logs/
). Cliquez sur Continuer.
Saisissez le jeton de propriété, puis cliquez sur Continuer.
Sélectionnez l'ensemble de données à transférer vers l'espace de stockage.
Configurez votre tâche logpush :
- Saisissez le nom de la tâche.
- Sous Si les journaux correspondent, vous pouvez sélectionner les événements à inclure ou à supprimer de vos journaux.
- Dans Envoyer les champs suivants, choisissez les journaux à transférer.
- Choisissez le format de l'horodatage (RFC 339 recommandé).
- Configurez le taux d'échantillonnage si nécessaire.
Cliquez sur Envoyer.
Configurer un flux dans Google SecOps pour ingérer les journaux Cloudflare depuis Google Cloud Storage
- Accédez à Paramètres SIEM > Flux.
- Cliquez sur Ajouter.
- Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple,
Cloudflare GCS Logs
). - Sélectionnez Google Cloud Storage V2 comme Type de source.
- Sélectionnez Cloudflare comme type de journal.
- Cliquez sur Obtenir un compte de service.
- Cliquez sur Suivant.
Spécifiez les valeurs des paramètres d'entrée suivants :
- URI du bucket Storage : URL du bucket au format
gs://my-bucket/<value>/
. Google Cloud Cette URL doit se terminer par une barre oblique (/). - Options de suppression de la source : sélectionnez l'option de suppression de votre choix.
- Âge maximal du fichier : inclut les fichiers modifiés au cours des derniers jours. La valeur par défaut est de 180 jours.
- Espace de noms de l'élément : espace de noms de l'élément.
- Libellés d'ingestion : libellé à appliquer aux événements de ce flux.
- URI du bucket Storage : URL du bucket au format
Cliquez sur Suivant.
Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.
Table de mappage UDM
Champ du journal | Mappage UDM | Logique |
---|---|---|
ClientIP | read_only_udm.principal.asset.ip read_only_udm.principal.ip |
La valeur est extraite du champ "ClientIP". |
ClientRequestHost | read_only_udm.target.asset.hostname read_only_udm.target.hostname |
La valeur est extraite du champ "ClientRequestHost". |
ClientRequestMethod | read_only_udm.network.http.method | La valeur est extraite du champ ClientRequestMethod. |
ClientRequestURI | read_only_udm.target.url | La valeur est extraite du champ ClientRequestURI. Si le champ "ClientRequestHost" n'est pas vide, la valeur est concaténée avec le champ "ClientRequestHost". |
ClientSrcPort | read_only_udm.principal.port | La valeur est extraite du champ ClientSrcPort. |
ClientRequestUserAgent | read_only_udm.network.http.user_agent | La valeur est extraite du champ "ClientRequestUserAgent". |
ClientSSLCipher | read_only_udm.network.tls.cipher | La valeur est extraite du champ "ClientSSLCipher". |
ClientSSLProtocol | read_only_udm.network.tls.version | La valeur est extraite du champ ClientSSLProtocol. |
Pays | read_only_udm.target.location.country_or_region | La valeur est extraite du champ "Pays". |
CreatedAt | read_only_udm.metadata.event_timestamp | La valeur est extraite du champ "CreatedAt" (Créé le). |
Date/Heure | read_only_udm.metadata.event_timestamp | La valeur est extraite du champ "Date/Heure". |
DestinationIP | read_only_udm.target.asset.ip read_only_udm.target.ip |
La valeur est extraite du champ "DestinationIP". |
DestinationPort | read_only_udm.target.port | La valeur est extraite du champ "DestinationPort". |
DeviceID | read_only_udm.principal.asset_id | La valeur est extraite du champ "DeviceID" et est précédée de "Cloudflare:". |
DeviceName | read_only_udm.principal.asset.hostname read_only_udm.principal.hostname |
La valeur est extraite du champ "DeviceName". |
DstIP | read_only_udm.target.asset.ip read_only_udm.target.ip |
La valeur est extraite du champ "DstIP". |
DstPort | read_only_udm.target.port | La valeur est extraite du champ "DstPort". |
EdgeResponseBytes | read_only_udm.network.received_bytes | La valeur est extraite du champ "EdgeResponseBytes". |
EdgeResponseStatus | read_only_udm.network.http.response_code | La valeur est extraite du champ EdgeResponseStatus. |
EdgeServerIP | read_only_udm.target.asset.ip read_only_udm.target.ip |
La valeur est extraite du champ "EdgeServerIP". |
read_only_udm.principal.user.email_addresses read_only_udm.target.user.email_addresses |
La valeur est extraite du champ "Adresse e-mail". | |
FirewallMatchesActions | read_only_udm.security_result.action | La valeur est définie sur "ALLOW" si le champ FirewallMatchesAction est "allow", "Allow", "ALLOW", "skip", "SKIP" ou "Skip", sur "ALLOW_WITH_MODIFICATION" si le champ FirewallMatchesAction est "challengeSolved" ou "jschallengeSolved", sur "BLOCK" si le champ FirewallMatchesAction est "drop" ou "block", et sur "UNKNOWN_ACTION" si le champ FirewallMatchesAction n'est pas vide. |
FirewallMatchesRuleIDs | read_only_udm.security_result.rule_id | La valeur est extraite du champ "FirewallMatchesRuleIDs". |
FirewallMatchesSources | read_only_udm.security_result.rule_name | La valeur est extraite du champ "FirewallMatchesSources". |
HTTPMethod | read_only_udm.network.http.method | La valeur est extraite du champ HTTPMethod. |
HTTPHost | read_only_udm.target.hostname | La valeur est extraite du champ HTTPHost. |
HTTPVersion | read_only_udm.network.application_protocol | La valeur est extraite du champ "HTTPVersion". Si la valeur contient "HTTP", elle est remplacée par "HTTP". |
IPAddress | read_only_udm.target.asset.ip read_only_udm.target.ip |
La valeur est extraite du champ "IPAddress". |
IsIsolated | read_only_udm.about.labels read_only_udm.security_result.about.resource.attribute.labels |
La valeur est extraite du champ "IsIsolated" et convertie en chaîne. |
Emplacement | read_only_udm.principal.location.name | La valeur est extraite du champ "Emplacement". |
OriginIP | read_only_udm.intermediary.ip read_only_udm.target.asset.ip read_only_udm.target.ip |
La valeur est extraite du champ "OriginIP". |
OriginPort | read_only_udm.target.port | La valeur est extraite du champ "OriginPort". |
OwnerID | read_only_udm.target.user.product_object_id | La valeur est extraite du champ "OwnerID". |
Règle | read_only_udm.security_result.rule_name | La valeur est extraite du champ "Règle". |
PolicyID | read_only_udm.security_result.rule_id | La valeur est extraite du champ "PolicyID". |
PolicyName | read_only_udm.security_result.rule_name | La valeur est extraite du champ "PolicyName". |
Protocole | read_only_udm.network.ip_protocol | La valeur est extraite du champ "Protocole" et convertie en majuscules. |
QueryCategoryIDs | read_only_udm.security_result.about.labels read_only_udm.security_result.about.resource.attribute.labels |
La valeur est extraite du champ "QueryCategoryIDs". |
QueryName | read_only_udm.network.dns.questions.name | La valeur est extraite du champ QueryName. |
QueryNameReversed | read_only_udm.network.dns.questions.name | La valeur est extraite du champ "QueryNameReversed". |
QuerySize | read_only_udm.network.sent_bytes | La valeur est extraite du champ "QuerySize". |
QueryType | read_only_udm.network.dns.questions.type | La valeur est extraite du champ "QueryType". Si la valeur correspond à l'un des types d'enregistrement DNS connus, elle est mappée à sa valeur numérique correspondante. Sinon, la valeur est convertie en chaîne. |
RData | read_only_udm.network.dns.answers | La valeur est extraite du champ "RData". Le champ "type" est converti en entier non signé. |
RayID | read_only_udm.metadata.product_log_id | La valeur est extraite du champ "RayID". |
Référent | read_only_udm.network.http.referral_url | La valeur est extraite du champ "Referer". |
RequestID | read_only_udm.metadata.product_log_id | La valeur est extraite du champ RequestID. |
ResolverDecision | read_only_udm.security_result.summary | La valeur est extraite du champ "ResolverDecision". |
ResourceID | read_only_udm.target.resource.id read_only_udm.target.resource.product_object_id |
La valeur est extraite du champ "ResourceID". |
ResourceType | read_only_udm.target.resource.resource_subtype | La valeur est extraite du champ ResourceType. |
SNI | read_only_udm.network.tls.client.server_name | La valeur est extraite du champ "SNI". |
SecurityAction | read_only_udm.security_result.action | La valeur est définie sur "ALLOW" si le champ SecurityAction ou sec_action est vide, sur "ALLOW_WITH_MODIFICATION" si le champ SecurityAction est "challengeSolved" ou "jschallengeSolved", et sur "BLOCK" si le champ SecurityAction est "drop" ou "block". |
SecurityLevel | read_only_udm.security_result.severity | La valeur est extraite du champ "SecurityLevel" et est mappée à la valeur de gravité UDM correspondante. |
SessionID | read_only_udm.network.session_id | La valeur est extraite du champ "SessionID". |
SessionStartTime | read_only_udm.metadata.event_timestamp | La valeur est extraite du champ "SessionStartTime". |
SourceIP | read_only_udm.principal.asset.ip read_only_udm.principal.ip read_only_udm.src.asset.ip read_only_udm.src.ip |
La valeur est extraite du champ SourceIP. |
SourcePort | read_only_udm.principal.port read_only_udm.src.port |
La valeur est extraite du champ SourcePort. |
SrcIP | read_only_udm.principal.asset.ip read_only_udm.principal.ip |
La valeur est extraite du champ "SrcIP". |
SrcPort | read_only_udm.principal.port | La valeur est extraite du champ "SrcPort". |
TemporaryAccessDuration | read_only_udm.network.session_duration.seconds | La valeur est extraite du champ "TemporaryAccessDuration". |
Horodatage | read_only_udm.metadata.event_timestamp | La valeur est extraite du champ "Code temporel". |
Transport | read_only_udm.network.ip_protocol | La valeur est extraite du champ "Transport" et convertie en majuscules. |
URL | read_only_udm.target.url | La valeur est extraite du champ "URL". |
UserAgent | read_only_udm.network.http.user_agent | La valeur est extraite du champ "UserAgent". |
UserID | read_only_udm.principal.user.product_object_id | La valeur est extraite du champ "UserID". |
UserUID | read_only_udm.target.user.product_object_id | La valeur est extraite du champ UserUID. |
VirtualNetworkID | read_only_udm.principal.resource.product_object_id | La valeur est extraite du champ "VirtualNetworkID". |
WAFAction | read_only_udm.security_result.about.labels read_only_udm.security_result.about.resource.attribute.labels |
La valeur est extraite du champ "WAFAction". |
WAFAttackScore | read_only_udm.security_result.about.resource.attribute.labels | La valeur est extraite du champ "WAFAttackScore". |
WAFFlags | read_only_udm.security_result.about.resource.attribute.labels | La valeur est extraite du champ "WAFFlags". |
WAFProfile | read_only_udm.security_result.about.labels read_only_udm.security_result.about.resource.attribute.labels |
La valeur est extraite du champ WAFProfile. |
WAFRCEAttackScore | read_only_udm.security_result.about.resource.attribute.labels | La valeur est extraite du champ "WAFRCEAttackScore". |
WAFRuleID | read_only_udm.security_result.about.labels read_only_udm.security_result.about.resource.attribute.labels read_only_udm.security_result.threat_id |
La valeur est extraite du champ WAFRuleID. |
WAFRuleMessage | read_only_udm.security_result.rule_name read_only_udm.security_result.threat_name |
La valeur est extraite du champ WAFRuleMessage. |
WAFSQLiAttackScore | read_only_udm.security_result.about.resource.attribute.labels | La valeur est extraite du champ "WAFSQLiAttackScore". |
WAFXSSAttackScore | read_only_udm.security_result.about.resource.attribute.labels | La valeur est extraite du champ "WAFXSSAttackScore". |
ZoneID | read_only_udm.additional.fields | La valeur est extraite du champ "ZoneID". |
read_only_udm.metadata.log_type | La valeur est définie sur "CLOUDFLARE". | |
read_only_udm.metadata.product_name | La valeur est définie sur "DNS Cloudflare Gateway" si le journal est un journal DNS, sur "HTTP Cloudflare Gateway" si le journal est un journal HTTP Gateway, sur "Audit Cloudflare" si le journal est un journal d'audit, ou sur "Pare-feu d'application Web" dans le cas contraire. | |
read_only_udm.metadata.vendor_name | La valeur est définie sur "Cloudflare". | |
read_only_udm.network.application_protocol | La valeur est définie sur "DNS" si le journal est un journal DNS, sur "HTTP" si le champ HTTPVersion contient "HTTP", ou sur la valeur du champ Protocol convertie en majuscules si le champ Protocol n'est pas vide et n'est pas "tls" ni "TLS". | |
read_only_udm.network.direction | La valeur est définie sur "OUTBOUND" si le champ "EgressIP" n'est pas vide. | |
read_only_udm.network.http.parsed_user_agent | La valeur est extraite du champ UserAgent ou ClientRequestUserAgent et analysée à l'aide du filtre parseduseragent. | |
read_only_udm.extensions.auth.type | La valeur est définie sur "MACHINE" si le champ "Action" est défini sur "login" ou "logout". | |
read_only_udm.metadata.event_type | La valeur est définie sur "NETWORK_DNS" si le journal est un journal DNS, sur "NETWORK_CONNECTION" si le journal est un journal HTTP de passerelle, sur "USER_RESOURCE_ACCESS" si le journal est un journal d'audit et que les champs "ActorIP" et "ActorEmail" sont vides, sur "USER_RESOURCE_UPDATE_CONTENT" si le journal est un journal d'audit et que les champs "ResourceType" et "newvalue" ne sont pas vides, sur "USER_LOGIN" si le champ "Action" est défini sur "login", sur "USER_LOGOUT" si le champ "Action" est défini sur "logout", sur "USER_RESOURCE_ACCESS" si le champ "Email" n'est pas vide et correspond au format d'adresse e-mail, ou sur "NETWORK_CONNECTION" si les champs "EgressIP" et "SourceIP" ne sont pas vides ou si les champs "OriginIP" et "SourceIP" ne sont pas vides. | |
read_only_udm.target.file.mime_type | La valeur est extraite du champ "EdgeResponseContentType". | |
read_only_udm.target.location.country_or_region | La valeur est extraite du champ "Pays". | |
read_only_udm.target.resource.id | La valeur est extraite du champ "AccountID" ou "ResourceID". | |
read_only_udm.target.resource.product_object_id | La valeur est extraite des champs AccountID, AppUUID ou ResourceID. | |
read_only_udm.target.user.product_object_id | La valeur est extraite du champ OwnerID ou UserUID. |
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.