import win32evtlog import json import requests import os import sys import logging from datetime import datetime # File to store the last processed record number LAST_PROCESSED_FILE = 'last_processed_record.txt' # Splunk HEC configuration SPLUNK_HEC_TOKEN = 'xxxxxxxxxxx' SPLUNK_HEC_URL = 'https://172.31.1.245:8088/services/collector/event' # Configuration server = 'localhost' log_name = 'Data Security Essentials' source_names = ['Superna Data Security Essentials BOT Service', 'Superna Data Security Policy Engine'] trigger_severities = ['MAJOR', 'CRITICAL'] # Adjust as needed def setup_logging(): script_directory = os.path.dirname(os.path.abspath(__file__)) log_file_path = os.path.join(script_directory, "splunk-dse.log") logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(log_file_path, mode='w'), logging.StreamHandler(sys.stdout) ]) logging.info(f"Script run on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") logging.info(f"Logging to file: {log_file_path}") def get_last_processed_record(): if os.path.exists(LAST_PROCESSED_FILE): try: with open(LAST_PROCESSED_FILE, 'r') as f: lines = f.readlines() if len(lines) >= 2: last_record = int(lines[0].strip()) last_time_and_event_id = lines[1].strip() logging.info(f"Loaded last processed record: {last_record}, {last_time_and_event_id}") return last_record, last_time_and_event_id except Exception as e: logging.error(f"Error reading {LAST_PROCESSED_FILE}: {e}") logging.info(f"No last processed record file found. Starting fresh.") return 0, None def save_last_processed_record(record_number, event_time, event_id): try: with open(LAST_PROCESSED_FILE, 'w') as f: f.write(f"{record_number}\n") f.write(f"{event_time} | EventID: {event_id}\n") logging.info(f"Saved last processed record: {record_number}, {event_time}, EventID: {event_id}") except Exception as e: logging.error(f"Error saving {LAST_PROCESSED_FILE}: {e}") def send_to_splunk(event_json): """Send a structured payload to Splunk via HEC.""" splunk_event = { "sourcetype": "supernaZT", "event": { "user": event_json.get("user"), "state": event_json.get("state"), "userName": event_json.get("userName"), "protocol": event_json.get("protocol"), "eventSource": event_json.get("eventSource"), "numFiles": event_json.get("numFiles"), "nes": event_json.get("nes"), "detected": event_json.get("detected"), "clientIPs": event_json.get("clientIPs"), "shares": event_json.get("shares"), "files": event_json.get("files"), # Add more fields as needed } } headers = { 'Authorization': f'Splunk {SPLUNK_HEC_TOKEN}', 'Content-Type': 'application/json' } try: response = requests.post(SPLUNK_HEC_URL, headers=headers, data=json.dumps(splunk_event), verify=False) response.raise_for_status() logging.info("Successfully sent event to Splunk.") except requests.RequestException as e: logging.error(f"Failed to send event to Splunk: {e}") def collect_windows_event_log(server, log_name, source_names): logging.info(f"Collecting Windows Event Logs from {log_name} on server {server}...") h = win32evtlog.OpenEventLog(server, log_name) flags = win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ last_processed_record, last_time_and_event_id = get_last_processed_record() latest_record = last_processed_record latest_event_time = None latest_event_id = None try: while True: events = win32evtlog.ReadEventLog(h, flags, 0) if not events: break for event in events: record_number = event.RecordNumber event_time = event.TimeGenerated.Format() event_id = event.EventID & 0xFFFF if record_number <= last_processed_record: continue if event.SourceName not in source_names: continue logging.info(f"Processing Event - RecordNumber: {record_number}, EventID: {event_id}, TimeGenerated: {event_time}, Source: {event.SourceName}") try: if event.Data: data_content = event.Data.decode('utf-8', errors='replace') logging.debug(f"Raw JSON Payload: {data_content}") try: event_json = json.loads(data_content) logging.debug(f"Parsed JSON: {json.dumps(event_json, indent=2)}") severity = event_json.get('severity') if severity not in trigger_severities: logging.info(f"Event severity '{severity}' does not match filter. Skipping.") continue send_to_splunk(event_json) except json.JSONDecodeError as e: logging.error(f"JSON parsing failed: {e}") except Exception as e: logging.warning(f"Event processing failed: {e}") latest_record = max(latest_record, record_number) latest_event_time = event_time latest_event_id = event_id finally: win32evtlog.CloseEventLog(h) if latest_event_time and latest_event_id: save_last_processed_record(latest_record, latest_event_time, latest_event_id) def main(): setup_logging() collect_windows_event_log(server, log_name, source_names) if __name__ == "__main__": main()