first sync
This commit is contained in:
454
inc/wazuhtab.class.php
Normal file
454
inc/wazuhtab.class.php
Normal file
@@ -0,0 +1,454 @@
|
||||
<?php
|
||||
/*
|
||||
* Plugin SIEM-Wazuh pour GLPI
|
||||
* Classe de gestion des onglets Wazuh sur les assets
|
||||
*/
|
||||
|
||||
if (!defined('GLPI_ROOT')) {
|
||||
die("Sorry. You can't access this file directly");
|
||||
}
|
||||
|
||||
class PluginSiemWazuhTab extends CommonGLPI {
|
||||
|
||||
static $rightname = 'plugin_siem_wazuh_alert';
|
||||
|
||||
/**
|
||||
* Get tab name for item
|
||||
*/
|
||||
function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
|
||||
if (!$withtemplate && Session::haveRight(static::$rightname, READ)) {
|
||||
if (in_array($item->getType(), ['Computer', 'NetworkEquipment', 'Peripheral', 'Phone', 'Printer'])) {
|
||||
$nb = 0;
|
||||
if ($_SESSION['glpishow_count_on_tabs']) {
|
||||
$nb = self::countForItem($item);
|
||||
}
|
||||
return self::createTabEntry(__('Wazuh Alerts', 'siem-wazuh'), $nb);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Display tab content
|
||||
*/
|
||||
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
|
||||
if (in_array($item->getType(), ['Computer', 'NetworkEquipment', 'Peripheral', 'Phone', 'Printer'])) {
|
||||
self::showForItem($item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count alerts for item
|
||||
*/
|
||||
static function countForItem(CommonGLPI $item) {
|
||||
global $DB;
|
||||
|
||||
$itemtype = $item->getType();
|
||||
$items_id = $item->getID();
|
||||
|
||||
$field_map = [
|
||||
'Computer' => 'computer_id',
|
||||
'NetworkEquipment' => 'networkequipment_id',
|
||||
'Peripheral' => 'peripheral_id',
|
||||
'Phone' => 'phone_id',
|
||||
'Printer' => 'printer_id'
|
||||
];
|
||||
|
||||
if (!isset($field_map[$itemtype])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return countElementsInTable('glpi_plugin_siem_wazuh_alerts', [
|
||||
$field_map[$itemtype] => $items_id
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show alerts for item
|
||||
*/
|
||||
static function showForItem(CommonGLPI $item) {
|
||||
global $DB, $CFG_GLPI;
|
||||
|
||||
$itemtype = $item->getType();
|
||||
$items_id = $item->getID();
|
||||
|
||||
$field_map = [
|
||||
'Computer' => 'computer_id',
|
||||
'NetworkEquipment' => 'networkequipment_id',
|
||||
'Peripheral' => 'peripheral_id',
|
||||
'Phone' => 'phone_id',
|
||||
'Printer' => 'printer_id'
|
||||
];
|
||||
|
||||
if (!isset($field_map[$itemtype])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$field = $field_map[$itemtype];
|
||||
$canupdate = Session::haveRight(static::$rightname, UPDATE);
|
||||
|
||||
// Récupération des alertes
|
||||
$iterator = $DB->request([
|
||||
'SELECT' => [
|
||||
'glpi_plugin_siem_wazuh_alerts.*',
|
||||
'glpi_plugin_siem_wazuh_servers.name AS server_name'
|
||||
],
|
||||
'FROM' => 'glpi_plugin_siem_wazuh_alerts',
|
||||
'LEFT JOIN' => [
|
||||
'glpi_plugin_siem_wazuh_servers' => [
|
||||
'ON' => [
|
||||
'glpi_plugin_siem_wazuh_alerts' => 'wazuh_server_id',
|
||||
'glpi_plugin_siem_wazuh_servers' => 'id'
|
||||
]
|
||||
]
|
||||
],
|
||||
'WHERE' => [$field => $items_id],
|
||||
'ORDER' => ['timestamp DESC', 'rule_level DESC'],
|
||||
'LIMIT' => 100
|
||||
]);
|
||||
|
||||
$alerts = iterator_to_array($iterator);
|
||||
|
||||
echo "<div class='spaced'>";
|
||||
|
||||
// Résumé des alertes
|
||||
self::showAlertsSummary($alerts);
|
||||
|
||||
if (count($alerts) > 0) {
|
||||
// Filtres
|
||||
self::showAlertsFilters($item, $field);
|
||||
|
||||
// Tableau des alertes
|
||||
self::showAlertsTable($alerts, $canupdate);
|
||||
|
||||
// Actions de masse
|
||||
if ($canupdate && count($alerts) > 0) {
|
||||
self::showMassActions($item, $field);
|
||||
}
|
||||
} else {
|
||||
echo "<div class='center'>";
|
||||
echo "<p>" . __('No Wazuh alerts found for this item', 'siem-wazuh') . "</p>";
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Show alerts summary
|
||||
*/
|
||||
static function showAlertsSummary($alerts) {
|
||||
$stats = [
|
||||
'total' => count($alerts),
|
||||
'new' => 0,
|
||||
'processed' => 0,
|
||||
'ticket_created' => 0,
|
||||
'ignored' => 0,
|
||||
'critical' => 0,
|
||||
'high' => 0,
|
||||
'medium' => 0,
|
||||
'low' => 0
|
||||
];
|
||||
|
||||
foreach ($alerts as $alert) {
|
||||
$stats[$alert['status']]++;
|
||||
$stats[$alert['severity']]++;
|
||||
}
|
||||
|
||||
echo "<div class='alert-summary'>";
|
||||
echo "<table class='tab_cadre_fixe'>";
|
||||
echo "<tr class='tab_bg_2'>";
|
||||
echo "<th colspan='8'>" . __('Alerts Summary', 'siem-wazuh') . "</th>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td class='center'><strong>" . $stats['total'] . "</strong><br>" . __('Total', 'siem-wazuh') . "</td>";
|
||||
echo "<td class='center status-new'><strong>" . $stats['new'] . "</strong><br>" . __('New', 'siem-wazuh') . "</td>";
|
||||
echo "<td class='center status-processed'><strong>" . $stats['processed'] . "</strong><br>" . __('Processed', 'siem-wazuh') . "</td>";
|
||||
echo "<td class='center status-ticket'><strong>" . $stats['ticket_created'] . "</strong><br>" . __('Ticket Created', 'siem-wazuh') . "</td>";
|
||||
echo "<td class='center severity-critical'><strong>" . $stats['critical'] . "</strong><br>" . __('Critical', 'siem-wazuh') . "</td>";
|
||||
echo "<td class='center severity-high'><strong>" . $stats['high'] . "</strong><br>" . __('High', 'siem-wazuh') . "</td>";
|
||||
echo "<td class='center severity-medium'><strong>" . $stats['medium'] . "</strong><br>" . __('Medium', 'siem-wazuh') . "</td>";
|
||||
echo "<td class='center severity-low'><strong>" . $stats['low'] . "</strong><br>" . __('Low', 'siem-wazuh') . "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "</table>";
|
||||
echo "</div>";
|
||||
echo "<br>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Show alerts filters
|
||||
*/
|
||||
static function showAlertsFilters($item, $field) {
|
||||
echo "<div class='alert-filters'>";
|
||||
echo "<form method='get' action=''>";
|
||||
echo "<input type='hidden' name='id' value='" . $item->getID() . "'>";
|
||||
echo "<input type='hidden' name='_glpi_tab' value='PluginSiemWazuhTab$1'>";
|
||||
|
||||
echo "<table class='tab_cadre_fixe'>";
|
||||
echo "<tr class='tab_bg_2'>";
|
||||
echo "<th colspan='4'>" . __('Filters', 'siem-wazuh') . "</th>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>" . __('Status') . "</td>";
|
||||
echo "<td>";
|
||||
$statuses = ['all' => __('All')] + PluginSiemWazuhAlert::getStatusArray();
|
||||
Dropdown::showFromArray('filter_status', $statuses, [
|
||||
'value' => $_GET['filter_status'] ?? 'all'
|
||||
]);
|
||||
echo "</td>";
|
||||
|
||||
echo "<td>" . __('Severity', 'siem-wazuh') . "</td>";
|
||||
echo "<td>";
|
||||
$severities = ['all' => __('All')] + PluginSiemWazuhAlert::getSeverityArray();
|
||||
Dropdown::showFromArray('filter_severity', $severities, [
|
||||
'value' => $_GET['filter_severity'] ?? 'all'
|
||||
]);
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>" . __('Date from', 'siem-wazuh') . "</td>";
|
||||
echo "<td>";
|
||||
Html::showDateField('filter_date_from', [
|
||||
'value' => $_GET['filter_date_from'] ?? ''
|
||||
]);
|
||||
echo "</td>";
|
||||
|
||||
echo "<td>" . __('Date to', 'siem-wazuh') . "</td>";
|
||||
echo "<td>";
|
||||
Html::showDateField('filter_date_to', [
|
||||
'value' => $_GET['filter_date_to'] ?? ''
|
||||
]);
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td colspan='4' class='center'>";
|
||||
echo "<input type='submit' value='" . _sx('button', 'Filter') . "' class='submit'>";
|
||||
echo " ";
|
||||
echo "<input type='button' value='" . _sx('button', 'Reset') . "' class='submit' onclick='window.location.href=\"" . $item->getLinkURL() . "&_glpi_tab=PluginSiemWazuhTab$1\"'>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "</table>";
|
||||
echo "</form>";
|
||||
echo "</div>";
|
||||
echo "<br>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Show alerts table
|
||||
*/
|
||||
static function showAlertsTable($alerts, $canupdate) {
|
||||
echo "<div class='alert-list'>";
|
||||
echo "<form method='post' name='alerts_form' id='alerts_form' action='" . Plugin::getWebDir('siem-wazuh') . "/front/wazuhalert.form.php'>";
|
||||
echo "<table class='tab_cadre_fixehov'>";
|
||||
|
||||
$header = "<tr class='tab_bg_2'>";
|
||||
if ($canupdate) {
|
||||
$header .= "<th width='10'>";
|
||||
$header .= "<input type='checkbox' name='select_all' onclick='checkAll(this)'>";
|
||||
$header .= "</th>";
|
||||
}
|
||||
$header .= "<th>" . __('Alert ID', 'siem-wazuh') . "</th>";
|
||||
$header .= "<th>" . __('Server', 'siem-wazuh') . "</th>";
|
||||
$header .= "<th>" . __('Rule', 'siem-wazuh') . "</th>";
|
||||
$header .= "<th>" . __('Level', 'siem-wazuh') . "</th>";
|
||||
$header .= "<th>" . __('Agent', 'siem-wazuh') . "</th>";
|
||||
$header .= "<th>" . __('Timestamp', 'siem-wazuh') . "</th>";
|
||||
$header .= "<th>" . __('Status') . "</th>";
|
||||
$header .= "<th>" . __('Severity', 'siem-wazuh') . "</th>";
|
||||
$header .= "<th>" . __('Ticket') . "</th>";
|
||||
$header .= "</tr>";
|
||||
|
||||
echo $header;
|
||||
|
||||
if (count($alerts) == 0) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td colspan='" . ($canupdate ? "10" : "9") . "' class='center'>";
|
||||
echo __('No alerts found', 'siem-wazuh');
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
$statuses = PluginSiemWazuhAlert::getStatusArray();
|
||||
$severities = PluginSiemWazuhAlert::getSeverityArray();
|
||||
|
||||
foreach ($alerts as $alert) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
|
||||
if ($canupdate) {
|
||||
echo "<td>";
|
||||
echo "<input type='checkbox' name='selected_alerts[]' value='" . $alert['id'] . "'>";
|
||||
echo "</td>";
|
||||
}
|
||||
|
||||
echo "<td>";
|
||||
echo "<a href='" . PluginSiemWazuhAlert::getFormURLWithID($alert['id']) . "'>";
|
||||
echo $alert['alert_id'];
|
||||
echo "</a>";
|
||||
echo "</td>";
|
||||
|
||||
echo "<td>" . $alert['server_name'] . "</td>";
|
||||
|
||||
echo "<td>";
|
||||
echo "<strong>" . $alert['rule_id'] . "</strong><br>";
|
||||
echo "<small>" . Html::clean($alert['rule_description']) . "</small>";
|
||||
echo "</td>";
|
||||
|
||||
echo "<td class='center'>";
|
||||
echo "<span class='rule-level-" . $alert['rule_level'] . "'>";
|
||||
echo $alert['rule_level'];
|
||||
echo "</span>";
|
||||
echo "</td>";
|
||||
|
||||
echo "<td>";
|
||||
echo $alert['agent_name'] . "<br>";
|
||||
echo "<small>" . $alert['agent_ip'] . "</small>";
|
||||
echo "</td>";
|
||||
|
||||
echo "<td>" . Html::convDateTime($alert['timestamp']) . "</td>";
|
||||
|
||||
echo "<td>";
|
||||
echo "<span class='status-badge status-" . $alert['status'] . "'>";
|
||||
echo $statuses[$alert['status']];
|
||||
echo "</span>";
|
||||
echo "</td>";
|
||||
|
||||
echo "<td>";
|
||||
echo "<span class='severity-badge severity-" . $alert['severity'] . "'>";
|
||||
echo $severities[$alert['severity']];
|
||||
echo "</span>";
|
||||
echo "</td>";
|
||||
|
||||
echo "<td>";
|
||||
if ($alert['ticket_id']) {
|
||||
$ticket = new Ticket();
|
||||
if ($ticket->getFromDB($alert['ticket_id'])) {
|
||||
echo $ticket->getLink();
|
||||
}
|
||||
} else {
|
||||
echo "-";
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
echo "</table>";
|
||||
|
||||
if ($canupdate && count($alerts) > 0) {
|
||||
echo "<div class='center' style='margin-top: 10px;'>";
|
||||
echo "<input type='submit' name='mark_processed' value='" . __('Mark as Processed', 'siem-wazuh') . "' class='submit'>";
|
||||
echo " ";
|
||||
echo "<input type='submit' name='mark_ignored' value='" . __('Mark as Ignored', 'siem-wazuh') . "' class='submit'>";
|
||||
echo " ";
|
||||
echo "<input type='submit' name='create_tickets' value='" . __('Create Tickets', 'siem-wazuh') . "' class='submit'>";
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
echo Html::closeForm();
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Show mass actions
|
||||
*/
|
||||
static function showMassActions($item, $field) {
|
||||
echo "<br>";
|
||||
echo "<div class='mass-actions'>";
|
||||
echo "<table class='tab_cadre_fixe'>";
|
||||
echo "<tr class='tab_bg_2'>";
|
||||
echo "<th colspan='2'>" . __('Mass Actions', 'siem-wazuh') . "</th>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>" . __('Sync new alerts', 'siem-wazuh') . "</td>";
|
||||
echo "<td>";
|
||||
echo "<button type='button' class='btn btn-primary' onclick='syncAlertsForItem(" . $item->getID() . ", \"" . $item->getType() . "\")'>";
|
||||
echo __('Sync Now', 'siem-wazuh');
|
||||
echo "</button>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>" . __('Export alerts', 'siem-wazuh') . "</td>";
|
||||
echo "<td>";
|
||||
echo "<a href='" . Plugin::getWebDir('siem-wazuh') . "/front/wazuhalert.php?export=1&" . $field . "=" . $item->getID() . "' class='btn'>";
|
||||
echo __('Export CSV', 'siem-wazuh');
|
||||
echo "</a>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "</table>";
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get search options for item
|
||||
*/
|
||||
static function getSearchOptionsForItem($itemtype) {
|
||||
$tab = [];
|
||||
|
||||
$tab[5150]['table'] = 'glpi_plugin_siem_wazuh_alerts';
|
||||
$tab[5150]['field'] = 'id';
|
||||
$tab[5150]['name'] = __('Wazuh Alerts', 'siem-wazuh');
|
||||
$tab[5150]['forcegroupby'] = true;
|
||||
$tab[5150]['usehaving'] = true;
|
||||
$tab[5150]['datatype'] = 'count';
|
||||
$tab[5150]['massiveaction'] = false;
|
||||
|
||||
$field_map = [
|
||||
'Computer' => 'computer_id',
|
||||
'NetworkEquipment' => 'networkequipment_id',
|
||||
'Peripheral' => 'peripheral_id',
|
||||
'Phone' => 'phone_id',
|
||||
'Printer' => 'printer_id'
|
||||
];
|
||||
|
||||
if (isset($field_map[$itemtype])) {
|
||||
$tab[5150]['linkfield'] = $field_map[$itemtype];
|
||||
}
|
||||
|
||||
return $tab;
|
||||
}
|
||||
}
|
||||
|
||||
// JavaScript pour les fonctionnalités interactives
|
||||
echo "<script type='text/javascript'>
|
||||
function checkAll(checkbox) {
|
||||
var checkboxes = document.querySelectorAll('input[name=\"selected_alerts[]\"]');
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
checkboxes[i].checked = checkbox.checked;
|
||||
}
|
||||
}
|
||||
|
||||
function syncAlertsForItem(itemId, itemType) {
|
||||
if (confirm('" . __('Are you sure you want to sync alerts for this item?', 'siem-wazuh') . "')) {
|
||||
// AJAX call to sync alerts
|
||||
fetch('" . Plugin::getWebDir('siem-wazuh') . "/ajax/sync_alerts.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'item_id=' + itemId + '&item_type=' + itemType
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
alert('" . __('Sync completed successfully', 'siem-wazuh') . "');
|
||||
location.reload();
|
||||
} else {
|
||||
alert('" . __('Sync failed:', 'siem-wazuh') . " ' + data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('" . __('An error occurred during sync', 'siem-wazuh') . "');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>";
|
Reference in New Issue
Block a user