- Rewrite overview.js to use KissTheme wrapper - Add health status cards for Agent, Manager, Indexer, CrowdSec - Add alert statistics with color-coded counters - Add security layers table (Firewall, IPS, SIEM, WAF) - Add quick actions with restart agent button - Include built IPK in secubox-feed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
255 lines
7.3 KiB
JavaScript
255 lines
7.3 KiB
JavaScript
'use strict';
|
|
'require view';
|
|
'require dom';
|
|
'require poll';
|
|
'require wazuh.api as api';
|
|
'require secubox/kiss-theme';
|
|
|
|
return view.extend({
|
|
handleSaveApply: null,
|
|
handleSave: null,
|
|
handleReset: null,
|
|
|
|
load: function() {
|
|
return Promise.all([
|
|
api.getOverview(),
|
|
api.getAlertSummary(),
|
|
api.getCrowdSecCorrelation()
|
|
]);
|
|
},
|
|
|
|
render: function(data) {
|
|
var self = this;
|
|
var overview = data[0] || {};
|
|
var alerts = data[1] || {};
|
|
var crowdsec = data[2] || {};
|
|
|
|
// Determine health status
|
|
var agentOk = overview.agent && overview.agent.connected;
|
|
var managerOk = overview.manager && overview.manager.running;
|
|
var indexerOk = overview.manager && overview.manager.indexer_status === 'green';
|
|
var crowdsecOk = crowdsec.crowdsec_running;
|
|
|
|
var content = [
|
|
// Header
|
|
E('div', { 'style': 'margin-bottom: 24px;' }, [
|
|
E('div', { 'style': 'display: flex; align-items: center; gap: 16px; flex-wrap: wrap;' }, [
|
|
E('h2', { 'style': 'font-size: 24px; font-weight: 700; margin: 0;' }, 'Wazuh SIEM'),
|
|
KissTheme.badge(managerOk ? 'RUNNING' : 'STOPPED', managerOk ? 'green' : 'red')
|
|
]),
|
|
E('p', { 'style': 'color: var(--kiss-muted); margin: 8px 0 0 0;' },
|
|
'Security Information and Event Management')
|
|
]),
|
|
|
|
// Navigation tabs
|
|
this.renderNav('overview'),
|
|
|
|
// Stats row
|
|
E('div', { 'class': 'kiss-grid kiss-grid-4', 'id': 'wazuh-stats', 'style': 'margin: 20px 0;' }, [
|
|
KissTheme.stat(alerts.critical || 0, 'Critical', this.colors.red),
|
|
KissTheme.stat(alerts.high || 0, 'High', this.colors.orange),
|
|
KissTheme.stat(alerts.medium || 0, 'Medium', this.colors.yellow),
|
|
KissTheme.stat(alerts.total || 0, 'Total Alerts', this.colors.cyan)
|
|
]),
|
|
|
|
// Two column layout
|
|
E('div', { 'class': 'kiss-grid kiss-grid-2' }, [
|
|
// Health Status card
|
|
KissTheme.card('System Health', this.renderHealth(overview, crowdsec)),
|
|
// Quick Actions card
|
|
KissTheme.card('Quick Actions', this.renderActions())
|
|
]),
|
|
|
|
// Security Layers
|
|
KissTheme.card('Security Layers', this.renderLayers(overview, crowdsec))
|
|
];
|
|
|
|
poll.add(L.bind(this.pollData, this), 30);
|
|
return KissTheme.wrap(content, 'admin/services/wazuh/overview');
|
|
},
|
|
|
|
colors: {
|
|
green: '#00C853',
|
|
red: '#FF1744',
|
|
orange: '#fb923c',
|
|
yellow: '#fbbf24',
|
|
cyan: '#22d3ee',
|
|
muted: '#94a3b8'
|
|
},
|
|
|
|
renderNav: function(active) {
|
|
var tabs = [
|
|
{ name: 'Overview', path: 'admin/services/wazuh/overview' },
|
|
{ name: 'Alerts', path: 'admin/services/wazuh/alerts' },
|
|
{ name: 'File Integrity', path: 'admin/services/wazuh/fim' },
|
|
{ name: 'Agents', path: 'admin/services/wazuh/agents' }
|
|
];
|
|
|
|
return E('div', { 'class': 'kiss-tabs' }, tabs.map(function(tab) {
|
|
var isActive = tab.path.indexOf(active) !== -1;
|
|
return E('a', {
|
|
'href': L.url(tab.path),
|
|
'class': 'kiss-tab' + (isActive ? ' active' : '')
|
|
}, tab.name);
|
|
}));
|
|
},
|
|
|
|
renderHealth: function(overview, crowdsec) {
|
|
var self = this;
|
|
var items = [
|
|
{
|
|
name: 'Wazuh Agent',
|
|
status: overview.agent && overview.agent.connected ? 'Connected' :
|
|
(overview.agent && overview.agent.running ? 'Running' : 'Stopped'),
|
|
ok: overview.agent && overview.agent.connected,
|
|
desc: 'Local security monitoring'
|
|
},
|
|
{
|
|
name: 'Wazuh Manager',
|
|
status: overview.manager && overview.manager.running ? 'Running' : 'Stopped',
|
|
ok: overview.manager && overview.manager.running,
|
|
desc: 'SIEM server in LXC'
|
|
},
|
|
{
|
|
name: 'Indexer',
|
|
status: overview.manager ? (overview.manager.indexer_status || 'Unknown') : 'Unknown',
|
|
ok: overview.manager && overview.manager.indexer_status === 'green',
|
|
desc: 'OpenSearch cluster'
|
|
},
|
|
{
|
|
name: 'CrowdSec',
|
|
status: crowdsec.crowdsec_running ? 'Active' : 'Inactive',
|
|
ok: crowdsec.crowdsec_running,
|
|
desc: (crowdsec.active_decisions || 0) + ' ban decisions'
|
|
}
|
|
];
|
|
|
|
return E('div', {}, items.map(function(item) {
|
|
return E('div', {
|
|
'style': 'display: flex; align-items: center; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid var(--kiss-line);'
|
|
}, [
|
|
E('div', {}, [
|
|
E('div', { 'style': 'font-weight: 600;' }, item.name),
|
|
E('div', { 'style': 'font-size: 12px; color: var(--kiss-muted);' }, item.desc)
|
|
]),
|
|
KissTheme.badge(item.status, item.ok ? 'green' : 'red')
|
|
]);
|
|
}));
|
|
},
|
|
|
|
renderActions: function() {
|
|
var self = this;
|
|
return E('div', { 'style': 'display: flex; flex-direction: column; gap: 12px;' }, [
|
|
E('a', {
|
|
'href': 'https://wazuh.gk2.secubox.in',
|
|
'target': '_blank',
|
|
'class': 'kiss-btn kiss-btn-green',
|
|
'style': 'text-decoration: none; justify-content: center;'
|
|
}, '🔗 Open Wazuh Dashboard'),
|
|
|
|
E('button', {
|
|
'class': 'kiss-btn kiss-btn-blue',
|
|
'click': L.bind(this.handleRestartAgent, this)
|
|
}, '🔄 Restart Agent'),
|
|
|
|
E('a', {
|
|
'href': L.url('admin/services/wazuh/alerts'),
|
|
'class': 'kiss-btn',
|
|
'style': 'text-decoration: none; justify-content: center;'
|
|
}, '📋 View Alerts'),
|
|
|
|
E('a', {
|
|
'href': L.url('admin/services/wazuh/fim'),
|
|
'class': 'kiss-btn',
|
|
'style': 'text-decoration: none; justify-content: center;'
|
|
}, '📁 File Integrity')
|
|
]);
|
|
},
|
|
|
|
renderLayers: function(overview, crowdsec) {
|
|
var layers = [
|
|
{
|
|
num: 1,
|
|
name: 'Firewall',
|
|
component: 'Vortex + nftables',
|
|
desc: 'Kernel-level IP blocking',
|
|
ok: true
|
|
},
|
|
{
|
|
num: 2,
|
|
name: 'IPS',
|
|
component: 'CrowdSec + Bouncer',
|
|
desc: 'Behavior-based detection',
|
|
ok: crowdsec.crowdsec_running
|
|
},
|
|
{
|
|
num: 3,
|
|
name: 'SIEM/XDR',
|
|
component: 'Wazuh Manager',
|
|
desc: 'Log analysis & correlation',
|
|
ok: overview.manager && overview.manager.running
|
|
},
|
|
{
|
|
num: 4,
|
|
name: 'WAF',
|
|
component: 'mitmproxy + HAProxy',
|
|
desc: 'Web application firewall',
|
|
ok: true
|
|
}
|
|
];
|
|
|
|
return E('table', { 'class': 'kiss-table' }, [
|
|
E('thead', {}, [
|
|
E('tr', {}, [
|
|
E('th', {}, 'Layer'),
|
|
E('th', {}, 'Component'),
|
|
E('th', {}, 'Function'),
|
|
E('th', { 'style': 'text-align: right;' }, 'Status')
|
|
])
|
|
]),
|
|
E('tbody', {}, layers.map(function(layer) {
|
|
return E('tr', {}, [
|
|
E('td', {}, 'L' + layer.num + ': ' + layer.name),
|
|
E('td', { 'style': 'font-family: monospace;' }, layer.component),
|
|
E('td', { 'style': 'color: var(--kiss-muted);' }, layer.desc),
|
|
E('td', { 'style': 'text-align: right;' },
|
|
KissTheme.badge(layer.ok ? 'ACTIVE' : 'DOWN', layer.ok ? 'green' : 'red')
|
|
)
|
|
]);
|
|
}))
|
|
]);
|
|
},
|
|
|
|
handleRestartAgent: function() {
|
|
return api.restartAgent().then(function(res) {
|
|
if (res.success) {
|
|
L.ui.addNotification(null, E('p', 'Wazuh agent restarted successfully'), 'info');
|
|
} else {
|
|
L.ui.addNotification(null, E('p', 'Failed to restart agent'), 'error');
|
|
}
|
|
});
|
|
},
|
|
|
|
pollData: function() {
|
|
var self = this;
|
|
return Promise.all([
|
|
api.getOverview(),
|
|
api.getAlertSummary()
|
|
]).then(function(data) {
|
|
var overview = data[0] || {};
|
|
var alerts = data[1] || {};
|
|
|
|
// Update stats
|
|
var statsEl = document.getElementById('wazuh-stats');
|
|
if (statsEl) {
|
|
dom.content(statsEl, [
|
|
KissTheme.stat(alerts.critical || 0, 'Critical', self.colors.red),
|
|
KissTheme.stat(alerts.high || 0, 'High', self.colors.orange),
|
|
KissTheme.stat(alerts.medium || 0, 'Medium', self.colors.yellow),
|
|
KissTheme.stat(alerts.total || 0, 'Total Alerts', self.colors.cyan)
|
|
]);
|
|
}
|
|
});
|
|
}
|
|
});
|