add ui
This commit is contained in:
@@ -5,11 +5,14 @@ import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from .anomaly import anomaly_summary, detect_source_anomalies
|
||||
from .dashboard import serve_dashboard
|
||||
from .llm import ollama_summary
|
||||
from .logs import local_in_failures, read_events, summarize_events, top_field_values
|
||||
from .mitigation import FortiGateClient, parse_allowlist, suggest_block_candidates
|
||||
from .policies import audit_policies, read_policies
|
||||
from .syslog_server import listen_udp_syslog
|
||||
from .monitor import monitor_loop
|
||||
|
||||
|
||||
def _print_json(data: object) -> None:
|
||||
@@ -24,8 +27,10 @@ def analyze_logs(args: argparse.Namespace) -> int:
|
||||
min_score=args.min_score,
|
||||
allowlist=parse_allowlist(args.allowlist),
|
||||
)
|
||||
anomalies = detect_source_anomalies(events, limit=args.anomaly_limit)
|
||||
analysis = {
|
||||
"summary": summarize_events(events),
|
||||
"anomaly_summary": anomaly_summary(anomalies),
|
||||
"diagnostics": {
|
||||
"top_source_ips": top_field_values(events, "srcip", limit=10),
|
||||
"top_services": top_field_values(events, "service", limit=10),
|
||||
@@ -37,6 +42,17 @@ def analyze_logs(args: argparse.Namespace) -> int:
|
||||
{"src_ip": candidate.src_ip, "score": candidate.score, "reasons": candidate.reasons}
|
||||
for candidate in candidates
|
||||
],
|
||||
"anomalies": [
|
||||
{
|
||||
"subject": finding.subject,
|
||||
"score": finding.score,
|
||||
"severity": finding.severity,
|
||||
"confidence": finding.confidence,
|
||||
"reasons": finding.reasons,
|
||||
"evidence": finding.evidence,
|
||||
}
|
||||
for finding in anomalies
|
||||
],
|
||||
}
|
||||
_print_json(analysis)
|
||||
if args.llm:
|
||||
@@ -78,6 +94,31 @@ def suggest_blocks(args: argparse.Namespace) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def detect_anomalies(args: argparse.Namespace) -> int:
|
||||
events = read_events(args.logs)
|
||||
anomalies = detect_source_anomalies(events, limit=args.limit)
|
||||
output = {
|
||||
"summary": anomaly_summary(anomalies),
|
||||
"anomalies": [
|
||||
{
|
||||
"subject": finding.subject,
|
||||
"score": finding.score,
|
||||
"severity": finding.severity,
|
||||
"confidence": finding.confidence,
|
||||
"reasons": finding.reasons,
|
||||
"evidence": finding.evidence,
|
||||
}
|
||||
for finding in anomalies
|
||||
if finding.score >= args.min_score
|
||||
],
|
||||
}
|
||||
_print_json(output)
|
||||
if args.llm:
|
||||
print("\nLLM summary:")
|
||||
print(ollama_summary([], [], args.model, analysis=output, timeout=args.llm_timeout))
|
||||
return 0
|
||||
|
||||
|
||||
def test_connection(args: argparse.Namespace) -> int:
|
||||
client = FortiGateClient.from_env()
|
||||
status = client.system_status()
|
||||
@@ -105,6 +146,22 @@ def listen_syslog(args: argparse.Namespace) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def run_monitor(args: argparse.Namespace) -> int:
|
||||
monitor_loop(
|
||||
args.logs,
|
||||
args.output,
|
||||
policy_path=args.policies,
|
||||
interval=args.interval,
|
||||
anomaly_limit=args.anomaly_limit,
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
def run_dashboard(args: argparse.Namespace) -> int:
|
||||
serve_dashboard(args.host, args.port, args.status_file, image_dir=args.image_dir)
|
||||
return 0
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(description="Local FortiGate AI/ML inspection tool")
|
||||
subparsers = parser.add_subparsers(required=True)
|
||||
@@ -117,8 +174,18 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
logs.add_argument("--llm", action="store_true", help="Ask local Ollama to summarize results")
|
||||
logs.add_argument("--model", default=None, help="Ollama model name")
|
||||
logs.add_argument("--llm-timeout", type=int, default=None, help="Ollama request timeout in seconds")
|
||||
logs.add_argument("--anomaly-limit", type=int, default=20, help="Maximum anomaly findings to include")
|
||||
logs.set_defaults(func=analyze_logs)
|
||||
|
||||
anomalies = subparsers.add_parser("detect-anomalies", help="Score likely traffic anomalies by source IP")
|
||||
anomalies.add_argument("--logs", required=True, help="Path to syslog JSONL or key/value log file")
|
||||
anomalies.add_argument("--limit", type=int, default=20, help="Maximum anomaly findings to include")
|
||||
anomalies.add_argument("--min-score", type=int, default=1, help="Minimum anomaly score to output")
|
||||
anomalies.add_argument("--llm", action="store_true", help="Ask local Ollama to summarize results")
|
||||
anomalies.add_argument("--model", default=None, help="Ollama model name")
|
||||
anomalies.add_argument("--llm-timeout", type=int, default=None, help="Ollama request timeout in seconds")
|
||||
anomalies.set_defaults(func=detect_anomalies)
|
||||
|
||||
policies = subparsers.add_parser("audit-policies", help="Audit FortiOS firewall policy config")
|
||||
policies.add_argument("--config", required=True, help="Path to FortiOS config backup")
|
||||
policies.add_argument("--llm", action="store_true", help="Ask local Ollama to summarize results")
|
||||
@@ -149,6 +216,21 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
listener.add_argument("--quiet", action="store_true", help="Do not print each received syslog message")
|
||||
listener.set_defaults(func=listen_syslog)
|
||||
|
||||
monitor = subparsers.add_parser("monitor", help="Continuously analyze logs and write dashboard status JSON")
|
||||
monitor.add_argument("--logs", required=True, help="Path to syslog JSONL or key/value log file")
|
||||
monitor.add_argument("--output", default="state/fgai-status.json", help="Status JSON written for dashboard")
|
||||
monitor.add_argument("--policies", default=None, help="Optional FortiGate policy JSON/config file to audit continuously")
|
||||
monitor.add_argument("--interval", type=int, default=10, help="Seconds between analysis runs")
|
||||
monitor.add_argument("--anomaly-limit", type=int, default=20, help="Maximum anomaly findings to include")
|
||||
monitor.set_defaults(func=run_monitor)
|
||||
|
||||
dashboard = subparsers.add_parser("dashboard", help="Serve local fgAI dashboard")
|
||||
dashboard.add_argument("--host", default="127.0.0.1", help="Dashboard bind address")
|
||||
dashboard.add_argument("--port", type=int, default=8088, help="Dashboard TCP port")
|
||||
dashboard.add_argument("--status-file", default="state/fgai-status.json", help="Status JSON produced by monitor")
|
||||
dashboard.add_argument("--image-dir", default="images", help="Directory containing dashboard images")
|
||||
dashboard.set_defaults(func=run_dashboard)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user