#!/usr/bin/env python import sys import os import requests import time import json import subprocess from datetime import datetime # Debug log file DEBUG_LOG = "/opt/splunk/var/log/socradar/status_update_log.txt" def log_debug(msg): os.makedirs(os.path.dirname(DEBUG_LOG), exist_ok=True) with open(DEBUG_LOG, 'a') as f: f.write(f"[{datetime.now()}] {msg}\n") # Simple version that outputs CSV directly print("alarm_id,status,result,message,time") try: log_debug("=== NEW STATUS UPDATE REQUEST ===") # Read all input input_lines = [] for line in sys.stdin: input_lines.append(line.strip()) log_debug(f"Input lines: {input_lines}") # Parse alarm_id and new_status from input alarm_id = "" new_status = "" for line in input_lines: if "alarm_id=" in line: parts = line.split(',') for part in parts: if 'alarm_id=' in part: alarm_id = part.split('=', 1)[1].strip().strip('"') elif 'new_status=' in part: new_status = part.split('=', 1)[1].strip().strip('"') log_debug(f"Parsed: alarm_id={alarm_id}, new_status={new_status}") if not alarm_id: print("NONE,No alarm selected,WAITING,Enter an alarm ID," + str(int(time.time()))) sys.exit(0) # Get credentials conf_file = "/opt/splunk/etc/apps/TA-socradar-incidents/local/inputs.conf" company_id = None api_key = None if os.path.exists(conf_file): with open(conf_file, 'r') as f: for line in f: line = line.strip() if line.startswith('socradar_company_id'): company_id = line.split('=', 1)[1].strip() elif line.startswith('socradar_api_key'): api_key = line.split('=', 1)[1].strip() if not company_id or not api_key: log_debug("Missing credentials") print(f"{alarm_id},Error,ERROR,Missing credentials," + str(int(time.time()))) sys.exit(0) # Status mapping status_map = { '0': 'Open', '1': 'OnHold-Investigating', '2': 'Closed-Resolved', '3': 'OnHold-Pending', '5': 'OnHold-Legal', '9': 'Closed-FalsePositive', '10': 'Closed-Duplicate', '11': 'Closed-ProcessedInternally', '12': 'Closed-Mitigated', '13': 'Closed-NotApplicable' } status_name = status_map.get(new_status, f'Status-{new_status}') # Make API call url = f"https://platform.socradar.com/api/company/{company_id}/alarms/status/change?key={api_key}" payload = { "status": new_status, "alarm_ids": alarm_id, "comments": f"Updated via Splunk to: {status_name}" } log_debug(f"Calling API: {url[:50]}...") log_debug(f"Payload: {payload}") response = requests.post(url, json=payload, headers={"Content-Type": "application/json"}, timeout=30) response_data = response.json() log_debug(f"API Response: {response.status_code} - {response_data}") if response.status_code == 200 and response_data.get('is_success', False): print(f"{alarm_id},{status_name},SUCCESS,Updated successfully," + str(int(time.time()))) # Map status to SOCRadar API format api_status_map = { 'Open': 'OPEN', 'OnHold-Investigating': 'INVESTIGATING', 'Closed-Resolved': 'RESOLVED', 'OnHold-Pending': 'PENDING_INFO', 'OnHold-Legal': 'LEGAL', 'Closed-FalsePositive': 'FALSE_POSITIVE', 'Closed-Duplicate': 'DUPLICATE', 'Closed-ProcessedInternally': 'PROCESSED_INTERNALLY', 'Closed-Mitigated': 'MITIGATED', 'Closed-NotApplicable': 'NOT_APPLICABLE' } api_status = api_status_map.get(status_name, status_name) # Update checkpoint try: checkpoint_file = "/opt/splunk/var/lib/splunk/modinputs/socradar_incidents_collector/deneme_002_socradar_v4_processed_alarms" if os.path.exists(checkpoint_file): with open(checkpoint_file, 'r') as f: checkpoint_data = json.load(f) if 'alarm_status' in checkpoint_data: checkpoint_data['alarm_status'][str(alarm_id)] = api_status checkpoint_data['last_updated'] = datetime.now().isoformat() with open(checkpoint_file, 'w') as f: json.dump(checkpoint_data, f) log_debug(f"Updated checkpoint: {alarm_id} -> {api_status}") except Exception as e: log_debug(f"Checkpoint update error: {e}") # Index the status change immediately using REST API try: log_debug("Attempting to index status change...") # Create event event = { "time": time.time(), "host": "socradar", "source": "status_update", "sourcetype": "socradar:incidents", "index": "socradar_incidents", "event": json.dumps({ "alarm_id": alarm_id, "status": api_status, "alarm_status": api_status, "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "update_source": "manual_status_update", "_time": time.time() }) } # Use Splunk REST API to index import urllib.request import urllib.parse import base64 # Use HTTP Event Collector endpoint with index specification url = "https://localhost:8089/services/receivers/simple?index=socradar_incidents&sourcetype=socradar:incidents" data = event['event'] # Create request req = urllib.request.Request( url, data=data.encode('utf-8'), headers={ 'Authorization': 'Basic ' + base64.b64encode(b'admin:123456789').decode('ascii'), 'Content-Type': 'application/json' } ) # Disable SSL verification for localhost import ssl ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE # Send request with urllib.request.urlopen(req, context=ctx) as response: result = response.read().decode('utf-8') log_debug(f"Index result: {result}") except Exception as e: log_debug(f"Indexing error: {e}") # Fallback to oneshot try: # Get the full alarm data from collector's last run event_data = { "alarm_id": alarm_id, "status": api_status, "alarm_status": api_status, "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "update_source": "manual_status_update", "_time": time.time(), "alarm_type": "incident", "alarm_risk_level": "UNKNOWN" } event_json = json.dumps(event_data) cmd = ['/opt/splunk/bin/splunk', 'add', 'oneshot', '-', '-sourcetype', 'socradar:incidents', '-index', 'socradar_incidents', '-auth', 'admin:123456789'] proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate(input=event_json.encode()) log_debug(f"Oneshot result: {proc.returncode}, stdout: {stdout}, stderr: {stderr}") except Exception as e2: log_debug(f"Oneshot error: {e2}") else: msg = response_data.get('message', 'Update failed').replace(',', ';') print(f"{alarm_id},{status_name},FAILED,{msg}," + str(int(time.time()))) log_debug(f"Update failed: {msg}") except Exception as e: log_debug(f"EXCEPTION: {e}") print(f"ERROR,Error,ERROR,{str(e).replace(',', ';')}," + str(int(time.time())))