From 0227465e7e8d98010cb470247b94f987f576cbef Mon Sep 17 00:00:00 2001 From: Sebastian Rodriguez Date: Thu, 24 Oct 2024 10:24:34 -0300 Subject: [PATCH] Allow setting the hostname and authN mechanism through a .env file --- .gitignore | 2 ++ README.md | 36 +++++++++++++++++++++++++------ export_audit_trail.py | 50 +++++++++++++++++++++++++++++++++---------- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 28396d0..e974ab6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .DS_Store .vscode/ aux/ +.env +audit_trail_export_*.csv diff --git a/README.md b/README.md index c765919..7838864 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,22 @@ The output is a CSV file containing all the events that matched the query ## Usage -The script requires the `--hostname` parameter to be passed and either a `--jwt` or `--api-key` for authentication. It also accepts optional parameters such as an event name and user information. +The script requires a `Hostname` and either a `JWT` or an `API-Key` for authentication. They can be provided as arguments or can be defined in a `.env` file to be loaded + +Example of the .env file +``` +HOSTNAME= +JWT= +API_KEY= +``` + +It also accepts optional parameters such as an event name and user information. ## Arguments | Argument | Required | Description | |------------------|----------|------------------------------------------------------------------------| -| `--hostname` | Yes | The hostname to connect to. | +| `--hostname` | Yes* | The hostname to connect to. | | `--jwt` | Yes* | The JWT token for authentication. | | `--api-key` | Yes* | The Domino API key for authentication. | | `--event` | No | The event name. | @@ -34,24 +43,39 @@ The script requires the `--hostname` parameter to be passed and either a `--jwt` python3 export_audit_trail.py --hostname https://domino_instance.com --jwt my-jwt-token ``` -### Example 2: Using API key for authentication and specifying an event +### Example 2: Providing the hostname and authentication through the .env file and exporting all available data + +`.env` definition +``` +HOSTNAME= +JWT= +``` + +Calling the script +```bash +python3 export_audit_trail.py +``` + +### Example 3: Using API key for authentication and specifying an event ```bash python3 export_audit_trail.py --hostname https://domino_instance.com --api-key my-api-key --event "Create Dataset" ``` -### Example 3: Providing parameters to filter the export data +### Example 4: Providing parameters to filter the export data ```bash python3 export_audit_trail.py --hostname https://domino_instance.com --jwt my-jwt-token --user_name "Alice" --event "Create Dataset" ``` -### Example 4: Providing start and end timestamps +### Example 5: Providing start and end timestamps ```bash python3 export_audit_trail.py --hostname https://domino_instance.com --jwt my-jwt-token --start_date "2024-10-18 14:10:04" --end_date "2024-10-22 09:04:33" ``` ### Notes * The script runs on Python 3 (Python 2 is not supported) -* If neither --jwt nor --api-key is provided, the script will display an error and exit. +* The hostname and authentication (jwt or api-key) can be defined in an .env file instead of being sent as arguments +* If no hostname is defined, the script will display an error and exit. +* If no authentication mechanism (jwt or api-key) is provided, the script will display an error and exit. * You can combine optional parameters to customize the behavior and context of the export action. * Events are exported in time descending order * The Date & Time of the events is displayed in UTC diff --git a/export_audit_trail.py b/export_audit_trail.py index 31af7ce..e18f7ea 100644 --- a/export_audit_trail.py +++ b/export_audit_trail.py @@ -1,14 +1,21 @@ import argparse import csv -from datetime import datetime, UTC, timezone +from datetime import datetime, timezone +import os import requests import sys #################### AUXILIARY VARIABLES #################### + +ENV_FILE = ".env" +HOSTNAME_ENV = "HOSTNAME" +JWT_ENV = "JWT" +API_KEY_ENV = "API_KEY" + AUDIT_TRAIL_PATH = "api/audittrail/v1/auditevents" BATCH_LIMIT = 1000 -CSV_BASE_FILENAME=f"audit_trail_export_{datetime.now().strftime("%Y-%m-%d:%H-%M-%S")}.csv" +CSV_BASE_FILENAME=f"audit_trail_export_{datetime.now().strftime('%Y-%m-%d:%H-%M-%S')}.csv" # HEADERS UTC_TIMESTAMP = "DATE & TIME (UTC)" @@ -50,12 +57,17 @@ def main(): parser = argparse.ArgumentParser(description="Script that exports Audit trail events") - # Required parameter - parser.add_argument('--hostname', required=True, help="Hostname (required)") - - # Optional parameters - parser.add_argument('--jwt', help="JWT token") - parser.add_argument('--api-key', help="API-Key") + parser.add_argument('--hostname', + help="Hostname. Can be defined in an .env file as HOSTNAME=your-hostname", + default=os.environ.get(HOSTNAME_ENV)) + parser.add_argument('--jwt', + help="JWT token. Can be defined in an .env file as JWT=your-jwt", + default=os.environ.get(JWT_ENV)) + parser.add_argument('--api-key', + help="API-Key. Can be defined in an .env file as API_KEY=your-api-key", + default=os.environ.get(API_KEY_ENV)) + + # Arguments for the filters parser.add_argument('--event', help="Event name") parser.add_argument('--user_name', dest='actorName', help="User name that performed the action") parser.add_argument('--target_name', dest='targetName', help="Object that received the action") @@ -67,8 +79,8 @@ def main(): print("Exporting Audit trail events using the following arguments:") print(f"- Hostname: {args.hostname}") - print(f"- JWT: {"*****" if args.jwt else '-'}") - print(f"- API Key: {"*****" if args.api_key else '-'}") + print(f"- JWT: {'*****' if args.jwt else '-'}") + print(f"- API Key: {'*****' if args.api_key else '-'}") print(f"- Start Date & Time: {args.startTimestamp or '-'}") print(f"- End Date & Time: {args.endTimestamp or '-'}") print(f"- Event: {args.event or '-'}") @@ -77,6 +89,10 @@ def main(): print(f"- Project Name: {args.withinProjectName or '-'}") # Validations and clean-up + if not args.hostname: + print("Error: You must provide the hostname.") + sys.exit(1) + # Ensure either jwt or api-key is provided if not args.jwt and not args.api_key: print("Error: You must provide either a JWT token or an API key.") @@ -100,6 +116,18 @@ def main(): export_audit_trail(args.hostname, request_headers, request_params) +def load_env_file(): + try: + with open(ENV_FILE) as f: + # Use a generator to process lines and filter comments and empty lines + env_vars = (line.strip().split('=', 1) for line in f if line.strip() and not line.startswith('#')) + # Set environment variables + for key, value in env_vars: + os.environ[key] = value + except FileNotFoundError: + print(f"No {ENV_FILE} file found. Skipping loading environment variables") + + def validate_and_format_timestamp(raw_timestamp): try: parsed_start_timestamp = datetime.strptime(raw_timestamp, "%Y-%m-%d %H:%M:%S") @@ -196,7 +224,7 @@ def parse_event(raw_event): COMMAND: None, } - parsed_event[UTC_TIMESTAMP] = datetime.fromtimestamp(raw_event['timestamp'] / 1000, UTC).strftime('%Y-%m-%d %H:%M:%S') + parsed_event[UTC_TIMESTAMP] = datetime.fromtimestamp(raw_event['timestamp'] / 1000, timezone.utc).strftime('%Y-%m-%d %H:%M:%S') actor_data = raw_event.get('actor', {}) parsed_event[USER_NAME] = actor_data.get('name', actor_data.get('id'))