add more streams
This commit is contained in:
@@ -5,6 +5,7 @@ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
|
||||
from .config import ConfigStore
|
||||
from .graylog_mcp import GraylogMcpClient
|
||||
|
||||
|
||||
HTML = """<!doctype html>
|
||||
@@ -62,7 +63,7 @@ HTML = """<!doctype html>
|
||||
<div data-view="overview" class="active"><section class="panel"><h2>AI Assessment</h2><div id="llmAssessment" class="muted">LLM assessment disabled.</div></section><section class="split"><div class="panel"><h2>Anomalies</h2><div id="anomalies"></div></div><div class="panel"><h2>Recommendations</h2><div id="recommendations"></div></div></section></div>
|
||||
<div data-view="findings"><section class="split"><div class="panel"><h2>Block Candidates</h2><div id="blocks"></div></div><div class="panel"><h2>Threat Intelligence</h2><div id="reputation"></div></div></section><section class="panel"><h2>Policy Findings</h2><div id="policies"></div></section></div>
|
||||
<div data-view="diagnostics"><section class="panel"><h2>Diagnostics</h2><div id="diagnostics"></div></section></div>
|
||||
<div data-view="settings"><section class="panel"><h2>Runtime Configuration</h2><form id="settingsForm"><div class="grid"><label>Log source<br><select name="log_source"><option value="local_syslog">Local syslog</option><option value="graylog_mcp">Graylog MCP</option></select></label><label>Graylog MCP URL<br><input name="graylog_mcp_url" type="url" placeholder="https://graylog.example/api/mcp"></label><label>Graylog stream<br><input name="graylog_stream" placeholder="FortiGate stream ID or name"></label><label>Graylog query<br><input name="graylog_query" placeholder="*"></label><label>Graylog field mapping (JSON)<br><textarea name="graylog_field_mapping" placeholder='{"srcip":"client_ip","dstip":"server_ip","action":"event_action"}'></textarea></label><label>Graylog MCP token<br><input name="graylog_mcp_token" type="password" placeholder="Leave blank to keep current token"></label><label>Ollama model<br><input name="llm_model" placeholder="llama3.1"></label><label><input name="llm_enabled" type="checkbox"> Enable Ollama analysis</label><label><input name="threat_intel_enabled" type="checkbox"> Enable threat intelligence</label></div><p><button type="submit">Save configuration</button> <span id="settingsResult" class="muted"></span></p></form></section></div>
|
||||
<div data-view="settings"><section class="panel"><h2>Runtime Configuration</h2><form id="settingsForm"><div class="grid"><label>Log source<br><select name="log_source"><option value="local_syslog">Local syslog</option><option value="graylog_mcp">Graylog MCP</option></select></label><label>Graylog MCP URL<br><input name="graylog_mcp_url" type="url" placeholder="https://graylog.example/api/mcp"></label><label>Graylog streams<br><button type="button" id="loadStreams">Load streams</button><div id="streamPicker" class="muted">Load streams after URL and token are saved.</div></label><label>Graylog query<br><input name="graylog_query" placeholder="*"></label><label>Graylog field mapping (JSON)<br><textarea name="graylog_field_mapping" placeholder='{"srcip":"client_ip","dstip":"server_ip","action":"event_action"}'></textarea></label><label>Graylog MCP token<br><input name="graylog_mcp_token" type="password" placeholder="Leave blank to keep current token"></label><label>Ollama model<br><input name="llm_model" placeholder="llama3.1"></label><label><input name="llm_enabled" type="checkbox"> Enable Ollama analysis</label><label><input name="threat_intel_enabled" type="checkbox"> Enable threat intelligence</label></div><p><button type="submit">Save configuration</button> <span id="settingsResult" class="muted"></span></p></form></section></div>
|
||||
</main>
|
||||
<script>
|
||||
function esc(value) {
|
||||
@@ -152,7 +153,10 @@ async function refresh() {
|
||||
{label:'Detail', key:'detail'}
|
||||
]);
|
||||
const d = data.diagnostics || {};
|
||||
const context = data.event_context || {};
|
||||
document.getElementById('diagnostics').innerHTML =
|
||||
'<h3>Entities</h3>' + table(context.source_profiles || [], [{label:'Entity', key:'entity'}, {label:'Events', key:'events'}, {label:'UTM', key:'utm_events'}, {label:'Deny', key:'deny_or_threat_actions'}, {label:'Destinations', key:'distinct_destinations'}, {label:'Actions', render:r => esc((r.top_actions || []).join(', '))}]) +
|
||||
'<h3>Security Event Samples</h3>' + table(context.security_event_samples || [], [{label:'Entity', key:'entity'}, {label:'Type', key:'type'}, {label:'Action', key:'action'}, {label:'Severity', key:'severity'}, {label:'Destination', key:'dst'}, {label:'Service', key:'service'}]) +
|
||||
'<h3>Top Sources</h3>' + table(d.top_source_ips || [], [{label:'Value', key:'value'}, {label:'Count', key:'count'}]) +
|
||||
'<h3>Top Destinations</h3>' + table(d.top_destination_ips || [], [{label:'Value', key:'value'}, {label:'Count', key:'count'}]) +
|
||||
'<h3>Top Policy IDs</h3>' + table(d.top_policy_ids || [], [{label:'Value', key:'value'}, {label:'Count', key:'count'}]) +
|
||||
@@ -172,12 +176,20 @@ async function loadSettings() {
|
||||
const token = form.elements.namedItem('graylog_mcp_token');
|
||||
token.placeholder = config.graylog_mcp_token_configured ? 'Token configured; leave blank to keep it' : 'Paste a read-only token';
|
||||
}
|
||||
async function loadStreams() {
|
||||
const response = await fetch('/api/graylog/streams');
|
||||
const payload = await response.json();
|
||||
const selected = new Set((payload.selected || []).map(item => item.id));
|
||||
document.getElementById('streamPicker').innerHTML = (payload.streams || []).map(stream => `<label><input type="checkbox" class="graylog-stream" data-id="${esc(stream.id)}" data-title="${esc(stream.title)}" ${selected.has(stream.id) ? 'checked' : ''}> ${esc(stream.title)}</label><br>`).join('') || esc(payload.error || 'No streams found.');
|
||||
}
|
||||
document.getElementById('loadStreams').addEventListener('click', loadStreams);
|
||||
document.getElementById('settingsForm').addEventListener('submit', async event => {
|
||||
event.preventDefault();
|
||||
const form = event.currentTarget;
|
||||
const values = Object.fromEntries(new FormData(form));
|
||||
values.llm_enabled = form.elements.llm_enabled.checked;
|
||||
values.threat_intel_enabled = form.elements.threat_intel_enabled.checked;
|
||||
values.graylog_streams = [...document.querySelectorAll('.graylog-stream')].map(item => ({id:item.dataset.id, title:item.dataset.title, enabled:item.checked}));
|
||||
const response = await fetch('/api/config', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(values)});
|
||||
document.getElementById('settingsResult').textContent = response.ok ? 'Saved. Monitor applies supported settings on its next cycle.' : 'Could not save configuration.';
|
||||
if (response.ok) loadSettings();
|
||||
@@ -208,6 +220,20 @@ def serve_dashboard(host: str, port: int, status_file: str, *, image_dir: str |
|
||||
if self.path == "/api/config":
|
||||
self._send(200, "application/json", json.dumps(config_store.public()).encode("utf-8"))
|
||||
return
|
||||
if self.path == "/api/graylog/streams":
|
||||
config = config_store.read()
|
||||
try:
|
||||
client = GraylogMcpClient(str(config.get("graylog_mcp_url", "")), str(config.get("graylog_mcp_token", "")))
|
||||
client.probe()
|
||||
result = client.call_tool("list_streams", {})
|
||||
content = result.get("result", {}).get("content", [])
|
||||
text = next((item.get("text", "") for item in content if isinstance(item, dict)), "")
|
||||
streams = json.loads(text)
|
||||
body = {"streams": streams, "selected": config.get("graylog_streams", [])}
|
||||
self._send(200, "application/json", json.dumps(body).encode("utf-8"))
|
||||
except Exception as exc:
|
||||
self._send(400, "application/json", json.dumps({"error": str(exc)}).encode("utf-8"))
|
||||
return
|
||||
if self.path == "/api/status":
|
||||
if status_path.exists():
|
||||
body = status_path.read_bytes()
|
||||
|
||||
Reference in New Issue
Block a user