Raccogliere i log di Akamai Enterprise Application Access
Versione parser: 3.0
Questo documento spiega come importare i log di Akamai Enterprise Application Access (EAA) in Google Security Operations utilizzando Akamai Unified Log Streamer (ULS) e Bindplane. Akamai EAA è una soluzione di accesso alla rete Zero Trust che fornisce un accesso sicuro e basato sull'identità alle applicazioni aziendali senza una VPN tradizionale. EAA produce dati operativi sotto forma di log di accesso, audit log amministratore, metriche di integrità del connettore, inventario dei dispositivi e informazioni sull'integrità della directory. Il parser estrae i campi dai log JSON, esegue trasformazioni dei dati come conversioni di stringhe ed estrazione di indirizzi IP e mappa questi campi all'UDM, gestendo vari tipi di eventi, tra cui NETWORK_HTTP e USER_UNCATEGORIZED, in base alla presenza di campi specifici.
Prima di iniziare
Assicurati di soddisfare i seguenti prerequisiti:
- Un'istanza Google SecOps.
- Un host Windows Server 2016 o versioni successive o Linux con
systemdper eseguire l'agente Bindplane. - Host Linux con Python 3.9 o versioni successive o un ambiente containerizzato (Docker o Kubernetes) per eseguire Unified Log Streamer.
- Se l'agente viene eseguito dietro un proxy, assicurati che le porte del firewall siano aperte in base ai requisiti dell'agente Bindplane.
- Tenant Akamai EAA con accesso amministrativo.
Credenziali API Akamai:
- Per i feed di controllo dell'accesso e dell'amministrazione: chiave e segreto API legacy EAA (creati in Enterprise Center).
- Per i feed sullo stato del connettore, l'inventario dei dispositivi e lo stato della directory: credenziali dell'API Akamai OPEN (autenticazione EdgeGrid) con accesso in lettura/scrittura all'API Enterprise Application Access.
Recuperare il file di autenticazione dell'importazione di Google SecOps
- Accedi alla console Google SecOps.
- Vai a Impostazioni SIEM > Agenti di raccolta.
- Scarica il file di autenticazione dell'acquisizione. Salva il file in modo sicuro sul sistema in cui verrà installato Bindplane.
Recuperare l'ID cliente Google SecOps
- Accedi alla console Google SecOps.
- Vai a Impostazioni SIEM > Profilo.
- Copia e salva l'ID cliente dalla sezione Dettagli dell'organizzazione.
Installa l'agente Bindplane
Installa l'agente Bindplane sul sistema operativo Windows o Linux seguendo le istruzioni riportate di seguito.
Installazione di Windows
- Apri Prompt dei comandi o PowerShell come amministratore.
Esegui questo comando:
msiexec /i "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" /quiet
Installazione di Linux
- Apri un terminale con privilegi root o sudo.
Esegui questo comando:
sudo sh -c "$(curl -fsSlL https://github.com/observiq/bindplane-agent/releases/latest/download/install_unix.sh)" install_unix.sh
Risorse aggiuntive per l'installazione
Per ulteriori opzioni di installazione, consulta la guida all'installazione dell'agente Bindplane.
Configura l'agente Bindplane per importare i log e inviarli a Google SecOps
Apri il file di configurazione dell'agente Bindplane in un editor di testo:
Linux:
sudo nano /status observiq-otel-collector/config.yamlWindows:
notepad "C:\Program Files\observIQ OpenTelemetry Collector\config.yaml"Modifica il file
config.yamlcome segue:receivers: tcplog: listen_address: "0.0.0.0:5140" 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 service: pipelines: logs/akamai_eaa: receivers: - tcplog exporters: - chronicle/akamai_eaa
Sostituisci quanto segue:
/path/to/ingestion-authentication-file.json: il percorso completo del file di autenticazione dell'importazione.- Linux:
/etc/bindplane-agent/ingestion-auth.json - Windows:
C:\Program Files\observIQ OpenTelemetry Collector\ingestion-auth.json
- Linux:
<CUSTOMER_ID>: l'ID cliente Google SecOps.0.0.0.0:5140: l'indirizzo IP e la porta su cui Bindplane deve rimanere in ascolto. Modifica in base alle esigenze del tuo ambiente.
Riavvia l'agente Bindplane per applicare le modifiche
Per riavviare l'agente Bindplane in Linux:
Esegui questo comando:
sudo systemctl restart observiq-otel-collectorVerifica che il servizio sia in esecuzione:
sudo systemctl status observiq-otel-collectorControlla i log per individuare eventuali errori:
sudo journalctl -u observiq-otel-collector -f
Per riavviare l'agente Bindplane in Windows:
Scegli una delle seguenti opzioni:
- Prompt dei comandi o PowerShell come amministratore:
net stop observiq-otel-collector && net start observiq-otel-collector- Console dei servizi:
- Premi
Win+R, digitaservices.msce premi Invio. - Individua observIQ OpenTelemetry Collector.
- Fai clic con il tasto destro del mouse e seleziona Riavvia.
- Premi
Verifica che il servizio sia in esecuzione:
sc query observiq-otel-collectorControlla i log per individuare eventuali errori:
type "C:\Program Files\observIQ OpenTelemetry Collector\log\collector.log"
Crea credenziali API Akamai
Akamai EAA utilizza due tipi di credenziali API a seconda del tipo di feed. Crea le credenziali corrispondenti ai feed che vuoi raccogliere.
Crea credenziali API legacy EAA (per feed di accesso e amministratore)
- Accedi ad Akamai Control Center.
- Seleziona Enterprise Center dal menu di navigazione principale a sinistra.
- Vai a Impostazioni generali > Impostazioni.
- Seleziona la scheda Chiavi API.
- Fai clic su Genera nuova chiave API nell'angolo in alto a destra.
- Inserisci un nome e una descrizione per la chiave API.
Nella schermata di conferma, copia la chiave e il secret.
Crea credenziali API OPEN di Akamai (per lo stato del connettore, l'inventario dei dispositivi e i feed sullo stato della directory)
- Accedi ad Akamai Control Center.
- Vai ad Amministrazione account > Identità e accesso.
- Seleziona la scheda Utenti API.
- Fai clic su Crea client API.
- Nella sezione Seleziona API, cerca Accesso alle applicazioni aziendali e imposta il livello di accesso su READ-WRITE.
- Completa le impostazioni rimanenti e fai clic su Crea client API.
Fai clic su Scarica per scaricare le credenziali in formato
.edgerco su Copia per copiarle in un file.edgercesistente.
Configurare il file delle credenziali .edgerc
Crea il file delle credenziali
.edgercsul sistema in cui verrà eseguito ULS:touch ~/.edgercApri il file in un editor di testo:
nano ~/.edgercAggiungi le credenziali API Akamai nel seguente formato:
[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>Proteggi il file delle credenziali:
chmod 600 ~/.edgerc
Sostituisci quanto segue:
<EAA_API_KEY>: la chiave API legacy di EAA (ad esempio,XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX).<EAA_API_SECRET>: l'API secret legacy di EAA.<OPEN_API_HOST>: il nome host dell'API OPEN di Akamai (ad esempio,akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net).<CLIENT_TOKEN>: il token client API OPEN di Akamai (ad esempio,akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx).<CLIENT_SECRET>: il client secret dell'API OPEN di Akamai.<ACCESS_TOKEN>: il token di accesso all'API OPEN di Akamai (ad esempio,akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx).
Installa Akamai Unified Log Streamer
Unified Log Streamer (ULS) estrae i log da Akamai EAA tramite le API Akamai e li trasmette in streaming all'agente Bindplane utilizzando TCP. ULS è un'applicazione Python che richiede Python 3.9 o versioni successive.
Installazione di Linux (Python)
Clona il repository ULS:
git clone https://github.com/akamai/uls.git cd ulsInstalla i requisiti Python di ULS:
pip3 install -r bin/requirements.txtInstalla la dipendenza 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.txtVerifica l'installazione:
python3 bin/uls.py --help
Installazione di Docker
Esegui il pull dell'immagine Docker ULS ufficiale:
docker pull akamai/uls:latest
Configurare ULS per lo streaming dei log EAA in Bindplane
Esecuzione dalla riga di comando (test)
Esegui ULS con output TCP per trasmettere i log in streaming all'agente Bindplane:
python3 bin/uls.py --input eaa \ --feed access \ --output tcp \ --host <BINDPLANE_HOST> \ --port 5140 \ --edgerc ~/.edgerc \ --section default
Sostituisci quanto segue:
<BINDPLANE_HOST>: L'indirizzo IP o il nome host del server che esegue l'agente Bindplane.5140: la porta configurata nel ricevitore Bindplanetcplog.Per trasmettere in streaming più tipi di feed, esegui istanze ULS separate:
# 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
Servizio Systemd (produzione)
Per le implementazioni di produzione, configura ULS come servizio systemd.
Crea un file di configurazione ULS:
sudo mkdir -p /etc/uls sudo nano /etc/uls/eaa-access-tcp.confAggiungi la seguente configurazione:
ULS_INPUT=eaa ULS_FEED=access ULS_OUTPUT=tcp ULS_HOST=<BINDPLANE_HOST> ULS_PORT=5140 ULS_EDGERC=/root/.edgerc ULS_SECTION=defaultCrea un file di servizio systemd:
sudo nano /etc/systemd/system/uls-eaa-access.serviceAggiungi i seguenti contenuti:
[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.targetAttiva e avvia il servizio:
sudo systemctl daemon-reload sudo systemctl enable uls-eaa-access.service sudo systemctl start uls-eaa-access.serviceVerifica che il servizio sia in esecuzione:
sudo systemctl status uls-eaa-access.serviceVisualizza i log:
sudo journalctl -u uls-eaa-access.service -f
Ripeti i passaggi da 1 a 7 per ogni tipo di feed aggiuntivo (amministratore, conhealth) creando file di configurazione e di servizio separati con nomi diversi (ad esempio, uls-eaa-admin.service, uls-eaa-conhealth.service).
Deployment di Docker Compose
Crea un file
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
Sostituisci <BINDPLANE_HOST> con l'indirizzo IP o il nome host del server dell'agente Bindplane.
Avvia i container:
docker compose up -dVisualizza i log:
docker compose logs -f
Tabella di mappatura UDM
| Campo log | mappatura UDM | Logica |
|---|---|---|
app |
target.application |
Il valore dopo i due punti nel campo app. |
apphost |
target.hostname |
Mappato direttamente. |
browser |
network.http.user_agent |
Mappato direttamente. |
bytes_in |
network.recieved_bytes |
Mappato direttamente. |
bytes_out |
network.sent_bytes |
Mappato direttamente. |
cc |
principal.location.country_or_region |
Mappato direttamente. |
client_id |
additional.fields.key: "Client Id", additional.fields.value.string_value: client_id |
Mappato in modo condizionale se è presente client_id. |
clientip |
principal.ip |
Mappato direttamente. |
cloud_zone |
principal.cloud.availability_zone |
Mappato direttamente. |
connector_resp_time |
security_result.detection_fields.key: "Tempo di risposta del connettore", security_result.detection_fields.value: connector_resp_time |
Mappato in modo condizionale se connector_resp_time non è vuoto o "-". |
content_type |
additional.fields.key: "Tipo di contenuti", additional.fields.value.string_value: content_type |
Mappato in modo condizionale se è presente content_type. |
datetime |
metadata.event_timestamp |
Analizzato dal campo datetime utilizzando il formato RFC 3339. |
deny_reason |
security_result.summary |
Mappato direttamente. |
device_type |
principal.platform, principal.platform_version |
Mappato a WINDOWS, LINUX o MAC in base alla corrispondenza con l'espressione regolare. Il valore non elaborato è mappato a principal.platform_version. |
di |
metadata.ingestion_labels.key: "di", metadata.ingestion_labels.value: di |
Mappato direttamente come etichetta di importazione. |
error_code |
additional.fields.key: "Error code", additional.fields.value.string_value: error_code |
Mappato in modo condizionale se è presente error_code. |
event |
metadata.description |
Mappato direttamente. |
geo_city |
principal.location.city |
Mappato direttamente. |
geo_country |
principal.location.country_or_region |
Mappato direttamente. |
geo_state |
principal.location.state |
Mappato direttamente. |
groups |
principal.user.group_identifiers |
Mappato direttamente. |
http_method |
network.http.method |
Mappato direttamente. |
http_ver |
network.application_protocol, network.application_protocol_version |
Analizzato utilizzando grok per estrarre il protocollo e la versione. |
idpinfo |
additional.fields.key: "IDP Info", additional.fields.value.string_value: idpinfo |
Mappato in modo condizionale se è presente idpinfo. |
internal_host |
additional.fields.key: "Internal host", additional.fields.value.string_value: internal_host |
Mappato in modo condizionale se è presente internal_host. |
metadata.log_type |
metadata.log_type |
Codificato in modo permanente su "AKAMAI_EAA". |
metadata.product_name |
metadata.product_name |
Codificato in modo permanente su "AKAMAI_EAA". |
metadata.vendor_name |
metadata.vendor_name |
Codificato in modo permanente su "AKAMAI_EAA". |
metadata.event_type |
metadata.event_type |
Determinato dalla logica: USER_UNCATEGORIZED se è presente uid, NETWORK_HTTP se sono impostati sia principal.ip che target o GENERIC_EVENT altrimenti. |
origin_host |
additional.fields.key: "Origin host", additional.fields.value.string_value: origin_host |
Mappato in modo condizionale se è presente origin_host. |
origin_resp_time |
security_result.detection_fields.key: "Tempo di risposta dell'origine", security_result.detection_fields.value: origin_resp_time |
Mappato in modo condizionale se origin_resp_time non è vuoto o "-". |
os |
principal.platform |
Mappato a WINDOWS, MAC o LINUX in base alla corrispondenza con l'espressione regolare. |
port |
target.port |
Il valore dopo i due punti nel campo app. |
ral |
metadata.description |
Valori concatenati dell'array ral, separati da virgole. |
referer |
network.http.referral_url |
Mappato direttamente. |
resource |
principal.resource.attribute.labels.key: "Resource", principal.resource.attribute.labels.value: resource |
Mappato in modo condizionale se è presente resource. |
resource_type |
principal.resource.attribute.labels.key: "Resource Type", principal.resource.attribute.labels.value: resource_type |
Mappato in modo condizionale se è presente resource_type. |
rscd |
metadata.ingestion_labels.key: "rscd", metadata.ingestion_labels.value: rscd |
Mappato direttamente come etichetta di importazione. |
session_id |
network.session_id |
Mappato direttamente. |
session_info |
additional.fields.key: "Informazioni sulla sessione", additional.fields.value.string_value: session_info |
Mappato in modo condizionale se è presente session_info. |
state |
principal.location.state |
Mappato direttamente. |
status_code |
network.http.response_code |
Mappato direttamente. |
total_resp_time |
security_result.detection_fields.key: "Tempo di risposta totale", security_result.detection_fields.value: total_resp_time |
Mappato in modo condizionale se total_resp_time non è vuoto o "-". |
ts |
metadata.event_timestamp |
Analizzato dal campo ts come millisecondi o secondi UNIX, se presente, altrimenti dal campo datetime. |
uid |
principal.user.userid |
Mappato direttamente. |
uip |
principal.ip |
Mappato direttamente. |
url_path |
target.url |
Mappato direttamente. |
user_agent |
network.http.user_agent, network.http.parsed_user_agent |
Mappato e analizzato direttamente in un campo parsed_user_agent strutturato. |
username |
principal.user.email_addresses o principal.user.userid |
Mappato a email_addresses se sembra un'email, altrimenti a userid. |
Log delle modifiche
Visualizza il log delle modifiche per questo parser
Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.