first sync
This commit is contained in:
706
inc/wazuhalert.class.php
Normal file
706
inc/wazuhalert.class.php
Normal file
@@ -0,0 +1,706 @@
|
||||
<?php
|
||||
/*
|
||||
* Plugin SIEM-Wazuh pour GLPI
|
||||
* Classe de gestion des alertes Wazuh
|
||||
*/
|
||||
|
||||
if (!defined('GLPI_ROOT')) {
|
||||
die("Sorry. You can't access this file directly");
|
||||
}
|
||||
|
||||
class PluginSiemWazuhAlert extends CommonDBTM {
|
||||
|
||||
public $dohistory = true;
|
||||
|
||||
static $rightname = 'plugin_siem_wazuh_alert';
|
||||
|
||||
const MATRIX_FIELD = '';
|
||||
const SEARCHOPTIONS_INHERITANCE = true;
|
||||
|
||||
/**
|
||||
* Return the localized name of the current Type
|
||||
*/
|
||||
static function getTypeName($nb = 0) {
|
||||
return _n('Wazuh Alert', 'Wazuh Alerts', $nb, 'siem-wazuh');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define search options
|
||||
*/
|
||||
function rawSearchOptions() {
|
||||
$tab = [];
|
||||
|
||||
$tab[] = [
|
||||
'id' => 'common',
|
||||
'name' => __('Characteristics')
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '1',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'alert_id',
|
||||
'name' => __('Alert ID', 'siem-wazuh'),
|
||||
'datatype' => 'itemlink',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '2',
|
||||
'table' => 'glpi_plugin_siem_wazuh_servers',
|
||||
'field' => 'name',
|
||||
'name' => __('Wazuh Server', 'siem-wazuh'),
|
||||
'datatype' => 'dropdown',
|
||||
'massiveaction' => false,
|
||||
'linkfield' => 'wazuh_server_id'
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '3',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'rule_id',
|
||||
'name' => __('Rule ID', 'siem-wazuh'),
|
||||
'datatype' => 'integer',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '4',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'rule_level',
|
||||
'name' => __('Rule Level', 'siem-wazuh'),
|
||||
'datatype' => 'integer',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '5',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'rule_description',
|
||||
'name' => __('Rule Description', 'siem-wazuh'),
|
||||
'datatype' => 'text',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '6',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'agent_name',
|
||||
'name' => __('Agent Name', 'siem-wazuh'),
|
||||
'datatype' => 'string',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '7',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'agent_ip',
|
||||
'name' => __('Agent IP', 'siem-wazuh'),
|
||||
'datatype' => 'string',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '8',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'timestamp',
|
||||
'name' => __('Alert Timestamp', 'siem-wazuh'),
|
||||
'datatype' => 'datetime',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '9',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'status',
|
||||
'name' => __('Status'),
|
||||
'datatype' => 'specific',
|
||||
'searchtype' => 'equals',
|
||||
'massiveaction' => true
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '10',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'severity',
|
||||
'name' => __('Severity', 'siem-wazuh'),
|
||||
'datatype' => 'specific',
|
||||
'searchtype' => 'equals',
|
||||
'massiveaction' => true
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '11',
|
||||
'table' => 'glpi_computers',
|
||||
'field' => 'name',
|
||||
'name' => __('Associated Computer', 'siem-wazuh'),
|
||||
'datatype' => 'dropdown',
|
||||
'massiveaction' => false,
|
||||
'linkfield' => 'computer_id'
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '12',
|
||||
'table' => 'glpi_networkequipments',
|
||||
'field' => 'name',
|
||||
'name' => __('Associated Network Equipment', 'siem-wazuh'),
|
||||
'datatype' => 'dropdown',
|
||||
'massiveaction' => false,
|
||||
'linkfield' => 'networkequipment_id'
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '13',
|
||||
'table' => 'glpi_tickets',
|
||||
'field' => 'name',
|
||||
'name' => __('Associated Ticket', 'siem-wazuh'),
|
||||
'datatype' => 'dropdown',
|
||||
'massiveaction' => false,
|
||||
'linkfield' => 'ticket_id'
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '30',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'date_creation',
|
||||
'name' => __('Creation date'),
|
||||
'datatype' => 'datetime',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '31',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'date_mod',
|
||||
'name' => __('Last update'),
|
||||
'datatype' => 'datetime',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
return $tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display specific values
|
||||
*/
|
||||
static function getSpecificValueToDisplay($field, $values, array $options = []) {
|
||||
if (!is_array($values)) {
|
||||
$values = [$field => $values];
|
||||
}
|
||||
|
||||
switch ($field) {
|
||||
case 'status':
|
||||
$statuses = self::getStatusArray();
|
||||
return $statuses[$values[$field]] ?? $values[$field];
|
||||
|
||||
case 'severity':
|
||||
$severities = self::getSeverityArray();
|
||||
return $severities[$values[$field]] ?? $values[$field];
|
||||
}
|
||||
|
||||
return parent::getSpecificValueToDisplay($field, $values, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status array
|
||||
*/
|
||||
static function getStatusArray() {
|
||||
return [
|
||||
'new' => __('New', 'siem-wazuh'),
|
||||
'processed' => __('Processed', 'siem-wazuh'),
|
||||
'ignored' => __('Ignored', 'siem-wazuh'),
|
||||
'ticket_created' => __('Ticket Created', 'siem-wazuh')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get severity array
|
||||
*/
|
||||
static function getSeverityArray() {
|
||||
return [
|
||||
'low' => __('Low', 'siem-wazuh'),
|
||||
'medium' => __('Medium', 'siem-wazuh'),
|
||||
'high' => __('High', 'siem-wazuh'),
|
||||
'critical' => __('Critical', 'siem-wazuh')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Display form
|
||||
*/
|
||||
function showForm($ID, $options = []) {
|
||||
$this->initForm($ID, $options);
|
||||
$this->showFormHeader($options);
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Alert ID', 'siem-wazuh')."</td>";
|
||||
echo "<td>".$this->fields["alert_id"]."</td>";
|
||||
echo "<td>".__('Rule ID', 'siem-wazuh')."</td>";
|
||||
echo "<td>".$this->fields["rule_id"]."</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Rule Level', 'siem-wazuh')."</td>";
|
||||
echo "<td>";
|
||||
echo $this->fields["rule_level"];
|
||||
if ($this->fields["rule_level"]) {
|
||||
$severity = self::getSeverityFromLevel($this->fields["rule_level"]);
|
||||
$severities = self::getSeverityArray();
|
||||
echo " <span class='badge severity-$severity'>".$severities[$severity]."</span>";
|
||||
}
|
||||
echo "</td>";
|
||||
echo "<td>".__('Agent Name', 'siem-wazuh')."</td>";
|
||||
echo "<td>".$this->fields["agent_name"]."</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Agent IP', 'siem-wazuh')."</td>";
|
||||
echo "<td>".$this->fields["agent_ip"]."</td>";
|
||||
echo "<td>".__('Timestamp', 'siem-wazuh')."</td>";
|
||||
echo "<td>".Html::convDateTime($this->fields["timestamp"])."</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Status')."</td>";
|
||||
echo "<td>";
|
||||
$statuses = self::getStatusArray();
|
||||
Dropdown::showFromArray('status', $statuses, ['value' => $this->fields["status"]]);
|
||||
echo "</td>";
|
||||
echo "<td>".__('Severity', 'siem-wazuh')."</td>";
|
||||
echo "<td>";
|
||||
$severities = self::getSeverityArray();
|
||||
Dropdown::showFromArray('severity', $severities, ['value' => $this->fields["severity"]]);
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Rule Description', 'siem-wazuh')."</td>";
|
||||
echo "<td colspan='3'>";
|
||||
echo nl2br(Html::entities_deep($this->fields["rule_description"]));
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
// Affichage des associations
|
||||
if ($this->fields["computer_id"]) {
|
||||
$computer = new Computer();
|
||||
$computer->getFromDB($this->fields["computer_id"]);
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Associated Computer')."</td>";
|
||||
echo "<td>";
|
||||
echo $computer->getLink();
|
||||
echo "</td>";
|
||||
echo "<td></td><td></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
if ($this->fields["networkequipment_id"]) {
|
||||
$netequip = new NetworkEquipment();
|
||||
$netequip->getFromDB($this->fields["networkequipment_id"]);
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Associated Network Equipment')."</td>";
|
||||
echo "<td>";
|
||||
echo $netequip->getLink();
|
||||
echo "</td>";
|
||||
echo "<td></td><td></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
if ($this->fields["ticket_id"]) {
|
||||
$ticket = new Ticket();
|
||||
$ticket->getFromDB($this->fields["ticket_id"]);
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>".__('Associated Ticket')."</td>";
|
||||
echo "<td>";
|
||||
echo $ticket->getLink();
|
||||
echo "</td>";
|
||||
echo "<td></td><td></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
// Affichage des données brutes
|
||||
if (!empty($this->fields["raw_data"])) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td colspan='4'>";
|
||||
echo "<details>";
|
||||
echo "<summary>".__('Raw Alert Data', 'siem-wazuh')."</summary>";
|
||||
echo "<pre class='json-data'>";
|
||||
echo json_encode(json_decode($this->fields["raw_data"]), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
echo "</pre>";
|
||||
echo "</details>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
$this->showFormButtons($options);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process alerts from Wazuh API
|
||||
*/
|
||||
function processAlerts($server_id, $alerts_data) {
|
||||
$processed = 0;
|
||||
$config = new PluginSiemWazuhConfig();
|
||||
|
||||
foreach ($alerts_data as $alert_data) {
|
||||
$alert_id = $alert_data['id'] ?? $alert_data['_id'] ?? null;
|
||||
if (!$alert_id) continue;
|
||||
|
||||
// Vérifier si l'alerte existe déjà
|
||||
if ($this->getFromDBByCrit([
|
||||
'wazuh_server_id' => $server_id,
|
||||
'alert_id' => $alert_id
|
||||
])) {
|
||||
continue; // Alerte déjà traitée
|
||||
}
|
||||
|
||||
// Extraire les informations de l'alerte
|
||||
$rule_id = $alert_data['rule']['id'] ?? null;
|
||||
$rule_level = $alert_data['rule']['level'] ?? 0;
|
||||
$rule_description = $alert_data['rule']['description'] ?? '';
|
||||
$agent_name = $alert_data['agent']['name'] ?? '';
|
||||
$agent_ip = $alert_data['agent']['ip'] ?? '';
|
||||
$timestamp = $alert_data['timestamp'] ?? $alert_data['@timestamp'] ?? date('Y-m-d H:i:s');
|
||||
|
||||
// Convertir le timestamp au format MySQL
|
||||
if (strpos($timestamp, 'T') !== false) {
|
||||
$timestamp = str_replace('T', ' ', substr($timestamp, 0, 19));
|
||||
}
|
||||
|
||||
// Déterminer la sévérité
|
||||
$severity = self::getSeverityFromLevel($rule_level);
|
||||
|
||||
// Créer l'alerte
|
||||
$alert_input = [
|
||||
'wazuh_server_id' => $server_id,
|
||||
'alert_id' => $alert_id,
|
||||
'rule_id' => $rule_id,
|
||||
'rule_level' => $rule_level,
|
||||
'rule_description' => $rule_description,
|
||||
'agent_id' => $alert_data['agent']['id'] ?? '',
|
||||
'agent_name' => $agent_name,
|
||||
'agent_ip' => $agent_ip,
|
||||
'timestamp' => $timestamp,
|
||||
'raw_data' => json_encode($alert_data),
|
||||
'severity' => $severity,
|
||||
'status' => 'new'
|
||||
];
|
||||
|
||||
// Tenter d'associer avec un asset
|
||||
$this->associateWithAsset($alert_input, $agent_name, $agent_ip);
|
||||
|
||||
if ($alert_id = $this->add($alert_input)) {
|
||||
$processed++;
|
||||
|
||||
// Créer automatiquement un ticket si configuré
|
||||
if ($config->getConfiguration('auto_create_ticket', 1)) {
|
||||
$this->createTicketFromAlert($alert_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate alert with GLPI asset
|
||||
*/
|
||||
private function associateWithAsset(&$alert_input, $agent_name, $agent_ip) {
|
||||
global $DB;
|
||||
|
||||
// Recherche par nom d'agent
|
||||
if (!empty($agent_name)) {
|
||||
// Recherche dans les ordinateurs
|
||||
$computer = $DB->request([
|
||||
'SELECT' => ['id'],
|
||||
'FROM' => 'glpi_computers',
|
||||
'WHERE' => [
|
||||
'name' => $agent_name,
|
||||
'is_deleted' => 0
|
||||
],
|
||||
'LIMIT' => 1
|
||||
])->current();
|
||||
|
||||
if ($computer) {
|
||||
$alert_input['computer_id'] = $computer['id'];
|
||||
return;
|
||||
}
|
||||
|
||||
// Recherche dans les équipements réseau
|
||||
$netequip = $DB->request([
|
||||
'SELECT' => ['id'],
|
||||
'FROM' => 'glpi_networkequipments',
|
||||
'WHERE' => [
|
||||
'name' => $agent_name,
|
||||
'is_deleted' => 0
|
||||
],
|
||||
'LIMIT' => 1
|
||||
])->current();
|
||||
|
||||
if ($netequip) {
|
||||
$alert_input['networkequipment_id'] = $netequip['id'];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Recherche par adresse IP
|
||||
if (!empty($agent_ip)) {
|
||||
// Recherche dans les ports réseau
|
||||
$port = $DB->request([
|
||||
'SELECT' => ['items_id', 'itemtype'],
|
||||
'FROM' => 'glpi_networkports',
|
||||
'INNER JOIN' => [
|
||||
'glpi_ipaddresses' => [
|
||||
'ON' => [
|
||||
'glpi_networkports' => 'id',
|
||||
'glpi_ipaddresses' => 'items_id'
|
||||
]
|
||||
]
|
||||
],
|
||||
'WHERE' => [
|
||||
'glpi_ipaddresses.name' => $agent_ip,
|
||||
'glpi_ipaddresses.itemtype' => 'NetworkPort'
|
||||
],
|
||||
'LIMIT' => 1
|
||||
])->current();
|
||||
|
||||
if ($port) {
|
||||
if ($port['itemtype'] == 'Computer') {
|
||||
$alert_input['computer_id'] = $port['items_id'];
|
||||
} elseif ($port['itemtype'] == 'NetworkEquipment') {
|
||||
$alert_input['networkequipment_id'] = $port['items_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ticket from alert
|
||||
*/
|
||||
function createTicketFromAlert($alert_id) {
|
||||
if (!$this->getFromDB($alert_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$server = new PluginSiemWazuhServer();
|
||||
if (!$server->getFromDB($this->fields['wazuh_server_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ticket = new Ticket();
|
||||
$config = new PluginSiemWazuhConfig();
|
||||
|
||||
// Déterminer la priorité basée sur le niveau de règle
|
||||
$priority = self::getPriorityFromLevel($this->fields['rule_level']);
|
||||
|
||||
$ticket_input = [
|
||||
'name' => sprintf(__('Wazuh Alert: %s', 'siem-wazuh'), $this->fields['rule_description']),
|
||||
'content' => $this->generateTicketContent(),
|
||||
'type' => $server->fields['ticket_type'] ?: 1,
|
||||
'itilcategories_id' => $server->fields['ticket_category'],
|
||||
'priority' => $priority,
|
||||
'urgency' => $priority,
|
||||
'impact' => $priority,
|
||||
'status' => CommonITILObject::INCOMING,
|
||||
'_add_validation' => 0
|
||||
];
|
||||
|
||||
// Associer le ticket à l'asset si trouvé
|
||||
if ($this->fields['computer_id']) {
|
||||
$ticket_input['_link']['items_id'] = $this->fields['computer_id'];
|
||||
$ticket_input['_link']['itemtype'] = 'Computer';
|
||||
} elseif ($this->fields['networkequipment_id']) {
|
||||
$ticket_input['_link']['items_id'] = $this->fields['networkequipment_id'];
|
||||
$ticket_input['_link']['itemtype'] = 'NetworkEquipment';
|
||||
}
|
||||
|
||||
$ticket_id = $ticket->add($ticket_input);
|
||||
|
||||
if ($ticket_id) {
|
||||
// Mettre à jour l'alerte
|
||||
$this->update([
|
||||
'id' => $alert_id,
|
||||
'ticket_id' => $ticket_id,
|
||||
'status' => 'ticket_created'
|
||||
]);
|
||||
|
||||
return $ticket_id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate ticket content from alert
|
||||
*/
|
||||
private function generateTicketContent() {
|
||||
$content = "[WAZUH-ALERT]\n\n";
|
||||
$content .= sprintf(__('Alert ID: %s', 'siem-wazuh'), $this->fields['alert_id']) . "\n";
|
||||
$content .= sprintf(__('Rule ID: %s', 'siem-wazuh'), $this->fields['rule_id']) . "\n";
|
||||
$content .= sprintf(__('Rule Level: %s', 'siem-wazuh'), $this->fields['rule_level']) . "\n";
|
||||
$content .= sprintf(__('Agent: %s (%s)', 'siem-wazuh'), $this->fields['agent_name'], $this->fields['agent_ip']) . "\n";
|
||||
$content .= sprintf(__('Timestamp: %s', 'siem-wazuh'), $this->fields['timestamp']) . "\n\n";
|
||||
$content .= sprintf(__('Description: %s', 'siem-wazuh'), $this->fields['rule_description']) . "\n\n";
|
||||
|
||||
if ($this->fields['raw_data']) {
|
||||
$content .= __('Raw Alert Data:', 'siem-wazuh') . "\n";
|
||||
$content .= "```json\n";
|
||||
$content .= json_encode(json_decode($this->fields['raw_data']), JSON_PRETTY_PRINT);
|
||||
$content .= "\n```";
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get severity from rule level
|
||||
*/
|
||||
static function getSeverityFromLevel($level) {
|
||||
if ($level >= 12) return 'critical';
|
||||
if ($level >= 10) return 'high';
|
||||
if ($level >= 7) return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get priority from rule level
|
||||
*/
|
||||
static function getPriorityFromLevel($level) {
|
||||
if ($level >= 12) return 5; // Very high
|
||||
if ($level >= 10) return 4; // High
|
||||
if ($level >= 7) return 3; // Medium
|
||||
if ($level >= 5) return 2; // Low
|
||||
return 1; // Very low
|
||||
}
|
||||
|
||||
/**
|
||||
* Show alerts for a server
|
||||
*/
|
||||
static function showForServer($server_id) {
|
||||
global $DB;
|
||||
|
||||
$iterator = $DB->request([
|
||||
'FROM' => 'glpi_plugin_siem_wazuh_alerts',
|
||||
'WHERE' => ['wazuh_server_id' => $server_id],
|
||||
'ORDER' => 'timestamp DESC',
|
||||
'LIMIT' => 50
|
||||
]);
|
||||
|
||||
echo "<div class='spaced'>";
|
||||
echo "<table class='tab_cadre_fixehov'>";
|
||||
echo "<tr class='tab_bg_2'>";
|
||||
echo "<th>".__('Alert ID', 'siem-wazuh')."</th>";
|
||||
echo "<th>".__('Rule', 'siem-wazuh')."</th>";
|
||||
echo "<th>".__('Level', 'siem-wazuh')."</th>";
|
||||
echo "<th>".__('Agent', 'siem-wazuh')."</th>";
|
||||
echo "<th>".__('Timestamp', 'siem-wazuh')."</th>";
|
||||
echo "<th>".__('Status')."</th>";
|
||||
echo "<th>".__('Ticket')."</th>";
|
||||
echo "</tr>";
|
||||
|
||||
$statuses = self::getStatusArray();
|
||||
|
||||
foreach ($iterator as $row) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td><a href='".PluginSiemWazuhAlert::getFormURLWithID($row['id'])."'>".$row['alert_id']."</a></td>";
|
||||
echo "<td>".$row['rule_id']." - ".Html::clean($row['rule_description'])."</td>";
|
||||
echo "<td>".$row['rule_level']."</td>";
|
||||
echo "<td>".$row['agent_name']." (".$row['agent_ip'].")</td>";
|
||||
echo "<td>".Html::convDateTime($row['timestamp'])."</td>";
|
||||
echo "<td>".$statuses[$row['status']]."</td>";
|
||||
echo "<td>";
|
||||
if ($row['ticket_id']) {
|
||||
$ticket = new Ticket();
|
||||
if ($ticket->getFromDB($row['ticket_id'])) {
|
||||
echo $ticket->getLink();
|
||||
}
|
||||
}
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
echo "</table>";
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Cron function to sync alerts
|
||||
*/
|
||||
static function cronSyncAlerts($task = null) {
|
||||
global $DB;
|
||||
|
||||
$config = new PluginSiemWazuhConfig();
|
||||
if (!$config->getConfiguration('sync_enabled', 1)) {
|
||||
return 0; // Synchronisation désactivée
|
||||
}
|
||||
|
||||
$iterator = $DB->request([
|
||||
'FROM' => 'glpi_plugin_siem_wazuh_servers',
|
||||
'WHERE' => ['is_active' => 1]
|
||||
]);
|
||||
|
||||
$total_processed = 0;
|
||||
|
||||
foreach ($iterator as $server_data) {
|
||||
$server = new PluginSiemWazuhServer();
|
||||
$server->fields = $server_data;
|
||||
|
||||
$result = $server->syncAlerts();
|
||||
if ($result['success']) {
|
||||
$matches = [];
|
||||
if (preg_match('/(\d+)/', $result['message'], $matches)) {
|
||||
$total_processed += (int)$matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($task) {
|
||||
$task->addVolume($total_processed);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return $total_processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cron function to cleanup old alerts
|
||||
*/
|
||||
static function cronCleanupOldAlerts($task = null) {
|
||||
global $DB;
|
||||
|
||||
$config = new PluginSiemWazuhConfig();
|
||||
$retention_days = $config->getConfiguration('alert_retention_days', 90);
|
||||
|
||||
$query = "DELETE FROM glpi_plugin_siem_wazuh_alerts
|
||||
WHERE date_creation < DATE_SUB(NOW(), INTERVAL $retention_days DAY)";
|
||||
|
||||
$result = $DB->query($query);
|
||||
$deleted = $DB->affectedRows();
|
||||
|
||||
if ($task) {
|
||||
$task->addVolume($deleted);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get menu content
|
||||
*/
|
||||
static function getMenuContent() {
|
||||
$menu = [];
|
||||
if (Session::haveRight(static::$rightname, READ)) {
|
||||
$menu['title'] = self::getMenuName();
|
||||
$menu['page'] = "/plugins/siem-wazuh/front/wazuhalert.php";
|
||||
$menu['links']['search'] = "/plugins/siem-wazuh/front/wazuhalert.php";
|
||||
}
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get menu name
|
||||
*/
|
||||
static function getMenuName() {
|
||||
return self::getTypeName(Session::getPluralNumber());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user