Collecter les journaux Akamai Enterprise Application Access
Version de l'analyseur : 3.0
Ce document explique comment ingérer des journaux Akamai Enterprise Application Access (EAA) dans Google Security Operations à l'aide d'Akamai Unified Log Streamer (ULS) et de Bindplane. Akamai EAA est une solution d'accès réseau zéro confiance qui permet d'accéder de manière sécurisée aux applications d'entreprise en fonction de l'identité, sans VPN traditionnel. EAA produit des données opérationnelles sous la forme de journaux d'accès, de journaux d'audit d'administration, de métriques d'état des connecteurs, d'inventaires d'appareils et d'informations sur l'état des annuaires. L'analyseur extrait les champs des journaux JSON, effectue des transformations de données telles que des conversions de chaînes et l'extraction d'adresses IP, et mappe ces champs à l'UDM, en gérant différents types d'événements, y compris NETWORK_HTTP et USER_UNCATEGORIZED, en fonction de la présence de champs spécifiques.
Avant de commencer
Assurez-vous de remplir les conditions suivantes :
- Une instance Google SecOps.
- Un hôte Windows Server 2016 ou version ultérieure, ou Linux avec
systemdpour exécuter l'agent Bindplane. - Un hôte Linux avec Python 3.9 ou version ultérieure, ou un environnement conteneurisé (Docker ou Kubernetes) pour exécuter Unified Log Streamer.
- Si vous exécutez l'agent derrière un proxy, assurez-vous que les ports du pare-feu sont ouverts conformément aux exigences de l'agent BindPlane.
- Locataire Akamai EAA avec accès administrateur.
Identifiants de l'API Akamai :
- Pour les flux d'audit des accès et des administrateurs : clé et code secret de l'ancienne API EAA (créés dans Enterprise Center).
- Pour les flux d'état du connecteur, d'inventaire des appareils et d'état de l'annuaire : identifiants Akamai OPEN API (authentification EdgeGrid) avec accès en LECTURE/ÉCRITURE à l'API Enterprise Application Access.
Obtenir des identifiants Google SecOps pour l'agent BindPlane
Pour authentifier l'agent Bindplane auprès de Google SecOps, choisissez l'une des méthodes suivantes :
- Nouveaux déploiements : utilisez l'API Chronicle (option 1).
- Anciens déploiements : continuez à utiliser le fichier d'authentification d'ingestion (option 2) jusqu'à l'arrêt de l'API Ingestion le 20 juillet 2027.
Option 1 : Créer un compte de service pour l'API Chronicle (recommandé)
- Connectez-vous à la consoleGoogle Cloud et sélectionnez le projet Google Cloud associé à votre instance Google SecOps.
- Accédez à IAM et administration > Comptes de service.
- Cliquez sur Créer un compte de service.
- Fournissez les informations de configuration suivantes :
- Nom du compte de service : saisissez un nom pour le compte (par exemple,
bindplane-ingest). - Description du compte de service : saisissez une description (par exemple,
Bindplane agent log ingestion).
- Nom du compte de service : saisissez un nom pour le compte (par exemple,
- Cliquez sur Créer et continuer.
- Dans la section Autoriser ce compte de service à accéder au projet, cliquez sur Sélectionner un rôle, puis sélectionnez Éditeur Chronicle.
- Cliquez sur Continue (Continuer), puis sur Done (OK).
- Cliquez sur le compte de service que vous avez créé, puis accédez à l'onglet Clés.
- Cliquez sur Ajouter une clé > Créer une clé.
- Sélectionnez JSON, puis cliquez sur Créer. Le fichier de clé est téléchargé sur votre ordinateur.
- Enregistrez le fichier de clé sous le nom
ingestion-auth.jsondans le répertoire du collecteur BindPlane (/opt/observiq-otel-collector/ingestion-auth.jsonsous Linux ouC:\Program Files\observIQ OpenTelemetry Collector\ingestion-auth.jsonsous Windows), ou mettez à jourcreds_file_pathdansconfig.yamlpour qu'il corresponde au chemin d'accès où vous l'enregistrez. - Accédez à IAM et administration > Paramètres, puis copiez le numéro du projet. Vous en aurez besoin pour la configuration de l'exportateur.
Option 2 : Télécharger le fichier d'authentification d'ingestion (ancien)
- Connectez-vous à la console Google SecOps.
- Accédez à Paramètres SIEM> Agents de collecte.
- Téléchargez le fichier d'authentification d'ingestion.
- Enregistrez le fichier de manière sécurisée sur le système où l'agent BindPlane sera installé.
Obtenir l'ID client Google SecOps
- Connectez-vous à la console Google SecOps.
- Accédez à Paramètres du SIEM > Profil.
- Copiez et enregistrez le numéro client dans la section Informations sur l'organisation.
Installer l'agent Bindplane
Installez l'agent BindPlane sur votre système d'exploitation Windows ou Linux en suivant les instructions ci-dessous.
Installation de Windows
- Ouvrez l'invite de commandes ou PowerShell en tant qu'administrateur.
Exécutez la commande suivante :
msiexec /i "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" /quiet
Installation sous Linux
- Ouvrez un terminal avec des privilèges root ou sudo.
Exécutez la commande suivante :
sudo sh -c "$(curl -fsSlL https://github.com/observiq/bindplane-agent/releases/latest/download/install_unix.sh)" install_unix.sh
Autres ressources d'installation
Pour connaître les autres options d'installation, consultez le guide d'installation de l'agent BindPlane.
Configurer l'agent Bindplane pour ingérer les journaux et les envoyer à Google SecOps
Ouvrez le fichier de configuration de l'agent Bindplane dans un éditeur de texte :
Linux :
sudo nano /opt/observiq-otel-collector/config.yamlWindows :
notepad "C:\Program Files\observIQ OpenTelemetry Collector\config.yaml"Modifiez le fichier
config.yamlcomme suit :receivers: tcplog: listen_address: "0.0.0.0:5140" exporters: chronicle/akamai_eaa: protocol: https # Region of your instance, for example us, europe, asia-southeast1 location: <LOCATION> # Project number of the Google Cloud project linked to the instance project: '<PROJECT_NUMBER>' compression: gzip creds_file_path: '/path/to/ingestion-authentication-file.json' customer_id: '<CUSTOMER_ID>' endpoint: chronicle.googleapis.com log_type: 'AKAMAI_EAA' raw_log_field: body ingestion_labels: source: akamai_eaa service: pipelines: logs/akamai_eaa: receivers: - tcplog exporters: - chronicle/akamai_eaa
Remplacez les éléments suivants :
/path/to/ingestion-authentication-file.json: chemin d'accès complet au fichier de clé JSON du compte de service (option 1).- Linux :
/opt/observiq-otel-collector/ingestion-auth.json - Windows :
C:\Program Files\observIQ OpenTelemetry Collector\ingestion-auth.json
- Linux :
- Remplacez
<LOCATION>par la région de votre instance Google SecOps (par exemple,us,europeouasia-southeast1). L'exportateur ajoute cette valeur en préfixe àchronicle.googleapis.com. - Remplacez
<PROJECT_NUMBER>par le numéro de projet indiqué dans IAM et administration > Paramètres. <CUSTOMER_ID>: ID client Google SecOps.0.0.0.0:5140: adresse IP et port sur lesquels Bindplane doit écouter. Adaptez-le à votre environnement, le cas échéant.
Ancien exportateur d'API d'ingestion
Si vous utilisez le fichier d'authentification d'ingestion de l'option 2, remplacez le bloc
exporterspar ce qui suit. Définissezcreds_file_pathsur le chemin d'accès au fichier d'authentification d'ingestion. Si votre instance se trouve en dehors des États-Unis, remplacezmalachiteingestion-pa.googleapis.compar votre point de terminaison régional (par exemple,europe-malachiteingestion-pa.googleapis.com).exporters: chronicle/akamai_eaa: compression: gzip creds_file_path: '/path/to/ingestion-authentication-file.json' customer_id: '<CUSTOMER_ID>' endpoint: malachiteingestion-pa.googleapis.com log_type: 'AKAMAI_EAA' raw_log_field: body ingestion_labels: source: akamai_eaa
Redémarrez l'agent Bindplane pour appliquer les modifications.
Pour redémarrer l'agent Bindplane sous Linux :
Exécutez la commande suivante :
sudo systemctl restart observiq-otel-collectorVérifiez que le service est en cours d'exécution :
sudo systemctl status observiq-otel-collectorRecherchez les erreurs dans les journaux :
sudo journalctl -u observiq-otel-collector -f
Pour redémarrer l'agent BindPlane sous Windows :
Choisissez l'une des options suivantes :
- Invite de commande ou PowerShell en tant qu'administrateur :
net stop observiq-otel-collector && net start observiq-otel-collector- Console Services :
- Appuyez sur
Win+R, saisissezservices.msc, puis appuyez sur Entrée. - Recherchez observIQ OpenTelemetry Collector.
- Effectuez un clic droit et sélectionnez Redémarrer.
- Appuyez sur
Vérifiez que le service est en cours d'exécution :
sc query observiq-otel-collectorRecherchez les erreurs dans les journaux :
type "C:\Program Files\observIQ OpenTelemetry Collector\log\collector.log"
Créer des identifiants d'API Akamai
Akamai EAA utilise deux types d'identifiants d'API en fonction du type de flux. Créez les identifiants correspondant aux flux que vous souhaitez collecter.
Créer des identifiants pour l'ancienne API EAA (pour les flux d'accès et d'administration)
- Connectez-vous à Akamai Control Center.
- Sélectionnez Enterprise Center dans le menu de navigation principal à gauche.
- Accédez à Paramètres généraux > Paramètres.
- Sélectionnez l'onglet Clés API.
- Cliquez sur Générer une clé API en haut à droite.
- Saisissez un nom et une description pour la clé API.
Sur l'écran de confirmation, copiez la clé et le code secret.
Créer des identifiants Akamai OPEN API (pour les flux d'état du connecteur, d'inventaire des appareils et d'état du répertoire)
- Connectez-vous à Akamai Control Center.
- Accédez à Administrateur de compte > Identité et accès.
- Sélectionnez l'onglet Utilisateurs de l'API.
- Cliquez sur Créer un client API.
- Dans la section Sélectionner des API, recherchez Enterprise Application Access et définissez le niveau d'accès sur LECTURE-ÉCRITURE.
- Renseignez les autres paramètres, puis cliquez sur Créer un client API.
Cliquez sur Télécharger pour télécharger les identifiants au format
.edgerc, ou sur Copier pour les copier dans un fichier.edgercexistant.
Configurer le fichier d'identifiants .edgerc
Créez le fichier d'identifiants
.edgercsur le système sur lequel ULS sera exécuté :touch ~/.edgercOuvrez le fichier dans un éditeur de texte :
nano ~/.edgercAjoutez vos identifiants Akamai API au format suivant :
[default] ; EAA Legacy API credentials (for access and admin feeds) eaa_api_host = manage.akamai-access.com eaa_api_key = <EAA_API_KEY> eaa_api_secret = <EAA_API_SECRET> ; Akamai OPEN API credentials (for conhealth, devinv, dirhealth feeds) host = <OPEN_API_HOST> client_token = <CLIENT_TOKEN> client_secret = <CLIENT_SECRET> access_token = <ACCESS_TOKEN>Sécurisez le fichier d'identifiants :
chmod 600 ~/.edgerc
Remplacez les éléments suivants :
<EAA_API_KEY>: clé API EAA Legacy (par exemple,XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX).<EAA_API_SECRET>: code secret de l'API EAA Legacy.<OPEN_API_HOST>: nom d'hôte de votre API Akamai OPEN (par exemple,akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net).<CLIENT_TOKEN>: votre jeton client Akamai OPEN API (par exemple,akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx).<CLIENT_SECRET>: code secret du client de votre API Akamai OPEN.<ACCESS_TOKEN>: votre jeton d'accès à l'API Akamai OPEN (par exemple,akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx).
Installer Akamai Unified Log Streamer
Unified Log Streamer (ULS) extrait les journaux d'Akamai EAA via les API Akamai et les transmet à l'agent Bindplane à l'aide de TCP. ULS est une application Python qui nécessite Python 3.9 ou version ultérieure.
Installation sous Linux (Python)
Clonez le dépôt ULS :
git clone https://github.com/akamai/uls.git cd ulsInstallez les exigences Python ULS :
pip3 install -r bin/requirements.txtInstallez la dépendance EAA CLI :
git clone --depth 1 --single-branch https://github.com/akamai/cli-eaa.git ext/cli-eaa pip3 install -r ext/cli-eaa/requirements.txtVérifiez l'installation :
python3 bin/uls.py --help
Installation de Docker
Extrayez l'image Docker ULS officielle :
docker pull akamai/uls:latest
Configurer ULS pour diffuser les journaux EAA vers BindPlane
Exécution en ligne de commande (tests)
Exécutez ULS avec une sortie TCP pour diffuser les journaux vers l'agent Bindplane :
python3 bin/uls.py --input eaa \ --feed access \ --output tcp \ --host <BINDPLANE_HOST> \ --port 5140 \ --edgerc ~/.edgerc \ --section default
Remplacez les éléments suivants :
<BINDPLANE_HOST>: adresse IP ou nom d'hôte du serveur exécutant l'agent Bindplane.5140: port configuré dans le récepteurtcplogBindplane.Pour diffuser plusieurs types de flux, exécutez des instances ULS distinctes :
# Access logs python3 bin/uls.py --input eaa --feed access --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default # Admin audit logs python3 bin/uls.py --input eaa --feed admin --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default # Connector health python3 bin/uls.py --input eaa --feed conhealth --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default
Service systemd (production)
Pour les déploiements en production, configurez ULS en tant que service systemd.
Créez un fichier de configuration ULS :
sudo mkdir -p /etc/uls sudo nano /etc/uls/eaa-access-tcp.confAjoutez la configuration suivante :
ULS_INPUT=eaa ULS_FEED=access ULS_OUTPUT=tcp ULS_HOST=<BINDPLANE_HOST> ULS_PORT=5140 ULS_EDGERC=/root/.edgerc ULS_SECTION=defaultCréez un fichier de service systemd :
sudo nano /etc/systemd/system/uls-eaa-access.serviceAjoutez le contenu suivant :
[Unit] Description=Unified Log Streamer - EAA Access Logs to Bindplane After=network.target [Service] Type=simple EnvironmentFile=/etc/uls/eaa-access-tcp.conf ExecStart=/usr/bin/python3 /opt/uls/bin/uls.py --input ${ULS_INPUT} --feed ${ULS_FEED} --output ${ULS_OUTPUT} --host ${ULS_HOST} --port ${ULS_PORT} --edgerc ${ULS_EDGERC} --section ${ULS_SECTION} Restart=always RestartSec=10 User=root [Install] WantedBy=multi-user.targetActivez et démarrez le service :
sudo systemctl daemon-reload sudo systemctl enable uls-eaa-access.service sudo systemctl start uls-eaa-access.serviceVérifiez que le service est en cours d'exécution :
sudo systemctl status uls-eaa-access.serviceAffichez les journaux :
sudo journalctl -u uls-eaa-access.service -f
Répétez les étapes 1 à 7 pour chaque type de flux supplémentaire (admin, conhealth) en créant des fichiers de configuration et de service distincts avec des noms différents (par exemple, uls-eaa-admin.service, uls-eaa-conhealth.service).
Déploiement Docker Compose
Créez un fichier
docker-compose.yml:version: '3.8' services: uls-eaa-access: image: akamai/uls:latest container_name: uls-eaa-access restart: unless-stopped environment: - ULS_INPUT=eaa - ULS_FEED=access - ULS_OUTPUT=tcp - ULS_HOST=<BINDPLANE_HOST> - ULS_PORT=5140 volumes: - ~/.edgerc:/root/.edgerc:ro uls-eaa-admin: image: akamai/uls:latest container_name: uls-eaa-admin restart: unless-stopped environment: - ULS_INPUT=eaa - ULS_FEED=admin - ULS_OUTPUT=tcp - ULS_HOST=<BINDPLANE_HOST> - ULS_PORT=5140 volumes: - ~/.edgerc:/root/.edgerc:ro uls-eaa-conhealth: image: akamai/uls:latest container_name: uls-eaa-conhealth restart: unless-stopped environment: - ULS_INPUT=eaa - ULS_FEED=conhealth - ULS_OUTPUT=tcp - ULS_HOST=<BINDPLANE_HOST> - ULS_PORT=5140 volumes: - ~/.edgerc:/root/.edgerc:ro
Remplacez <BINDPLANE_HOST> par l'adresse IP ou le nom d'hôte du serveur de l'agent Bindplane.
Démarrez les conteneurs :
docker compose up -dAffichez les journaux :
docker compose logs -f
Table de mappage UDM
| Champ du journal | mappage UDM | Logique |
|---|---|---|
app |
target.application |
La valeur après le signe deux-points dans le champ app. |
apphost |
target.hostname |
Mappage direct. |
browser |
network.http.user_agent |
Mappage direct. |
bytes_in |
network.recieved_bytes |
Mappage direct. |
bytes_out |
network.sent_bytes |
Mappage direct. |
cc |
principal.location.country_or_region |
Mappage direct. |
client_id |
additional.fields.key : "ID client", additional.fields.value.string_value : client_id |
Mappé de manière conditionnelle si client_id est présent. |
clientip |
principal.ip |
Mappage direct. |
cloud_zone |
principal.cloud.availability_zone |
Mappé directement. |
connector_resp_time |
security_result.detection_fields.key : "Temps de réponse du connecteur", security_result.detection_fields.value : connector_resp_time |
Mappé de manière conditionnelle si connector_resp_time n'est pas vide ou ne contient pas "-". |
content_type |
additional.fields.key: "Content type", additional.fields.value.string_value: content_type |
Mappé de manière conditionnelle si content_type est présent. |
datetime |
metadata.event_timestamp |
Analysé à partir du champ datetime au format RFC 3339. |
deny_reason |
security_result.summary |
Mappage direct. |
device_type |
principal.platform, principal.platform_version |
Mappé sur WINDOWS, LINUX ou MAC en fonction de la correspondance d'expression régulière. La valeur brute est mappée sur principal.platform_version. |
di |
metadata.ingestion_labels.key: "di", metadata.ingestion_labels.value: di |
Mappé directement en tant que libellé d'ingestion. |
error_code |
additional.fields.key : "Code d'erreur", additional.fields.value.string_value : error_code |
Mappé de manière conditionnelle si error_code est présent. |
event |
metadata.description |
Mappage direct. |
geo_city |
principal.location.city |
Mappage direct. |
geo_country |
principal.location.country_or_region |
Mappage direct. |
geo_state |
principal.location.state |
Mappage direct. |
groups |
principal.user.group_identifiers |
Mappage direct. |
http_method |
network.http.method |
Mappé directement. |
http_ver |
network.application_protocol, network.application_protocol_version |
Analysé à l'aide de grok pour extraire le protocole et la version. |
idpinfo |
additional.fields.key: "IDP Info", additional.fields.value.string_value: idpinfo |
Mappé de manière conditionnelle si idpinfo est présent. |
internal_host |
additional.fields.key : "Hôte interne", additional.fields.value.string_value : internal_host |
Mappé de manière conditionnelle si internal_host est présent. |
metadata.log_type |
metadata.log_type |
Codé en dur sur "AKAMAI_EAA". |
metadata.product_name |
metadata.product_name |
Codé en dur sur "AKAMAI_EAA". |
metadata.vendor_name |
metadata.vendor_name |
Codé en dur sur "AKAMAI_EAA". |
metadata.event_type |
metadata.event_type |
Déterminé par la logique : USER_UNCATEGORIZED si uid est présent, NETWORK_HTTP si principal.ip et target sont définis, ou GENERIC_EVENT sinon. |
origin_host |
additional.fields.key: "Origin host", additional.fields.value.string_value: origin_host |
Mappé de manière conditionnelle si origin_host est présent. |
origin_resp_time |
security_result.detection_fields.key: "Origin response time", security_result.detection_fields.value: origin_resp_time |
Mappé de manière conditionnelle si origin_resp_time n'est pas vide ou "-". |
os |
principal.platform |
Mappé sur WINDOWS, MAC ou LINUX en fonction de la correspondance d'expression régulière. |
port |
target.port |
La valeur après le signe deux-points dans le champ app. |
ral |
metadata.description |
Valeurs concaténées du tableau ral, séparées par des virgules. |
referer |
network.http.referral_url |
Mappage direct. |
resource |
principal.resource.attribute.labels.key : "Ressource", principal.resource.attribute.labels.value : resource |
Mappé de manière conditionnelle si resource est présent. |
resource_type |
principal.resource.attribute.labels.key: "Resource Type", principal.resource.attribute.labels.value: resource_type |
Mappé de manière conditionnelle si resource_type est présent. |
rscd |
metadata.ingestion_labels.key: "rscd", metadata.ingestion_labels.value: rscd |
Mappé directement en tant que libellé d'ingestion. |
session_id |
network.session_id |
Mappé directement. |
session_info |
additional.fields.key: "Session info", additional.fields.value.string_value: session_info |
Mappé de manière conditionnelle si session_info est présent. |
state |
principal.location.state |
Mappage direct. |
status_code |
network.http.response_code |
Mappé directement. |
total_resp_time |
security_result.detection_fields.key : "Temps de réponse total", security_result.detection_fields.value : total_resp_time |
Mappé de manière conditionnelle si total_resp_time n'est pas vide ou ne contient pas "-". |
ts |
metadata.event_timestamp |
Analysé à partir du champ ts en tant que millisecondes ou secondes UNIX, le cas échéant, ou à partir du champ datetime. |
uid |
principal.user.userid |
Mappage direct. |
uip |
principal.ip |
Mappage direct. |
url_path |
target.url |
Mappage direct. |
user_agent |
network.http.user_agent, network.http.parsed_user_agent |
Mappé et analysé directement dans un champ parsed_user_agent structuré. |
username |
principal.user.email_addresses ou principal.user.userid |
Mappé sur email_addresses si cela ressemble à une adresse e-mail, sinon sur userid. |
Journal des modifications
Afficher le journal des modifications de cet analyseur
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.