Skip to content

Commit

Permalink
V. 0.9.0 Pull request (#8)
Browse files Browse the repository at this point in the history
* added missing -r in CLI USAGE pip installation for ETP THX JSR ;)

* enhanced JSR feedback to SPLUNK.md

* enhanced JSR feedback to SPLUNK.md

* Fix minor typo

* fixed a bug in the installation instructions etp -> eaa

* API credential docs + version upgrades

* references to api cred creation added

* minor changelog addition

* added filter code incl. err handling

* fixed edgerc - sample file

* fixed minor rawcmd issue, amended documentation for filtering

* added doc link for ETP API filtering

* amended new features to README.md

* added cpu / mem warning to readme

* fixed typo

* Minor edits on API credentials doc

* Minor change (screenshot dimension etc...)

* Minor doc update

* new mfa version

* bumped ULS Version

* fixed a bug in the re-fork counter to handover to docker after x-attempts

* bumped to a higher version 0.9.0

* bumped EAA version + amended stuff to changelog

* added FAQ document

* amended changelog

Co-authored-by: Antoine Drochon <[email protected]>
  • Loading branch information
MikeSchiessl and bitonio authored Jul 23, 2021
1 parent a073d1c commit 2d20b50
Show file tree
Hide file tree
Showing 23 changed files with 404 additions and 34 deletions.
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.9.5-slim-buster
FROM python:3.9.6-slim-buster
LABEL maintainer="Mike Schiessl - [email protected]"
LABEL APP="Akamai Universal Log Streamer"

Expand All @@ -8,8 +8,8 @@ ARG ULS_DIR="$HOMEDIR/uls"
ARG EXT_DIR="$ULS_DIR/ext"

ARG ETP_CLI_VERSION="0.3.5"
ARG EAA_CLI_VERSION="0.3.9"
ARG MFA_CLI_VERSION="0.0.5"
ARG EAA_CLI_VERSION="0.4.1"
ARG MFA_CLI_VERSION="0.0.6"

# ENV VARS
ENV ULS_DIR=$ULS_DIR
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ It can be run directly as Python code, as a provided Docker container or through
- Debug information (log level adjustment)
- HTTP CA CERT verification skipping
- Adoptable HTTP - POST format
- [Output filter](docs/ADDITIONAL_FEATURES.md#filter---filter-feature) (to reduce number of log lines sent to SIEM)

## Documentation
ULS can be operated in many ways.
Expand All @@ -69,7 +70,7 @@ More information for specific SIEM solutions can be found in [this directory](./

### Generic Requirements
- Python 3.9+ OR docker / docker-compose
- AKAMAI .edgerc file
- AKAMAI .edgerc file ([see further documentation here](docs/AKAMAI_API_CREDENTIALS.md))
- Internet access

### Command Line Usage
Expand Down Expand Up @@ -107,7 +108,7 @@ Contributions to this software can be provided via [Pull Requests](https://docs.
Akamai ULS is provided "as-is". It is not supported by Akamai Support. Akamai is neither liable for the function nor for any caused problems that come along with the usage or caused by this tool. Please refer to the [LICENSE](./LICENSE) document for more information.

To report an issue, feature request or bug, please open a new issue into the [GitHub Issues page](https://github.com/akamai/uls/issues).
This software is released under the "Apache License". Please visit the [debugging instructions](./docs/DEBUGGING.md) before opening a bug request.
This software is released under the "Apache License". Please read the [frequently asked questions](docs/FAQ.md) and visit the [debugging instructions](./docs/DEBUGGING.md) before opening a bug request.

[Pull requests](#development) to improve the code or enhance the functionality are welcome.

Expand Down
2 changes: 1 addition & 1 deletion bin/config/global_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3

# Common global variables / constants
__version__ = "0.0.4"
__version__ = "0.9.0"
__tool_name_long__ = "Akamai Unified Log Streamer"
__tool_name_short__ = "ULS"

Expand Down
7 changes: 7 additions & 0 deletions bin/modules/UlsArgsParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ def init():
default=int(os.environ.get('ULS_OUTPUT_PORT') or '0'),
help="Port for TCP/UDP")

# Output FILTER
output_group.add_argument('--filter',
action='store',
type=str,
default=(os.environ.get('ULS_OUTPUT_FILTER') or None),
help="Filter (regex) to reduce number of sent log files (Only send lines that match the --filter argument).")

# HTTP URL
output_group.add_argument('--httpurl',
action='store',
Expand Down
20 changes: 10 additions & 10 deletions bin/modules/UlsInputCli.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def __init__(self):
self.running = False # Internal Running tracker - do not touch
self.proc = None
self.proc_output = None
self.rerun_counter = 1

def _feed_selector(self, feed, product_feeds):
if feed in product_feeds:
Expand Down Expand Up @@ -87,9 +88,7 @@ def proc_create(self, product=None,
rawcmd=None,
inproxy=None):

rerun_counter = 1

while self.running is False and rerun_counter <= self.rerun_retries:
while self.running is False and self.rerun_counter <= self.rerun_retries:
edgegrid_auth = self._prep_edgegridauth(credentials_file, credentials_file_section)
aka_log.log.debug(f'{self.name} - selected product: {product}')

Expand All @@ -110,7 +109,7 @@ def proc_create(self, product=None,
cli_command.append('--json')
else:
cli_command = [self.bin_python, product_path] + \
self._uls_useragent(product, feed) +\
self._uls_useragent(product, "rawcmd") +\
shlex.split(rawcmd)

# ETP config
Expand All @@ -125,7 +124,7 @@ def proc_create(self, product=None,
cli_command[2:2] = self._prep_proxy(inproxy)
else:
cli_command = [self.bin_python, product_path] +\
self._uls_useragent(product, feed) +\
self._uls_useragent(product, "rawcmd") +\
shlex.split(rawcmd)

# MFA config
Expand All @@ -140,7 +139,7 @@ def proc_create(self, product=None,
cli_command[2:2] = self._prep_proxy(inproxy)
else:
cli_command = [self.bin_python, product_path] +\
self._uls_useragent(product, feed) +\
self._uls_useragent(product, "rawcmd") +\
shlex.split(rawcmd)

# Everything else (undefined)
Expand All @@ -163,19 +162,20 @@ def proc_create(self, product=None,
raise NameError(f"process [{cli_proc.pid}] "
f"exited RC={cli_proc.returncode}, REASON: {cli_proc.stderr.read().decode()}")

# Handover the app into running state (disable stderr as it caused issues)
# Handover the app into running state (disable stderr as it caused issues) and reset rerun counter to 1
self.running = True
self.rerun_counter = 1
cli_proc.stderr = subprocess.DEVNULL

except Exception as my_error:
time.sleep(self.rerun_delay)
self.running = False
rerun_counter += 1
self.rerun_counter += 1
aka_log.log.error(f'{self.name} - {my_error} - {cli_proc.stderr.read().decode()}')

if self.running is False and rerun_counter > self.rerun_retries:
if self.running is False and self.rerun_counter > self.rerun_retries:
aka_log.log.critical(f'Not able to start the CLI for {product}. See above errors. '
f'Giving up after {rerun_counter - 1} retries.')
f'Giving up after {self.rerun_counter - 1} retries.')
sys.exit(1)

def check_proc(self):
Expand Down
16 changes: 15 additions & 1 deletion bin/uls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import sys
import signal
import threading
import re

# ULS specific modules
import modules.aka_log as aka_log
Expand Down Expand Up @@ -72,6 +73,15 @@ def main():
my_output = UlsOutput.UlsOutput()
my_input = UlsInputCli.UlsInputCli()

# Prepare the Filter
if uls_args.filter:
try:
aka_log.log.debug(f"FILTER pattern has been specified: {uls_args.filter} - will only output matches")
filter_pattern = re.compile(uls_args.filter.encode())
except Exception as error:
aka_log.log.critical(f"Error in filter patter {uls_args.filter} (exiting). Error: {error}")
exit(1)

# When reading CLI output, if no data, pause 10ms before retrying
# if still no data, then it will backoff exponentially till 60s
wait_default = uls_config.main_wait_default
Expand Down Expand Up @@ -105,9 +115,13 @@ def main():
wait = wait_default # back to 10ms wait in case of bursty content
aka_log.log.debug(f"<IN> {input_data}")
for e in input_data.splitlines():
my_monitor.increase_message_count()
# ENHANCEMENT FOR FILTERING
if uls_args.filter and not filter_pattern.match(e):
aka_log.log.debug(f"SKIPPED LINE due to FILTER rule: {e}")
continue
out_data = e + uls_config.output_line_breaker.encode()
my_output.send_data(out_data)
my_monitor.increase_message_count()
aka_log.log.debug(f"<OUT> {out_data}")
else:
aka_log.log.debug(f"Mainloop, wait {wait} seconds [{my_monitor.get_stats()}]")
Expand Down
41 changes: 41 additions & 0 deletions docs/ADDITIONAL_FEATURES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Additional ULS Features
This document handles the usage of features not explained anywhere else.

## FILTER (--filter) Feature
This feature got introduced in ULS v0.0.5.
It allows to decrease the number of log lines sent to SIEM for cost, performance or security reasons.

The filter is **regex** based so it is capable of filtering "json" AND raw text events.
Only events **matching the filter pattern will be sent towards the selected SIEM** output.
Filtering can lead to higher CPU / MEMORY consumption in production environments.
For ETP there is also an option to [filter directly on the API request side](AKAMAI_API_CREDENTIALS.md#etp-api-event-filters).

### Usage examples:
- Filter for "geo_country": "Germany" (in EAA Access logs)
```bash
python3 bin/uls.py -i eaa -f access -o raw <additional params> --filter '.*"geo_country": "Germany".*'
```
- Filter for "actionName": "Block - Error Page" (in ETP Threat logs)
```bash
python3 bin/uls.py -i etp -f threat -o raw <additional params> --filter '.*"actionName": "Block - Error Page".*'
```
Always test your filter with the "RAW" console output on the command line before you send the data towards a SIEM
```bash
python3 bin/uls.py -i eaa --feed access --filter '.*"geo_country": "Germany".*' -o raw
```

## RAWCMD (--rawcmd) Feature
This feature got introduced in ULS v0.0.3.
Attention: This is a pretty critical setting, which can break ULS behaviour.

Raw commands within ULS can be used to trigger cli calls, that have not been integrated into ULS (yet).
This allows a more flexible implementation to solve some edge cases.
RAWCMD just requires the input to be selected.

Example:
```bash
python3 bin/uls.py -i etp --rawcmd 'event threat -f' -l debug -o raw
```
This will also run the etp threat feed in "tail -f" mode

Please be aware: Not all output from the cli will be redirected to ULS by default.
173 changes: 173 additions & 0 deletions docs/AKAMAI_API_CREDENTIALS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Configure Akamai API credentials for ULS<!-- omit in toc -->

This document describes how to create Akamai API credentials and configure them in Unified Log Streamer (ULS) to access the different Akamai products and data feeds.

## Table of contents<!-- omit in toc -->

- [Feeds / API overview](#feeds--api-overview)
- [Setting up API credentials for ULS](#setting-up-api-credentials-for-uls)
- [Enterprise Application Access (EAA)](#enterprise-application-access-eaa)
- [EAA Legacy API (for Access and Admin Audit feeds)](#eaa-legacy-api-for-access-and-admin-audit-feeds)
- [EAA {OPEN} API (for Connector Health feed)](#eaa-open-api-for-connector-health-feed)
- [Enterprise Threat Protector (ETP)](#enterprise-threat-protector-etp)
- [ETP {OPEN} API Reporting](#etp-open-api-reporting)
- [Akamai MFA](#akamai-mfa)
- [MFA Integration for logging](#mfa-integration-for-logging)
- [Advanced .edgerc usage](#advanced-edgerc-usage)
- [Multiple customer contracts](#multiple-customer-contracts)
- [Partner & employee enhancement](#partner--employee-enhancement)
- [ETP API EVENT Filters](#etp-api-event-filters)

## Feeds / API overview

|Product long name|Acronym|Feed|API|
|---|---|---|---|
|Enterprise Application Access|EAA|ACCESS|[EAA Legacy API](#eaa-legacy-api-for-access-and-admin-audit-feeds)|
|Enterprise Application Access|EAA|ADMIN|[EAA Legacy API](#eaa-legacy-api-for-access-and-admin-audit-feeds)|
|Enterprise Application Access|EAA|HEALTH|[{OPEN} API / Enterprise Application Access](#eaa-open-api-for-connector-health-feed)|
|Enterprise Threat Protector|ETP|THREAT|[{OPEN} API / ETP Report](#etp-open-api-reporting)|
|Enterprise Threat Protector|ETP|AUP|[{OPEN} API / ETP Report](#etp-open-api-reporting)|
|Akamai MFA|MFA|AUTH|[MFA Integration](#mfa-integration-for-logging)|
|Akamai MFA|MFA|POLICY|[MFA Integration](#mfa-integration-for-logging)|

## Setting up API credentials for ULS

ULS will read the API credentials from a text file, by default named `.edgerc` and stored in the home directory of the current user. The credentials configuration file can have multiple sections allowing to use multiple tenants (in case of multi-contract structure, or Akamai Partner).

Some basic information around `.edgerc` can be found [here](https://developer.akamai.com/legacy/introduction/Conf_Client.html).
This repo also provides a [.edgerc sample file](examples/.edgerc-sample) with all config sections added and explained.

Feel free to use the file as a template and comment out the sections not needed with `;`.

You'll find below all the details how to create the credentials based on the Akamai Data you plan to use with ULS.

### Enterprise Application Access (EAA)

#### EAA Legacy API (for Access and Admin Audit feeds)

To create **EAA Legacy API** credentials, connect to [Akamai Control Center](https://control.akamai.com)

- Select **Enterprise Center** from the main navigation menu on the left
- Navigate to **General Settings** > **Settings**
- Select the **API Keys** tab
- Click **Generate new API Key** top right button
- Enter a name and a description
- On the confirmation screen, copy the **Key** and the **Secret**:
- <img src="images/uls_apicreds_eaa_ec.png" width="846" />
- Add/replace/amend the following section to your `.edgerc` file and replace the data accordingly, example in the default section:

```INI
[default]
; API credentials for EAA access and admin logs
eaa_api_host = manage.akamai-access.com
eaa_api_key = XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX
eaa_api_secret = XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX
```

#### EAA {OPEN} API (for Connector Health feed)

To create **Akamai {OPEN} API** credentials, please follow [these instructions](https://developer.akamai.com/legacy/introduction/Prov_Creds.html).

Make sure the API user has `READ-WRITE` permission on the **Enterprise Application Access** API. For ULS usage, it is safe to provide all required API permission (such as EAA, ETP) to a single API user.

<img src="images/uls_apicreds_eaa_openapi.png" width="1251" alt="Edit API client screenshot in Akamai Control Center" />

Please add/replace/amend the following section to your `.edgerc` file and replace the data accordingly, example in the default section:

```INI
[default]
; Akamai {OPEN} API credentials
host = akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net
client_token = akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx
client_secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
access_token = akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx
```

### Enterprise Threat Protector (ETP)

#### ETP {OPEN} API Reporting

To create **AKAMAI {OPEN} API** credentials, please follow [these instructions](https://developer.akamai.com/legacy/introduction/Prov_Creds.html).

Make sure the API user has **READ-WRITE** permission to the **etp-config** API
For ULS usage, it is safe to provide all required roles (such as EAA, ETP) to a single api user.

For ETP usage, an additional config value (**etp_config_id**) is required.
The `etp_config_id` value can be obtained as follows:
- Connect to [Akamai Control Center](https://control.akamai.com)
- Select **Enterprise Center**
- Select **Locations** > **Locations** (or any other ETP specific page)
- Check out the URL bar of your browser, locate your **ETP configuration identifier** between `/etp/` and `/location/`:
![img.png](images/uls_apicreds_etp_customerid.png)

Please add/replace/amend the following section to your `.edgerc` file and replace the data accordingly:
```INI
[default]
; Akamai {OPEN} API credentials
host = akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net
client_token = akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx
client_secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
access_token = akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx

; ETP Config ID (required for ETP usage, can be obtained from the Akamai Web Interface)
etp_config_id = your-ETP-config-ID
```

### Akamai MFA

#### MFA Integration for logging

To create **MFA Integration** credentials, connect to [Akamai Control Center](https://control.akamai.com).

- Select **Enterprise Center** from the main navigation menu on the left
- Navigate to **MFA** > **Integrations**
- Click on (+) to add a new MFA integration:
<img src="images/uls_apicreds_mfa_create.png" width="778" />
- Confirm by clicking the **Save & Deploy** button
- **Copy** the credentials as shown below:
<img src="images/uls_apicreds_mfa_creds.png" width="366" />
- Add/replace/amend the following section to your `.edgerc` file and replace the data accordingly:

```INI
[default]
; Akamai MFA logging integration credentials
mfa_integration_id = app_xxxxxxxxxxxxxxxxxxxxx
mfa_signing_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## Advanced .edgerc usage

### Multiple customer contracts

If your organization has multiple contracts, please add the following "contract_id" line to your `.edgerc` file in order select the proper contract.
If ETP and EAA are on different contracts, we recommend the creation of two different `.edgerc` files.

```INI
[default]
; If your organization have multiple contracts with EAA service
; please add it below. Contact your Akamai representative to obtain it
contract_id = A-B-1CD2E34
```

### Partner & employee enhancement

For Partners or AKAMAI employees please add the "extra_qs" line to your `.edgerc` file in order to switch towards the desired tenant. Please replace "TENANT-SWITCH-KEY" with the provided switch key.

```INI
[default]
; If you are a partner managing multiple customers, you can use the switchkey
; For more information, see:
; https://learn.akamai.com/en-us/learn_akamai/getting_started_with_akamai_developers/developer_tools/accountSwitch.html
extra_qs = accountSwitchKey=TENANT-SWITCH-KEY
```

### ETP API EVENT Filters

For Enterprise Threat protector (ETP), events can already be filtered at API level, so they won't even be transferred towards ULS.
This can be used for performance / scaling as well for cost saving reasons.
Please find more information around filtering on ETP API in the [ETP APIv3 documentation](https://developer.akamai.com/api/enterprise_security/enterprise_threat_protector_reporting/v3.html#filter)

```INI
[default]
etp_event_filters = {"list":{"nin":["12345"]}}
```
Loading

0 comments on commit 2d20b50

Please sign in to comment.