loghunter-cli 0.1.0.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. loghunter/__init__.py +3 -0
  2. loghunter/cli.py +1108 -0
  3. loghunter/cli_init.py +567 -0
  4. loghunter/common/__init__.py +1 -0
  5. loghunter/common/allowlist.py +436 -0
  6. loghunter/common/clustering.py +326 -0
  7. loghunter/common/config.py +221 -0
  8. loghunter/common/display.py +323 -0
  9. loghunter/common/errors.py +45 -0
  10. loghunter/common/finding.py +239 -0
  11. loghunter/common/loader/__init__.py +136 -0
  12. loghunter/common/loader/diagnostics.py +94 -0
  13. loghunter/common/loader/discovery.py +335 -0
  14. loghunter/common/loader/io.py +76 -0
  15. loghunter/common/loader/pipeline.py +1010 -0
  16. loghunter/common/loader/sniff.py +184 -0
  17. loghunter/common/loader/types.py +207 -0
  18. loghunter/common/loader/windowing.py +523 -0
  19. loghunter/common/output.py +93 -0
  20. loghunter/common/paths.py +105 -0
  21. loghunter/common/sources.py +392 -0
  22. loghunter/data/allowlist/connections.txt +50 -0
  23. loghunter/data/allowlist/domains_devices.txt +5 -0
  24. loghunter/data/allowlist/domains_homelab.txt +5 -0
  25. loghunter/data/allowlist/domains_universal.txt +125 -0
  26. loghunter/data/config_example.toml +144 -0
  27. loghunter/detectors/__init__.py +5 -0
  28. loghunter/detectors/auth.py +27 -0
  29. loghunter/detectors/aws.py +671 -0
  30. loghunter/detectors/beacon.py +258 -0
  31. loghunter/detectors/dns.py +778 -0
  32. loghunter/detectors/dnsblock.py +29 -0
  33. loghunter/detectors/duration.py +178 -0
  34. loghunter/detectors/protocol.py +26 -0
  35. loghunter/detectors/scan.py +735 -0
  36. loghunter/detectors/ssl.py +25 -0
  37. loghunter/detectors/syslog.py +266 -0
  38. loghunter/detectors/weird.py +27 -0
  39. loghunter/digest/__init__.py +43 -0
  40. loghunter/digest/_stats.py +182 -0
  41. loghunter/digest/blob.py +698 -0
  42. loghunter/digest/cloudtrail.py +341 -0
  43. loghunter/digest/conn.py +367 -0
  44. loghunter/digest/dns.py +364 -0
  45. loghunter/digest/syslog.py +269 -0
  46. loghunter/exporters/__init__.py +534 -0
  47. loghunter/exporters/cloudtrail.py +499 -0
  48. loghunter/exporters/splunk.py +222 -0
  49. loghunter/outputs/__init__.py +1 -0
  50. loghunter/outputs/allowlist.py +75 -0
  51. loghunter/outputs/csv.py +70 -0
  52. loghunter/outputs/email.py +44 -0
  53. loghunter/outputs/html.py +99 -0
  54. loghunter/outputs/json.py +77 -0
  55. loghunter/outputs/text.py +1422 -0
  56. loghunter/parsers/__init__.py +1 -0
  57. loghunter/parsers/cloudtrail.py +287 -0
  58. loghunter/parsers/dnsmasq.py +331 -0
  59. loghunter/parsers/syslog.py +150 -0
  60. loghunter/parsers/zeek.py +294 -0
  61. loghunter/parsers/zeek_tsv.py +310 -0
  62. loghunter/runner.py +1895 -0
  63. loghunter_cli-0.1.0.dev0.dist-info/METADATA +336 -0
  64. loghunter_cli-0.1.0.dev0.dist-info/RECORD +122 -0
  65. loghunter_cli-0.1.0.dev0.dist-info/WHEEL +5 -0
  66. loghunter_cli-0.1.0.dev0.dist-info/entry_points.txt +2 -0
  67. loghunter_cli-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
  68. loghunter_cli-0.1.0.dev0.dist-info/top_level.txt +4 -0
  69. migrations/cloudtrail_parquet.py +59 -0
  70. migrations/conn_fft.py +550 -0
  71. migrations/conn_scan.py +1097 -0
  72. migrations/dns_dbscan.py +520 -0
  73. migrations/get_syslog.py +402 -0
  74. migrations/syslog_drain3.py +479 -0
  75. scratch/junk/parquet.py +59 -0
  76. tests/__init__.py +1 -0
  77. tests/_cloudtrail_fakes.py +116 -0
  78. tests/conftest.py +17 -0
  79. tests/test_allowlist_defaults_accessor.py +90 -0
  80. tests/test_architecture_spine.py +302 -0
  81. tests/test_aws_detector.py +504 -0
  82. tests/test_be_like_water.py +106 -0
  83. tests/test_cli_help.py +342 -0
  84. tests/test_cli_multi_positional.py +458 -0
  85. tests/test_cloudtrail_exporter.py +631 -0
  86. tests/test_cloudtrail_exporter_botocore.py +207 -0
  87. tests/test_cloudtrail_parser.py +393 -0
  88. tests/test_clustering.py +85 -0
  89. tests/test_clustering_interruptible.py +404 -0
  90. tests/test_config_cli.py +1006 -0
  91. tests/test_config_example_drift.py +164 -0
  92. tests/test_digest_blob.py +1237 -0
  93. tests/test_digest_cli.py +1040 -0
  94. tests/test_digest_cloudtrail.py +980 -0
  95. tests/test_digest_conn.py +1189 -0
  96. tests/test_digest_dns.py +770 -0
  97. tests/test_digest_stats.py +282 -0
  98. tests/test_digest_syslog.py +724 -0
  99. tests/test_display.py +370 -0
  100. tests/test_dns_detector.py +1010 -0
  101. tests/test_dnsmasq_parser.py +467 -0
  102. tests/test_duration_detector.py +491 -0
  103. tests/test_export_orchestrator_shape.py +153 -0
  104. tests/test_init_wizard.py +707 -0
  105. tests/test_loader.py +3639 -0
  106. tests/test_loader_package_surface.py +115 -0
  107. tests/test_loader_window_model.py +215 -0
  108. tests/test_output_path_cascade.py +575 -0
  109. tests/test_resolve_path.py +111 -0
  110. tests/test_root_provenance.py +212 -0
  111. tests/test_runner.py +2599 -0
  112. tests/test_scan_detector.py +455 -0
  113. tests/test_search_paths.py +50 -0
  114. tests/test_sniff_orchestrator.py +373 -0
  115. tests/test_sniff_recognizers.py +573 -0
  116. tests/test_source_resolution_seam.py +471 -0
  117. tests/test_sources.py +648 -0
  118. tests/test_splunk_exporter.py +351 -0
  119. tests/test_syslog_detector.py +458 -0
  120. tests/test_syslog_parser.py +582 -0
  121. tests/test_text_output.py +1225 -0
  122. tests/test_zeek_tsv_parser.py +580 -0
@@ -0,0 +1,144 @@
1
+ # LogHunter configuration. Every key is optional — omit any to take the default.
2
+ # Generate this for your environment with `loghunter init`.
3
+
4
+ [loghunter]
5
+
6
+ # Base dir for any RELATIVE path below. "" resolves relative paths from the
7
+ # current dir. Absolute (/…) and ~-anchored paths ignore it. Set it once and
8
+ # write export_dir = "exports". Env override: LOGHUNTER_ROOT.
9
+ root = "~/.loghunter"
10
+
11
+ # Detectors to run: "all" | "dns, beacon" | "all, !syslog". --detect overrides.
12
+ detect = "all"
13
+
14
+ # ── Log sources (read) ──────────────────────────────────────────────
15
+ # Directories holding your logs. Conventional locations shown; uncomment the
16
+ # others if you have them.
17
+ zeek_dir = "/var/log/zeek"
18
+ syslog_dir = "/var/log"
19
+ # pihole_dir = "/var/log/pihole"
20
+ # cloudtrail_dir = "/var/log/cloudtrail"
21
+
22
+ # ── Network ─────────────────────────────────────────────────────────
23
+ # Networks treated as internal for traffic-direction. Topology, not tuning.
24
+ home_net = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
25
+
26
+ # ── Output (write) ──────────────────────────────────────────────────
27
+ # Findings print to your terminal. Set report_dir (or pass --out) to write
28
+ # files instead — reports land in their own dir, never mixed with pulled logs.
29
+ # report_dir = "reports/"
30
+ # export_dir is a directory BASE: each export auto-segments per source into
31
+ # <base>/<source>/ (e.g. exports/syslog/, exports/cloudtrail/) so pulled logs
32
+ # of different families never share a directory. Override per backend or per
33
+ # query (below) to pin a literal dir; --out is always literal.
34
+ export_dir = "exports/"
35
+ output_format = "text"
36
+
37
+ # ── Analysis window ─────────────────────────────────────────────────
38
+ # default_window: lookback for a directory with no --since/--days ("1d","7d",
39
+ # "24h"; "" or "all" = whole archive; --all overrides one run).
40
+ # warn_above: prompt before analyzing more than this many records.
41
+ default_window = "1d"
42
+ warn_above = 5_000_000
43
+
44
+ # Per-detector total cap on rendered TEXT findings (json/csv/html ignore it —
45
+ # machine formats never truncate). Cap operates post severity-sort; a disclosure
46
+ # line is shown when it trips. 0 = unlimited.
47
+ max_findings_per_detector = 100
48
+
49
+ [allowlist]
50
+
51
+ # Shipped domain lists load automatically; add your own (one glob per line).
52
+ # connection_rules: local-only flow suppressions — start blank, add after review.
53
+ # allowlist_dir: TOML classification stanzas (all *.toml loaded).
54
+ domain_patterns = ["~/.loghunter/allowlist.d/domains_user.txt"]
55
+ connection_rules = ["~/.loghunter/allowlist.d/connections.txt"]
56
+ allowlist_dir = "~/.loghunter/allowlist.d/"
57
+
58
+ # ════════════════════════════════════════════════════════════════════
59
+ # Export backends (configure only what you use)
60
+ # ════════════════════════════════════════════════════════════════════
61
+ # Splunk — a non-empty host activates it. Prefer env LOGHUNTER_SPLUNK_USER /
62
+ # _PASS over plaintext credentials. A query named "default" runs with a bare
63
+ # `loghunter export`; run others by name (`loghunter export auth`).
64
+ #
65
+ # [export.splunk]
66
+ # host = "192.0.2.20"
67
+ # port = 8089
68
+ # Per-backend export_dir: a LITERAL final dir for every query on this backend
69
+ # (no per-source auto-segment). Uncomment to override the global base.
70
+ # export_dir = "/srv/exports/splunk/"
71
+ #
72
+ # [export.splunk.query.default]
73
+ # spl = "search index=main sourcetype=syslog | table _time, host, _raw"
74
+ # output_basename = "syslog"
75
+ # Per-query export_dir: the finest grain, a LITERAL final dir for this query
76
+ # only (no auto-segment). Wins over the per-backend and global tiers.
77
+ # export_dir = "/srv/exports/syslog/"
78
+ #
79
+ # [export.splunk.query.auth]
80
+ # spl = "search index=main sourcetype=linux_secure | table _time, host, _raw"
81
+ # output_basename = "auth"
82
+ #
83
+ # CloudTrail — a non-empty path activates it. AWS auth is NOT here; authenticate
84
+ # your shell and boto3 resolves it.
85
+ #
86
+ # [export.cloudtrail]
87
+ # path = "s3://example-bucket/AWSLogs/"
88
+ # egress_warn_gb = 5.0
89
+ # export_dir = "/srv/exports/cloudtrail/" # literal dir override (no auto-segment)
90
+
91
+ # ════════════════════════════════════════════════════════════════════
92
+ # Detector tuning — the engine room. You rarely need any of this; every
93
+ # detector ships sensible defaults. The values shown ARE those defaults —
94
+ # uncomment a line and change it to tune. Full surface per detector:
95
+ # `loghunter <detector> --help`.
96
+ # ════════════════════════════════════════════════════════════════════
97
+
98
+ # beacon — periodic C2-style callbacks (FFT over connection timing).
99
+ # [detectors.beacon]
100
+ # threshold = 0.5 # min composite score to report (0–1)
101
+ # min_connections = 20 # min connections for a flow to qualify
102
+ # bin_seconds = 30 # FFT bin; leave at 30 — 10 aliases a 60s beacon
103
+
104
+ # scan — vertical / horizontal / block / slow port scans.
105
+ # [detectors.scan]
106
+ # vertical_threshold = 15 # distinct ports on one target → vertical
107
+ # horizontal_threshold = 15 # distinct hosts on one port → horizontal
108
+ # block_port_threshold = 20 # ports AND…
109
+ # block_host_threshold = 20 # …hosts, both met → block scan
110
+ # block_state_min = 0.30 # min scan-state ratio for block/slow gates
111
+ # slow_state_min = 0.30
112
+ # window_secs = 3600 # detection window for vert/horiz/block
113
+ # slow_min_ports = 8 # slow scan: min ports across the dataset…
114
+ # slow_min_buckets = 4 # …over this many active time windows
115
+
116
+ # duration — abnormally long-lived connections.
117
+ # [detectors.duration]
118
+ # min_duration_seconds = 1800 # 30m floor to flag (LOW; verbose-only)
119
+
120
+ # dns — DNS clustering (HDBSCAN over per-query behavior).
121
+ # [detectors.dns]
122
+ # min_cluster_size = 2000
123
+ # min_samples = 100
124
+ # threshold = 1.5 # keep ≤ thresh_high_entropy
125
+ # thresh_high_entropy = 1.8 # the operative filter — raise to quiet noise
126
+ # [detectors.dns.pihole] # Pi-hole path clusters aggregated per-domain
127
+ # min_cluster_size = 25 # rows, so its sizes run much smaller
128
+ # min_samples = 10
129
+
130
+ # syslog — rare-event / reboot surfacing (drain3 templating + rarity).
131
+ # [detectors.syslog]
132
+ # lookback_days = 7 # default window when no --since/--days
133
+ # rarity_pct = 10 # bottom-N percentile of template count = rare
134
+ # max_count = 1 # templates seen ≤ this many times always flag
135
+
136
+ # aws — per-principal CloudTrail surfacing (rarity + weirdness + bursts).
137
+ # [detectors.aws]
138
+ # min_events = 50 # interactive principals below this are set aside
139
+ # burst_gap_seconds = 300 # first-seen actions closer than this = one burst
140
+ # burst_min_firsts = 3 # min first-seen actions to form a burst
141
+ # burst_high_error_rate = 0.5 # burst → HIGH escalation gate
142
+ # burst_high_service_count = 3 # burst → HIGH escalation gate
143
+ # composite_medium_threshold = 2.0 # ranked-principal severity bands (absolute
144
+ # composite_low_threshold = 1.0 # z, never rank position)
@@ -0,0 +1,5 @@
1
+ """Detector plugins. Each module exposes DETECTOR_NAME and run(context) -> list[Finding].
2
+
3
+ The framework discovers detectors automatically by scanning this package for modules
4
+ that define DETECTOR_NAME. No registry file, no import needed here.
5
+ """
@@ -0,0 +1,27 @@
1
+ """Auth detector — authentication pattern analysis from syslog. (planned)
2
+
3
+ Analyzes auth.log and secure log files for brute-force attempts, unusual
4
+ authentication patterns, privilege escalation, and new account activity.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from loghunter.common.finding import DetectorContext, Finding
10
+
11
+ DETECTOR_NAME = "auth"
12
+ STATUS = "planned"
13
+
14
+ REQUIRED_LOGS = [
15
+ {"source": "syslog_dir", "pattern": "auth.log*"},
16
+ ]
17
+
18
+ OPTIONAL_LOGS = [
19
+ {"source": "syslog_dir", "pattern": "secure*"},
20
+ ]
21
+
22
+ DEFAULT_CONFIG: dict = {}
23
+
24
+
25
+ def run(context: DetectorContext) -> list[Finding]:
26
+ """Detect anomalous authentication patterns in syslog auth files."""
27
+ raise NotImplementedError("auth detector is planned — not yet implemented")