Claude 24f816b6a3
Consolidate 22 sibling repos into layered organism structure
Place useful parts of the surrounding repos into sica-fondt by layer, per the
body model (Ada = membrane; brain/endocrine/capabilities/knowledge non-Ada):

- brain/        LLM reasoning + providers (dapr, hermes, MoMoA)
- capabilities/ REPRAG sidecars: hermes tools/skills, dapr tools, parallel
                dispatch, A51 channels, and the OSINT cluster
- knowledge/    LORAG corpus: 754 cyber-skills, agency personas, secure-coding,
                MITRE ATT&CK data
- reference/    defensive threat-reference (C3, shhbruh doc) + AdaYaml parser

License handling: AGPL sources (worldosint, advanced_evolution, mercury,
Reticulum) and GPL DeTTECT are SPEC-only clean-room/port descriptions — no
copyleft code copied. MIT/Apache/data parts copied as working trees.

Safety: shhbruh escape/persistence material and C3 covert-C2 kept as reference
only, not wired into the running organism. See CONSOLIDATION.md.

https://claude.ai/code/session_01UehUqEXXJJCsHoA4voCU5c
2026-06-10 06:53:01 +00:00

171 lines
6.5 KiB
Python

#!/usr/bin/env python3
"""Threat intelligence enrichment pipeline for Splunk.
Manages threat intel lookups, KV store collections, and modular inputs
for enriching Splunk events with IOC context from MISP, OTX, and CSV feeds.
"""
import json
import csv
import datetime
import io
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
SPLUNK_TI_COLLECTIONS = {
"ip_intel": {
"fields": ["ip", "threat_key", "description", "source", "weight", "time"],
"lookup_name": "ip_intel_lookup",
},
"domain_intel": {
"fields": ["domain", "threat_key", "description", "source", "weight", "time"],
"lookup_name": "domain_intel_lookup",
},
"file_intel": {
"fields": ["file_hash", "file_name", "threat_key", "description", "source", "weight", "time"],
"lookup_name": "file_intel_lookup",
},
"email_intel": {
"fields": ["src_user", "threat_key", "description", "source", "weight", "time"],
"lookup_name": "email_intel_lookup",
},
}
def fetch_otx_pulse_iocs(pulse_id):
"""Fetch IOCs from AlienVault OTX pulse."""
if not HAS_REQUESTS:
return {"error": "requests not installed"}
url = "https://otx.alienvault.com/api/v1/pulses/{}/indicators".format(pulse_id)
try:
resp = requests.get(url, timeout=15)
if resp.status_code == 200:
data = resp.json()
iocs = []
for ind in data.get("results", []):
iocs.append({
"type": ind.get("type", ""),
"indicator": ind.get("indicator", ""),
"title": ind.get("title", ""),
"created": ind.get("created", ""),
})
return {"pulse_id": pulse_id, "count": len(iocs), "indicators": iocs}
return {"error": "HTTP {}".format(resp.status_code)}
except Exception as e:
return {"error": str(e)}
def convert_iocs_to_splunk_lookup(iocs, collection_type="ip_intel"):
"""Convert IOC list to Splunk KV store format."""
collection = SPLUNK_TI_COLLECTIONS.get(collection_type, SPLUNK_TI_COLLECTIONS["ip_intel"])
rows = []
now = datetime.datetime.utcnow().isoformat() + "Z"
for ioc in iocs:
if collection_type == "ip_intel" and ioc.get("type") in ("IPv4", "IPv6"):
rows.append({
"ip": ioc["indicator"],
"threat_key": ioc.get("title", "malicious_ip"),
"description": "OTX: " + ioc.get("title", ""),
"source": "otx",
"weight": "3",
"time": now,
})
elif collection_type == "domain_intel" and ioc.get("type") in ("domain", "hostname"):
rows.append({
"domain": ioc["indicator"],
"threat_key": ioc.get("title", "malicious_domain"),
"description": "OTX: " + ioc.get("title", ""),
"source": "otx",
"weight": "3",
"time": now,
})
elif collection_type == "file_intel" and ioc.get("type") in ("FileHash-SHA256", "FileHash-MD5"):
rows.append({
"file_hash": ioc["indicator"],
"file_name": "",
"threat_key": ioc.get("title", "malicious_file"),
"description": "OTX: " + ioc.get("title", ""),
"source": "otx",
"weight": "3",
"time": now,
})
return {"collection": collection_type, "lookup_name": collection["lookup_name"], "row_count": len(rows), "rows": rows}
def generate_splunk_lookup_csv(rows, output_path=None):
"""Generate CSV file for Splunk lookup table."""
if not rows:
return ""
output = io.StringIO()
writer = csv.DictWriter(output, fieldnames=rows[0].keys())
writer.writeheader()
writer.writerows(rows)
csv_content = output.getvalue()
if output_path:
with open(output_path, "w", encoding="utf-8") as f:
f.write(csv_content)
return csv_content
def build_spl_correlation_search(collection_type="ip_intel"):
"""Build SPL query for threat intelligence correlation."""
queries = {
"ip_intel": (
'| tstats summariesonly=t count from datamodel=Network_Traffic '
'by All_Traffic.dest_ip '
'| rename All_Traffic.dest_ip as ip '
'| lookup ip_intel_lookup ip OUTPUT threat_key description source '
'| where isnotnull(threat_key) '
'| table ip threat_key description source count'
),
"domain_intel": (
'| tstats summariesonly=t count from datamodel=Network_Resolution '
'by DNS.query '
'| rename DNS.query as domain '
'| lookup domain_intel_lookup domain OUTPUT threat_key description source '
'| where isnotnull(threat_key) '
'| table domain threat_key description source count'
),
"file_intel": (
'index=endpoint sourcetype=sysmon EventCode=1 '
'| lookup file_intel_lookup file_hash as Hashes OUTPUT threat_key description '
'| where isnotnull(threat_key) '
'| table _time Computer Image Hashes threat_key description'
),
}
return queries.get(collection_type, "| makeresults | eval error=\"Unknown collection\"")
if __name__ == "__main__":
print("=" * 60)
print("Threat Intelligence Enrichment in Splunk")
print("KV store collections, lookup tables, SPL correlation")
print("=" * 60)
print(" requests available: {}".format(HAS_REQUESTS))
print("\n--- Splunk TI Collections ---")
for name, info in SPLUNK_TI_COLLECTIONS.items():
print(" {}: lookup={}, fields={}".format(name, info["lookup_name"], len(info["fields"])))
print("\n--- SPL Correlation Queries ---")
for ctype in ["ip_intel", "domain_intel", "file_intel"]:
spl = build_spl_correlation_search(ctype)
print(" [{}] {}...".format(ctype, spl[:80]))
demo_iocs = [
{"type": "IPv4", "indicator": "198.51.100.42", "title": "C2 Server"},
{"type": "domain", "indicator": "evil.example.com", "title": "Phishing Domain"},
{"type": "FileHash-SHA256", "indicator": "a" * 64, "title": "Malware Sample"},
]
for ctype in ["ip_intel", "domain_intel", "file_intel"]:
result = convert_iocs_to_splunk_lookup(demo_iocs, ctype)
if result["row_count"] > 0:
print("\n Converted {} IOCs to {} format".format(result["row_count"], ctype))
print("\n" + json.dumps({"collections_configured": len(SPLUNK_TI_COLLECTIONS)}, indent=2))