Collect Akamai EAA (Enterprise Application Access) logs

Supported in:

This document explains how to ingest Akamai Enterprise Application Access (EAA) logs to Google Security Operations using Akamai's Unified Log Streamer (ULS) and Bindplane. Akamai EAA produces operational data in the form of access logs, admin audit logs, authentication details, and connector health metrics. The parser extracts fields from the JSON logs, performs data transformations like string conversions and IP address extraction, and maps these fields to the UDM, handling various event types like NETWORK_HTTP and USER_UNCATEGORIZED based on the presence of specific fields. It also adds metadata like vendor and product names to the UDM event.

Before you begin

Make sure you have the following prerequisites:

  • A Google SecOps instance
  • A Windows 2016 or later or Linux host with systemd to run the Bindplane agent
  • Linux, macOS, or containerized environment (Docker/Kubernetes) to run Unified Log Streamer
  • If running behind a proxy, ensure firewall ports are open per the Bindplane agent requirements
  • Akamai EAA tenant with administrative access
  • Akamai API credentials (EdgeGrid authentication):
    • Access Token
    • Client Token
    • Client Secret
    • API Base Hostname (for example, akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net )

Get Google SecOps ingestion authentication file

  1. Sign in to the Google SecOps console.
  2. Go to SIEM Settings > Collection Agents.
  3. Download the Ingestion Authentication File. Save the file securely on the system where Bindplane will be installed.

Get Google SecOps customer ID

  1. Sign in to the Google SecOps console.
  2. Go to SIEM Settings > Profile.
  3. Copy and save the Customer IDfrom the Organization Detailssection.

Install the Bindplane agent

Install the Bindplane agent on your Windows or Linux operating system according to the following instructions.

Windows installation

  1. Open the Command Promptor PowerShellas an administrator.
  2. Run the following command:

      msiexec 
      
     / 
     i 
      
     "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" 
      
     / 
     quiet 
     
    

Linux installation

  1. Open a terminal with root or sudo privileges.
  2. Run the following command:

     sudo  
    sh  
    -c  
     " 
     $( 
    curl  
    -fsSlL  
    https://github.com/observiq/bindplane-agent/releases/latest/download/install_unix.sh ) 
     " 
      
    install_unix.sh 
    

Additional installation resources

Configure the Bindplane agent to ingest Syslog and send to Google SecOps

  1. Access the configuration file:

    1. Locate the config.yaml file. Typically, it's in the /etc/bindplane-agent/ directory on Linux or in the installation directory on Windows.
    2. Open the file using a text editor (for example, nano , vi , or Notepad).
  2. Edit the config.yaml file as follows:

      receivers 
     : 
      
     tcplog 
     : 
      
     listen_address 
     : 
      
     "0.0.0.0:5140" 
     exporters 
     : 
      
     chronicle/chronicle_w_labels 
     : 
      
     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/chronicle_w_labels 
     
    
    • Replace the following:
      • Replace <CUSTOMER_ID> with the actual customer ID.
      • Update /path/to/ingestion-authentication-file.json to the path where the authentication file was saved in the Get Google SecOps ingestion authentication file section.
      • 0.0.0.0:5140 : The IP address and port for Bindplane to listen on. Adjust as needed for your environment.

Restart the Bindplane agent to apply the changes

  • To restart the Bindplane agent in Linux, run the following command:

     sudo  
    systemctl  
    restart  
    bindplane-agent 
    
  • To restart the Bindplane agent in Windows, you can either use the Servicesconsole or enter the following command:

     net stop BindPlaneAgent && net start BindPlaneAgent 
    

Install Akamai Unified Log Streamer

Unified Log Streamer (ULS) pulls logs from Akamai EAA via the Enterprise Application Access API and streams them to Bindplane using TCP or UDP.

Linux installation

  1. Download the latest ULS release:

     curl  
    -LO  
    https://github.com/akamai/uls/releases/latest/download/uls-linux-amd64 
    
  2. Make the binary executable:

     chmod  
    +x  
    uls-linux-amd64 
    
  3. Move it to a standard location:

     sudo  
    mv  
    uls-linux-amd64  
    /usr/local/bin/uls 
    

macOS installation

  1. Download the latest ULS release:

     curl  
    -LO  
    https://github.com/akamai/uls/releases/latest/download/uls-darwin-amd64 
    
  2. Make the binary executable:

     chmod  
    +x  
    uls-darwin-amd64 
    
  3. Move it to a standard location:

     sudo  
    mv  
    uls-darwin-amd64  
    /usr/local/bin/uls 
    

Docker installation

  1. Pull the official ULS Docker image:

     docker  
    pull  
    akamai/uls:latest 
    

Configure Akamai EdgeGrid credentials

  1. Create the EdgeGrid credentials file:

     mkdir  
    -p  
    ~/.edgerc
    nano  
    ~/.edgerc 
    
  2. Add your Akamai API credentials in the following format:

      [default] 
     client_secret 
      
     = 
      
     your-client-secret 
     host 
      
     = 
      
     akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net 
     access_token 
      
     = 
      
     your-access-token 
     client_token 
      
     = 
      
     your-client-token 
     
    
  3. Secure the credentials file:

     chmod  
     600 
      
    ~/.edgerc 
    

Replace the following:

  • your-client-secret : Your Akamai Client Secret.
  • your-access-token : Your Akamai Access Token.
  • your-client-token : Your Akamai Client Token.
  • akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net : Your Akamai API base hostname.

Configure ULS to stream EAA logs to BindPlane

Command-line execution (testing)

Run ULS with TCP output to stream logs to the Bindplane agent:

   
uls  
--input  
eaa  
 \ 
  
--feed  
access  
 \ 
  
--output  
tcp  
 \ 
  
--host  
<BINDPLANE_HOST>  
 \ 
  
--port  
 5140 
  
 \ 
  
--edgerc  
~/.edgerc  
 \ 
  
--section  
default 
  • Replace the following:
    • <BINDPLANE_HOST> : The IP address or hostname of the server running Bindplane
    • 5140 : The port configured in Bindplane's tcplog receiver

To stream multiple feed types, run separate ULS instances:

 ```bash # 
Access logs
uls --input eaa --feed access --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default # 
Admin audit logs
uls --input eaa --feed admin --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default # 
Connector health
uls --input eaa --feed conhealth --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default
``` 

Systemd service (production)

For production deployments, configure ULS as a systemd service:

  1. Create a ULS configuration file:

     sudo  
    mkdir  
    -p  
    /etc/uls
    sudo  
    nano  
    /etc/uls/eaa-access-tcp.conf 
    
  2. Add the following configuration:

      ULS_INPUT 
     = 
    eaa ULS_FEED 
     = 
    access ULS_OUTPUT 
     = 
    tcp ULS_HOST 
     = 
    <BINDPLANE_HOST> ULS_PORT 
     = 
     5140 
     ULS_EDGERC 
     = 
    /root/.edgerc ULS_SECTION 
     = 
    default 
    
  3. Create a systemd service file:

     sudo  
    nano  
    /etc/systemd/system/uls-eaa-access.service 
    
  4. Add the following content:

      [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/local/bin/uls --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.target 
     
    
  5. Enable and start the service:

     sudo  
    systemctl  
    daemon-reload
    sudo  
    systemctl  
     enable 
      
    uls-eaa-access.service
    sudo  
    systemctl  
    start  
    uls-eaa-access.service 
    
  6. Verify the service is running:

     sudo  
    systemctl  
    status  
    uls-eaa-access.service 
    
  7. View logs:

     sudo  
    journalctl  
    -u  
    uls-eaa-access.service  
    -f 
    

Repeat steps 1-7 for each additional feed type (admin, conhealth) by creating separate configuration and service files with different names (for example, uls-eaa-admin.service , uls-eaa-conhealth.service ).

Docker deployment

  1. Create a Docker Compose file:

     nano  
    docker-compose.yml 
    
  2. Add the following configuration:

      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 
      
     command 
     : 
      
    >  
     --input eaa 
      
     --feed access 
      
     --output tcp 
      
     --host "$${ULS_HOST}" 
      
     --port "$${ULS_PORT}" 
      
     --edgerc /root/.edgerc 
      
     --section default 
      
     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 
      
     command 
     : 
      
    >  
     --input eaa 
      
     --feed admin 
      
     --output tcp 
      
     --host "$${ULS_HOST}" 
      
     --port "$${ULS_PORT}" 
      
     --edgerc /root/.edgerc 
      
     --section default 
      
     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 
      
     command 
     : 
      
    >  
     --input eaa 
      
     --feed conhealth 
      
     --output tcp 
      
     --host "$${ULS_HOST}" 
      
     --port "$${ULS_PORT}" 
      
     --edgerc /root/.edgerc 
      
     --section default 
     
    
    • Replace <BINDPLANE_HOST> with the IP address or hostname of your Bindplane server.
  3. Start the containers:

     docker-compose  
    up  
    -d 
    
  4. View logs:

     docker-compose  
    logs  
    -f 
    

UDM Mapping Table

Log field UDM mapping Logic
app
target.application The value after the colon in the app field.
apphost
target.hostname Directly mapped.
browser
network.http.user_agent Directly mapped.
bytes_in
network.received_bytes Directly mapped.
bytes_out
network.sent_bytes Directly mapped.
cc
principal.location.country_or_region Directly mapped.
client_id
additional.fields.key : "Client Id", additional.fields.value.string_value : client_id Conditionally mapped if client_id is present.
clientip
principal.ip Directly mapped.
cloud_zone
principal.cloud.availability_zone Directly mapped.
connector_resp_time
security_result.detection_fields.key : "Connector response time", security_result.detection_fields.value : connector_resp_time Conditionally mapped if connector_resp_time is not empty or "-".
content_type
additional.fields.key : "Content type", additional.fields.value.string_value : content_type Conditionally mapped if content_type is present.
datetime
metadata.event_timestamp Parsed from the datetime field using the RFC3339 format.
deny_reason
security_result.summary Directly mapped.
device_type
principal.platform , principal.platform_version Mapped to WINDOWS , LINUX , or MAC based on regex matching. The raw value is mapped to principal.platform_version .
di
metadata.ingestion_labels.key : "di", metadata.ingestion_labels.value : di Directly mapped as an ingestion label.
error_code
additional.fields.key : "Error code", additional.fields.value.string_value : error_code Conditionally mapped if error_code is present.
event
metadata.description Directly mapped.
geo_city
principal.location.city Directly mapped.
geo_country
principal.location.country_or_region Directly mapped.
geo_state
principal.location.state Directly mapped.
groups
principal.user.group_identifiers Directly mapped.
http_method
network.http.method Directly mapped.
http_ver
network.application_protocol , network.application_protocol_version Parsed using grok to extract protocol and version.
idpinfo
additional.fields.key : "IDP Info", additional.fields.value.string_value : idpinfo Conditionally mapped if idpinfo is present.
internal_host
additional.fields.key : "Internal host", additional.fields.value.string_value : internal_host Conditionally mapped if internal_host is present.
metadata.log_type
metadata.log_type Hardcoded to "AKAMAI_EAA".
metadata.product_name
metadata.product_name Hardcoded to "AKAMAI_EAA".
metadata.vendor_name
metadata.vendor_name Hardcoded to "AKAMAI_EAA".
metadata.event_type
metadata.event_type Determined by logic: USER_UNCATEGORIZED if uid is present, NETWORK_HTTP if both principal.ip and target are set, or GENERIC_EVENT otherwise.
origin_host
additional.fields.key : "Origin host", additional.fields.value.string_value : origin_host Conditionally mapped if origin_host is present.
origin_resp_time
security_result.detection_fields.key : "Origin response time", security_result.detection_fields.value : origin_resp_time Conditionally mapped if origin_resp_time is not empty or "-".
os
principal.platform Mapped to WINDOWS , MAC , or LINUX based on regex matching.
port
target.port The value after the colon in the app field.
ral
metadata.description Concatenated values of the ral array, separated by commas.
referer
network.http.referral_url Directly mapped.
resource
principal.resource.attribute.labels.key : "Resource", principal.resource.attribute.labels.value : resource Conditionally mapped if resource is present.
resource_type
principal.resource.attribute.labels.key : "Resource Type", principal.resource.attribute.labels.value : resource_type Conditionally mapped if resource_type is present.
rscd
metadata.ingestion_labels.key : "rscd", metadata.ingestion_labels.value : rscd Directly mapped as an ingestion label.
session_id
network.session_id Directly mapped.
session_info
additional.fields.key : "Session info", additional.fields.value.string_value : session_info Conditionally mapped if session_info is present.
state
principal.location.state Directly mapped.
status_code
network.http.response_code Directly mapped.
total_resp_time
security_result.detection_fields.key : "Total response time", security_result.detection_fields.value : total_resp_time Conditionally mapped if total_resp_time is not empty or "-".
ts
metadata.event_timestamp Parsed from the ts field as UNIX milliseconds or seconds if present, otherwise from the datetime field.
uid
principal.user.userid Directly mapped.
uip
principal.ip Directly mapped.
url_path
target.url Directly mapped.
user_agent
network.http.user_agent , network.http.parsed_user_agent Directly mapped and parsed into a structured parsed_user_agent field.
username
principal.user.email_addresses or principal.user.userid Mapped to email_addresses if it looks like an email, otherwise to userid .

Need more help? Get answers from Community members and Google SecOps professionals.

Design a Mobile Site
View Site in Mobile | Classic
Share by: