Skip to content

Commit

Permalink
- Handle UA prefix
Browse files Browse the repository at this point in the history
- Improves argument parsing when argument missing
- Improve inline help
- Bump to 0.0.4
  • Loading branch information
bitonio committed Jun 7, 2021
1 parent b72533b commit 86826b0
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 59 deletions.
129 changes: 71 additions & 58 deletions bin/akamai-mfa
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import os
import json


__VERSION__ = "0.0.3"
__VERSION__ = "0.0.4"
LOG_FMT = '%(asctime)s [%(levelname)s] %(threadName)s %(message)s'
MOST_RECENT_PADDING = 30

Expand All @@ -48,6 +48,8 @@ mfa_api_url = "https://mfa.akamai.com"
mfa_api_ver = "v1"
tail_pull_interval = 60 # Default is 60
page_size = 10 # default is 1000
epilog = '''Copyright (C) Akamai Technologies, Inc\n''' \
'''Visit http://github.com/akamai/cli-mfa for detailed documentation'''


class MFAConfig():
Expand All @@ -67,13 +69,15 @@ class MFAConfig():

# 1. Scan parameters from the CLI arguments

parser = argparse.ArgumentParser(prog="akamai mfa",
description='Process command line options.')
self.parser = argparse.ArgumentParser(prog="akamai mfa", epilog=epilog,
description='Process command line options.',
formatter_class=argparse.RawTextHelpFormatter)

subparsers = parser.add_subparsers(dest='command', help='Main command')
subparsers = self.parser.add_subparsers(dest='command', help='Main command')
cmdparser = subparsers.add_parser('version', help="Display CLI-MFA version")
eventparser = subparsers.add_parser('event', help="Dump MFA events")
eventparser.add_argument("event_type", choices=['policy', 'auth'], default='policy', help="Event type")
eventparser.add_argument("event_type", choices=['policy', 'auth'], nargs='?', const='event_type',
default='auth', help="MFA event type, default is 'auth'")
eventparser.add_argument("--start", "-s", default=None, type=int, help="Scan for events after this epoch")
eventparser.add_argument("--end", "-e", default=None, type=int, help="Scan for events before this epoch")
eventparser.add_argument("--tail", "-f", default=False, action="store_true",
Expand All @@ -82,14 +86,15 @@ class MFAConfig():
eventparser.add_argument("--noreceipt", default=False, action="store_true",
help="Discard the receipt attribute to save log space")

parser.add_argument("--edgerc", type=argparse.FileType('r'), default=os.path.expanduser("~/.edgerc"),
help='Location of the credentials file (default is %s)' % os.path.expanduser("~/.edgerc"))
self.parser.add_argument("--edgerc", type=argparse.FileType('r'), default=os.path.expanduser("~/.edgerc"),
help='Location of the credentials file (default is %s)' % os.path.expanduser("~/.edgerc"))

parser.add_argument("--section", default="default", help="Section inside .edgerc, default is [default]")
parser.add_argument("--debug", '-d', action="store_true", default=False, help="Debug mode")
self.parser.add_argument("--section", default="default", help="Section inside .edgerc, default is [default]")
self.parser.add_argument("--debug", '-d', action="store_true", default=False, help="Debug mode")
self.parser.add_argument('--user-agent-prefix', dest='ua_prefix', default='Akamai-CLI', help=argparse.SUPPRESS)

try:
scanned_cli_args = parser.parse_args()
scanned_cli_args = self.parser.parse_args()
cli_args = vars(scanned_cli_args)
for option in cli_args:
setattr(self, option, cli_args[option])
Expand Down Expand Up @@ -123,6 +128,9 @@ class MFAConfig():
if not hasattr(self, 'mfa_signing_key'):
raise RuntimeError("Missing mfa_signing_key")

def display_help(self):
self.parser.print_help()


class AkamaiMFAAuth(requests.auth.AuthBase):
"""
Expand Down Expand Up @@ -165,55 +173,60 @@ if __name__ == "__main__":
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

if config.command is None:
config.display_help()
sys.exit(1)
if config.command == "version":
print(__VERSION__)
sys.exit(0)
elif config.command == 'event':
session = requests.Session()
session.headers.update({'User-Agent': f'{config.ua_prefix} cli-mfa/{__VERSION__}'})
session.auth = AkamaiMFAAuth(config)

if config.event_type == 'auth':
api_report_type = 'auths'
elif config.event_type == 'policy':
api_report_type = 'policies'

api_url = f'{mfa_api_url}/api/{mfa_api_ver}/control/reports/{api_report_type}'
scan_end = datetime.datetime.utcnow() - datetime.timedelta(seconds=MOST_RECENT_PADDING)
scan_start = scan_end - datetime.timedelta(minutes=5)
if config.end:
scan_end = datetime.datetime.utcfromtimestamp(config.end)
if config.start:
scan_start = datetime.datetime.utcfromtimestamp(config.start)


while True:
loop_start = time.time()
page = 1
page_count = None
while page_count is None or page <= page_count:
params = {
'after': scan_start.isoformat(),
'before': scan_end.isoformat(),
'page_size': page_size,
'page': page
}
r = session.get(api_url, params=params)
page += 1
page_count = r.json().get('result', {}).get('total_page_count')
for mfa_event in r.json().get('result', {}).get('page'):
if config.noreceipt:
mfa_event.pop('receipt')
print(json.dumps(mfa_event))
sys.stdout.flush()

if config.tail:
wait = tail_pull_interval - (time.time() - loop_start)
logging.debug("Wait %s sec..." % wait)
time.sleep(wait)
scan_start = scan_end # next iteration we stich, start is the previous end
scan_end = datetime.datetime.utcnow() - datetime.timedelta(seconds=MOST_RECENT_PADDING)

else:
break
else:
raise ValueError(f"Unsupported command: {config.command}")

session = requests.Session()
session.headers.update({'User-Agent': f'cli-mfa/{__VERSION__}'})
session.auth = AkamaiMFAAuth(config)


if config.event_type == 'auth':
api_report_type = 'auths'
elif config.event_type == 'policy':
api_report_type = 'policies'

api_url = f'{mfa_api_url}/api/{mfa_api_ver}/control/reports/{api_report_type}'
scan_end = datetime.datetime.utcnow() - datetime.timedelta(seconds=MOST_RECENT_PADDING)
scan_start = scan_end - datetime.timedelta(minutes=5)
if config.end:
scan_end = datetime.datetime.utcfromtimestamp(config.end)
if config.start:
scan_start = datetime.datetime.utcfromtimestamp(config.start)


while True:
loop_start = time.time()
page = 1
page_count = None
while page_count is None or page <= page_count:
params = {
'after': scan_start.isoformat(),
'before': scan_end.isoformat(),
'page_size': page_size,
'page': page
}
r = session.get(api_url, params=params)
page += 1
page_count = r.json().get('result', {}).get('total_page_count')
for mfa_event in r.json().get('result', {}).get('page'):
if config.noreceipt:
mfa_event.pop('receipt')
print(json.dumps(mfa_event))
sys.stdout.flush()

if config.tail:
wait = tail_pull_interval - (time.time() - loop_start)
logging.debug("Wait %s sec..." % wait)
time.sleep(wait)
scan_start = scan_end # next iteration we stich, start is the previous end
scan_end = datetime.datetime.utcnow() - datetime.timedelta(seconds=MOST_RECENT_PADDING)

else:
break
2 changes: 1 addition & 1 deletion cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"commands": [
{
"name": "mfa",
"version": "0.0.3",
"version": "0.0.4",
"description": "Akamai CLI for MFA"
}
]
Expand Down

0 comments on commit 86826b0

Please sign in to comment.