Skip to content

Commit

Permalink
v0.6.5 (#37)
Browse files Browse the repository at this point in the history
- Reorganize documentation into sub-pages
- Add the full EAA Application Configuration with `include()` statements and included files
- Introduce connector outbound allowlist to configure Firewall/Network Security Equipment where EAA Connector are operating (experimental) `akamai eaa connector allowlist`
  • Loading branch information
bitonio authored Mar 5, 2024
1 parent 7959a9f commit f10f28d
Show file tree
Hide file tree
Showing 20 changed files with 863 additions and 264 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ __pycache__
.vscode
*.swp
tags
docs/examples/includes/*
docs/examples/includes.akdemo/*
*.env
233 changes: 8 additions & 225 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@
- [Key features](#key-features)
- [Installation / upgrade](#installation--upgrade)
- [Examples](#examples)
- [EAA event logs](#eaa-event-logs)
- [EAA Event Logs](#eaa-event-logs)
- [Applications](#applications)
- [Directory operations](#directory-operations)
- [Connectors](#connectors)
- [Swapping connectors](#swapping-connectors)
- [Certificate management](#certificate-management)
- [Display certificates](#display-certificates)
- [Rotation](#rotation)
- [Device Posture Inventory](#device-posture-inventory)
- [Known Limitations](#known-limitations)
- [Troubleshooting and Support](#troubleshooting-and-support)
Expand Down Expand Up @@ -67,241 +64,27 @@ See [install.md](docs/install.md)

### EAA Event Logs

EAA comes with two types of logs, the user access logs and the administrator audit logs.
For detailed description for each event field, refer to the product documentation on [https://techdocs.akamai.com](https://techdocs.akamai.com/eaa/docs/data-feed-siem).

You can retrieve EAA events one of these ways:
- in near realtime using the argument `-f` or `--tail`. If you set `-f` and date range, the `-f` option will be ignored.
- retrieve a period of time based on EPOCH timestamp in `--start` and `--end`
- tune the acceptable delay vs. completeness with `--delay`. We recommend 10 minutes delay for full completeness.

Pull user access logs, block until new logs are received.
You can stop using Control+C (Control+Break) or sending a SIG_INT or SIG_TERM signal to the process.

```bash
$ akamai eaa log access --tail
```

You may want a one time chunk of log for a period of time, for example, the last 6 hours:

```bash
$ START=$(bc <<< "$(date +%s) - 6 * 60 * 60")
$ akamai eaa log access -s $START
```

On Windows platforms, you can use PowerShell:
```powershell
PS /home/cli-eaa> $START = (Get-Date -UFormat %s) - 6 * 60 * 60
PS /home/cli-eaa> akamai eaa log access -s $START
```

Send the **user access events** to a file (utf-8 encoding is being used):
```bash
$ akamai eaa log access --tail -o /tmp/eaa_access.log
```

Pull **admin audit events**, block till new logs are received
```bash
$ akamai eaa log admin --tail
```
See [`akamai eaa log` documentation page](docs/commands/akamai-eaa-log.md)

### Applications
Common use cases:

**Find an application**:
```
$ akamai eaa search datascience
app://mD_Pw1XASpyVJc2JwgICTg,Data Science,akdemo-datascience,akdemo-datascience.go.akamai-access.com,4
Found 1 app(s), total 124 app(s)
```
Save an application:
You can save the application locally:
```
$ akamai eaa app app://mD_Pw1XASpyVJc2JwgICTg > ~/eaa_app_datascience_v3.json
```

**Restore the application**:
```
$ cat ~/eaa_app_datascience_v3.json | akamai eaa app app://mD_Pw1XASpyVJc2JwgICTg update
```

Or quickly walk through the JSON tree using `jq`.
```
$ akamai eaa -b app app://mD_Pw1XASpyVJc2JwgICTg | jq .advanced_settings.websocket_enabled
"true"
```

**Delete an application**:
```
akamai eaa app app://mD_Pw1XASpyVJc2JwgICTg delete
```

Deploy an application, you can optionally add a comment to keep track of the change:
```
akamai eaa app app://mD_Pw1XASpyVJc2JwgICTg deploy --comment "[TICKET1234] Update service account credentials"
```

Finding an application using a specific connector name:
*What are the applications using connector `xyz`?*\
Use `jq` and `grep`.\
Note: we use `-b` to avoid the extra info the CLI spills out, like the footer.

```
$ akamai eaa -b search | akamai eaa app - | jq -j '.name, ": ", (.agents[]|.name, " "), "\n"'|grep xyz
```

View groups associated with a particular application:
```
$ akamai eaa app app://FWbUCfpvRKaSOX1rl0u55Q viewgroups
```

You can pipe the command as well, for example to deploy all the application matching your search (eg. "bastion")

```
$ akamai eaa -b search bastion | akamai eaa app - deploy
```

Attach/detach connectors to a particular application:

```
$ akamai eaa app app://app-uuid-1 attach con://connector-uuid-1 con://connector-uuid-2
$ akamai eaa app app://app-uuid-1 detach con://connector-uuid-1 con://connector-uuid-2
```

### Directory operations

**List the configured directories**:

```
$ akamai eaa dir
dir://FuiibQiDQzmC34oBx7INfQ,Cloud Directory,7
dir://2Kz2YqmgSpqT_IJq9BLkWg,ad.akamaidemo.net,108
dir://EX5-YjMyTrKgeWKHrqhUEA,Okta LDAP,10
dir://Ygl1BpAFREiHrA8HR7dFhA,Azure AD,1
```

To view the output in JSON format and in follow mode to consume Directory Health:
See [`akamai eaa app` documentation page](docs/commands/akamai-eaa-app.md).

```
$ akamai eaa dir list --json --tail | jq .name
"Cloud Directory"
"AD Domain AkamaiDemo.net (global)"
"Azure AD (Sync with SCIM)"
"AKDEMO AD with UPN"
```

**Trigger directory synchronization**
### Directory operations

```
$ akamai eaa dir dir://2Kz2YqmgSpqT_IJq9BLkWg sync
Synchronize directory 2Kz2YqmgSpqT_IJq9BLkWg
Directory 2Kz2YqmgSpqT_IJq9BLkWg synchronization requested.
```
See [`akamai eaa log` documentation page](docs/commands/akamai-eaa-dir.md)

### Connectors

Using the shortcut `c` and the `column` command available in most POSIX environment.
When piping, the extra information is written to *stderr* so they appear seperately.
This example shows a short command `akamai eaa c`, replacing `akamai eaa connector list`:

```
$ akamai eaa c | column -t -s,
Total 9 connector(s)
#Connector-id name reachable status version privateip publicip debug
con://cht3_GEjQWyMW9LEk7KQfg demo-v2-con-1-amer 1 1 4.4.0-2765 10.1.4.206 12.123.123.123 Y
con://Wy0Y6FrwQ66yQzLBAInC4w demo-v2-con-2-amer 1 1 4.4.0-2765 10.1.4.172 12.123.123.123 Y
con://dK0f1UvhR7i8-RByABDXaQ demo-v2-con-4-emea 1 1 4.4.0-2765 192.168.1.90 12.123.12.12 N
con://Ihmf51dASo-R1P37hzaP3Q demo-v2-con-3-emea 1 1 4.4.0-2765 192.168.1.235 12.123.12.12 N
con://XiCmu80xQcSWnaeQcvH8Vg demo-v2-con-5-apj 1 1 4.4.0-2765 192.168.1.228 12.123.123.12 Y
con://pkGjL5OgSjyHoymMguvp9Q demo-v2-con-6-apj 1 1 4.4.0-2765 192.168.1.144 12.123.123.12 Y
con://NAWSlptPSXOjq-bk2-EQPw demo-v2-con-10-rus 1 1 4.4.0-2765 10.3.0.101 12.123.123.12 Y
con://e_0nShZBQ7esNAC3ZEkhSQ demo-v2-con-3-amer 1 1 4.4.0-2765 10.1.4.83 12.123.123.123 Y
con://OEe9o-n2S_aMeZpLxgwG0A tmelab-sfo 1 1 4.4.0-2765 192.168.2.101 12.123.123.12 Y
```

To integrate connector health into your monitoring system, use the `--perf` option.
`akamai eaa c list --perf`
This provides 7 extra columns:
- CPU usage (%)
- Memory usage (%)
- Network Traffic (Mbps)
- Total of dialout connections
- Idle dialout connections
- Active dialout connections

To correlate with applications served by each connector, use the `--showapps` argument to include a list of the application FQDNs as an array in the JSON response.

#### Swapping connectors

If you are doing a maintenance on an hypervizor, you may need to swap out 2 connectors.
The current implement look for all the apps, add the new connector, remove the old one.
The application is marked as ready to update.

Caveats (let us know if you need it):
- This doesn't perform swap for directory
- There is no option to automatically redeploy the impacted application after the swap

Example:
```
$ akamai eaa connector con://e_0nShZBQ7esNAC3ZEkhSQ swap con://cht3_GEjQWyMW9LEk7KQfg
#Operation,connector-id,connector-name,app-id,app-name
+,con://cht3_GEjQWyMW9LEk7KQfg,demo-v2-con-1-amer,app://nSFDNGYARHeZGNlweIX7Wg,Speedtest (v2.1)
-,con://e_0nShZBQ7esNAC3ZEkhSQ,demo-v2-con-3-amer,app://nSFDNGYARHeZGNlweIX7Wg,Speedtest (v2.1)
Connector swapped in 1 application(s).
Updated application(s) is/are marked as ready to deploy
```
See [`akamai eaa connector` documentation page](docs/commands/akamai-eaa-connector.md).

### Certificate management

#### Display certificates

The command `cert` displays all the certificate you have configured in EAA, along with the CN and SAN attribute in the `hosts` field, as a `+` separated list.

Example with a wildcard certificate:

```
$ akamai eaa cert | head -n1
#Certificate-ID,cn,type,expiration,days left,hosts
crt://KXi553saQSCeNI1_WH6xuA,*.akamaidemo.net,Custom,2031-06-05T22:56:34,3307,*.akamaidemo.net+akamaidemo.net
```

#### Rotate certificates

The cli-eaa helps with this task with the `akamai eaa certificate` command.

Pass the certificate and key file as parameter with the optional passphrase to replace the existing certificate.
By default, the rotation does NOT redeploy the impacted application or IdP.
To trigger the re-deployment of all impacted applications and IdP, add the ``--deployafter`` flag.

```
$ akamai eaa certificate crt://certificate-UUID rotate --key ~/certs/mycert.key --cert ~/certs/mycert.cert --deployafter
Rotating certificate certificate-UUID...
Certificate CN: *.akamaidemo.net (*.akamaidemo.net Lets Encrypt)
Certificate certificate-UUID updated, 3 application/IdP(s) have been marked ready for deployment.
Deploying application Multi-origin Active-Active Demo (US-East) (app://appid-1)...
Deploying application Multi-origin Active-Active Demo (US-West) (app://appid-2)...
Deploying IdP Bogus IdP to test EME-365 (idp://idpid-1)...
Deployment(s) in progress, it typically take 3 to 5 minutes
Use 'akamai eaa cert crt://certificate-UUID status' to monitor the progress.
```

Check the deployment status:

```bash
$ akamai eaa cert crt://certificate-UUID status
#App/IdP ID,name,status
app://appid-1,Multi-origin Active-Active Demo (US-East),Pending
app://appid-2,Multi-origin Active-Active Demo (US-West),Pending
idp://idpid-1,Bogus IdP to test EME-365,Pending
```
See [`akamai eaa certificate` documentation page](docs/commands/akamai-eaa-certificate.md).

### Device Posture Inventory

Pipe the result of the inventory into `jq` to display only device ID, name and user_id:

```bash
$ akamai eaa dp inventory | jq '.[] | {device_id, device_name, user_id}'
```
See [`akamai eaa dp` documentation page](docs/commands/akamai-eaa-dp.md).

## Known Limitations

Expand Down
43 changes: 41 additions & 2 deletions bin/akamai-eaa
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,48 @@ class ReportingAPI(BaseAPI):
))
cli.footer("%s unique EAA Clients checked-in in the last 30 days" % count)


@staticmethod
def facility_from_popname(pop_name):
"""
Crudly derive the facility based on the POP name.
"""
facility = "AWS"
if "-LIN-" in pop_name:
facility = "Akamai Cloud Compute (formerly Linode)"
return facility

def tenant_info(self):
"""
Display tenant info/stats.
"""
info = {"cloudzones": []}
resp = self.get('mgmt-pop/pops?shared=true')

if self._config.show_usage:
app_apiv3 = ApplicationAPI(self._config, BaseAPI.API_Version.OpenAPIv3)
app_api = ApplicationAPI(self._config, BaseAPI.API_Version.OpenAPI)
idp_api = IdentityProviderAPI(self._config)
app_by_cz = app_apiv3.stats_by_cloudzone()
entdns_by_cz = app_api.entdns_stats_by_cloudzone()
idp_by_pop = idp_api.stats_by_pop()

scanned_cz = []
for eaa_cloudzone in resp.json().get('objects'):
info['cloudzones'].append(eaa_cloudzone.get('region'))
cz_info = {
"name": eaa_cloudzone.get('region'),
"facility": ReportingAPI.facility_from_popname(eaa_cloudzone.get('name')),
}
if self._config.show_usage:
cz_info["count_idp"] = idp_by_pop.get(eaa_cloudzone.get('uuid_url'), 0)
cz_info["count_app"] = app_by_cz.get(eaa_cloudzone.get('region'), 0)
cz_info["count_entdns"] = entdns_by_cz.get(eaa_cloudzone.get('region'), 0)

scanned_cz.append(cz_info)

# sort by Cloud Zone name
info['cloudzones'] = sorted(scanned_cz, key=lambda x: x['name'])

print(dumps(info, indent=4))

def deviceposture_inventory(self, follow=False, interval=300):
Expand Down Expand Up @@ -272,14 +309,16 @@ if __name__ == "__main__":
elif config.command in ("app", "a"):
a = ApplicationAPI(config)
a.process_command()
elif config.command in ("connector", "c"):
elif config.command in ("connector", "c", "con"):
c = ConnectorAPI(config)
perf = hasattr(config, 'perf') and config.perf
if config.action == "swap":
c.swap(config.connector_id, config.new_connector_id, config.dryrun)
elif config.action == "apps":
con_moniker = EAAItem(config.connector_id)
c.list_apps(con_moniker, perf=perf)
elif config.action == "allowlist":
c.allow_list()
else:
# if command is "akamai eaa connector" we default to "list"
# Unless the long form "akamai eaa connector list" is used
Expand Down
19 changes: 17 additions & 2 deletions bin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def __init__(self, config_values, configuration, flags=None):
syncgrp_parser.add_argument("--retry", "-r", type=int, default=0, help=argparse.SUPPRESS)
# New: akamai eaa app xyz add_dnsexception www.abcd.efg
# akamai eaa app xyz del_dnsexception www.abcd.efg

app_parser = subparsers.add_parser('app', aliases=["a"], help='Manage EAA applications')
app_parser.add_argument(dest='application_id', help="Application ID, AppGroup ID or '-'")
subsub = app_parser.add_subparsers(dest="action", help='Application action')
Expand Down Expand Up @@ -161,11 +162,25 @@ def __init__(self, config_values, configuration, flags=None):
# subparsers.required = False
swap_parser = subsub.add_parser("swap", help="Swap connector with another one")
swap_parser.add_argument(dest="new_connector_id", help='New connector ID')
swap_parser.add_argument('--dryrun', dest="dryrun", action="store_true", default=False, help='Dry run mode')
swap_parser.add_argument('--dryrun', dest="dryrun", action="store_true", default=False,
help='Dry run mode')
allowlist_parser = subsub.add_parser("allowlist",
help="Dump EAA Cloud Endpoint for Firewall/Proxy/Network Security equipement")
allowlist_parser.add_argument('--skip-header', dest="skip_header", action="store_true", default=False,
help='Do not print CSV header (first row)')
allowlist_parser.add_argument('--used', dest="only_used", action="store_true", default=False,
help='Show only endpoints being used by your EAA configurations')
allowlist_parser.add_argument('--fqdn', dest="fqdn", action="store_true", default=False,
help='Show Hostname instead of IP/CIDR')
allowlist_parser.add_argument('--since-time', dest="since_time", default=None,
help='Only print endpoints updated after a specific date (RFC3339)')


subparsers.add_parser('idp', aliases=["i"], help='Manage EAA Identity Providers')

subparsers.add_parser('info', help='Display tenant info')
info_parser = subparsers.add_parser('info', help='Display tenant info (cloud zone)')
info_parser.add_argument("--show-usage", dest="show_usage", action="store_true", default=False,
help="Show configuration count using each cloud zone")

dp_parser = subparsers.add_parser('dp', help='Device Posture')
dp_parser.add_argument("dpcommand", choices=['inventory'], default="inventory")
Expand Down
Loading

0 comments on commit f10f28d

Please sign in to comment.