Introduction

Important: Please be advised that the information in this article is for legacy reference only, and should not be utilized as the primary source of examples. Please contact Support to access the most up-to-date Log Extract package.


Sample code provided below is for reference only. Authentic8 strongly encourages you to develop your own custom scripts using the language and coding practices best suited for your organization. Logs are stored in the Authentic8 database, and can be manually exported from the Logs section of the Admin Console or programmatically via the Log Extract API.

 

An Authentication Token is a security credential required for programmatic access to the Log Extract API. Authentication tokens are issued by the Authentic8 Support team. Please have your organizations Silo Administrator reach out to Support to obtain a Log Extract API token.


Important: Effective March 30 2020, Authentic8 endpoints will only support TLS 1.2 connections and will cease support for TLS 1.1. If you use one of our native applications, please ensure their version meets the minimum requirement to support TLS 1.2. Any in-line network infrastructure connecting to our servers must also be configured to use TLS 1.2 



Log Extraction Reference (Unencrypted Logs)

For samples scripts below to extract clear test logs, the parameters are:

  • -o 'org name'

  • -t 'auth token file'

  • -i <start_sequence_id>

  • -I <end_sequence_id>

  • -d <start date>

  • -D <end date>

 

One of -i or -d is used to specify the starting point of the log extraction. Optionally, -I or -D can be used to specify the end point of the log extraction.  It is strongly recommended that the sequence id is used to determine the log records retrieved to avoid any data loss or duplication


Supported Log Types are: URL, DOWNLOAD, UPLOAD, SESSION, AUTH (authentication logs for Silo session ONLY), ADMIN_AUDIT, LOCATION CHANGE, BLOCKED URL, TRANSLATION, & A8SS

 

The result is a JSON object, which has three keys at the top level

  • is_more: a boolean which is true if more log files are available

  • next_seq: a sequence number to use with -i for the next set of log files

  • logs: a list of JSON objects representing the log lines.

 

cURL Log Extract Example for Clear Text logs:

curl -k -X POST https://extapi.authentic8.com/api/ \
     -H "Content-Type: application/json" \
     -d '[
          {"command": "setauth", "data": "<auth_token>"},
          {"command": "extractlog", "start_seq": 0, "org": "<org_name>", "type": "URL"}
        ]'


Python 3.x Log Extract for Clear Text logs (Reference Only):

import json
import sys
import urllib.request
import urllib.error
import urllib.parse
from getopt import getopt

def usage_abort(extra=''):
    sys.exit(extra + '''

Usage: log_extract -o <org_name> -t <auth_token_file>
                  [ -i <start id> | -d <start date> ]
                  [ -I <end id> | -D <end date> ]

Example:
log_extract -o "org_name" -t auth.txt -d "2025-01-01 12:00:00"''')

opt_array, args = getopt(sys.argv[1:], 'd:i:D:I:l:o:t:')

if args:
    usage_abort(' '.join(args) + ' would be ignored')

opts = dict(opt_array)

ea_host = 'extapi.authentic8.com'

if '-o' in opts:
    org = opts['-o']
else:
    usage_abort('Missing org')

cmd = {
    'command': 'extractlog',
    'org': org,
    'type': 'URL'
}

if '-i' in opts:
    cmd['start_seq'] = int(opts['-i'])
if '-d' in opts:
    cmd['start_time'] = opts['-d']
if '-I' in opts:
    cmd['end_seq'] = int(opts['-I'])
if '-D' in opts:
    cmd['end_time'] = opts['-D']
if not ('start_seq' in cmd or 'start_time' in cmd):
    cmd['start_seq'] = 0
if '-l' in opts:
    cmd['limit'] = int(opts['-l'])

with open(opts['-t'], 'r', encoding='utf-8') as t:
    auth_data = t.read().strip()

auth_cmd = {
    'command': 'setauth',
    'data': auth_data
}

req_data = json.dumps([auth_cmd, cmd]).encode('utf-8')
req = urllib.request.Request(
    f'https://{ea_host}/api/',
    data=req_data,
    headers={'Content-Type': 'application/json'}
)

try:
    with urllib.request.urlopen(req) as reader:
        res = json.loads(reader.read().decode('utf-8'))
except urllib.error.URLError as e:
    sys.exit(f"Error: {e}")

assert len(res) == 2

if 'result' in res[1]:
    print(json.dumps(res[1]['result'], indent=2, ensure_ascii=False))
else:
    print('Failure')
    import pprint
    pprint.pprint(res[1].get('error', {}))



Log Extraction (Encrypted Logs)

Extracting and decrypting encrypted logs requires configuring a log encryption policy within Authentic8, and uses the free SECCURE ECC public key encryption toolset, which is licensed under the GNU Lesser General Public License v3 (LGPL).  

 

Source packages and documentations can be found at: http://point-at-infinity.org/seccure/

 

Also see the installation instructions for the Python SECCURE library at:

https://github.com/bwesterb/py-seccure

 

General Log Encryption information is available here for review.

 

The following are the parameters for the sample scripts below:

  • -o 'org name'

  • -t 'auth token file'

  • -p 'passphrase file'

  • -i <start_sequence_id>

  • -I <end_sequence_id>

  • -d <start date>

  • -D <end date>

 

One of -i or -d is used to specify the starting point of the log extraction.  Optionally, -I or -D can be used to specify the end point of the log extraction.

 

Supported Log Type is ENC for encrypted logs.

 

After extraction and decryption, the regular Authentic8 log types (AUTH, SESSION, etc) may be identified, as well as additional POST DATA and  COOKIES log types. POST DATA and COOKIES log types are only available when using log encryption.

 

The result is a JSON object, which has three keys at the top level

  • is_more: a boolean which is true if more log files are available

  • next_seq: a number to use with -i for the next set of log files

  • logs: a list of JSON objects representing the log lines.

 

cURL Log Extract Example for Encrypted logs:

curl -k -X POST https://extapi.authentic8.com/api/ \
     -H "Content-Type: application/json" \
     -d '[
          {"command": "setauth", "data": "<AuthToken>"},
          {"command": "extractlog", "start_seq": 0, "org": "<OrgName>", "type": "ENC"}
        ]'

Best Practice: For Windows systems, Cygwin can be installed in order to utilize the cURL command-line tool.

 

Python 3.x Log Extract for Encrypted logs (Reference Only): 

#!/usr/bin/env python3

import base64
import json
import sys
import urllib.request
import urllib.error
import urllib.parse
import argparse
import seccure

def usage_abort(extra=''):
    sys.exit(extra + '''\n
Usage: enc_log_extract -o <org name> -t <auth token file> -p <passphrase file>
                  [ -i <start id> | -d <start date> ]
                  [ -I <end id> | -D <end date> ]

Example:

enc_log_extract -o "Customer org" -t auth.txt -p pass.txt -d "2014-04-01 14:00:00"''')

# Argument parsing
parser = argparse.ArgumentParser()
parser.add_argument('-o', required=True, help='Organization name')
parser.add_argument('-t', required=True, help='Auth token file')
parser.add_argument('-p', required=True, help='Passphrase file')
parser.add_argument('-i', type=int, help='Start ID')
parser.add_argument('-d', help='Start date')
parser.add_argument('-I', type=int, help='End ID')
parser.add_argument('-D', help='End date')
parser.add_argument('-l', type=int, help='Limit')

args = parser.parse_args()

ea_host = 'extapi.authentic8.com'

# Construct command
cmd = {
    'command': 'extractlog',
    'org': args.o,
    'type': 'ENC'
}

if args.i:
    cmd['start_seq'] = args.i
if args.d:
    cmd['start_time'] = args.d
if args.I:
    cmd['end_seq'] = args.I
if args.D:
    cmd['end_time'] = args.D
if 'start_seq' not in cmd and 'start_time' not in cmd:
    cmd['start_seq'] = 0
if args.l:
    cmd['limit'] = args.l

# Read authentication token
with open(args.t, 'r', encoding='utf-8') as t:
    auth_cmd = {
        'command': 'setauth',
        'data': t.read().strip()
    }

# Read passphrase
with open(args.p, 'r', encoding='utf-8') as p:
    passphrase = p.read().strip()

# Send request
req = urllib.request.Request(
    f'https://{ea_host}/api/',
    data=json.dumps([auth_cmd, cmd]).encode('utf-8'),
    headers={'Content-Type': 'application/json'}
)

try:
    with urllib.request.urlopen(req) as response:
        res = json.load(response)
except urllib.error.URLError as e:
    sys.exit(f'Error connecting to API: {e}')

assert len(res) == 2

if 'result' in res[1]:
    for l in res[1]['result']['logs']:
        l['clear'] = json.loads(
            seccure.decrypt(base64.b64decode(l['enc']), passphrase, curve='secp256r1/nistp256')
        )
    print(json.dumps(res[1]['result'], indent=2, ensure_ascii=False))
else:
    print('Failure')
    import pprint
    pprint.pprint(res[1]['error'])



Please contact Support for any questions, or if you require additional information.