addDefaultFormTab($tabs); $this->addStandardTab('Log', $tabs, $options); return $tabs; } /** * Display the CVE Alert form * * @param integer $ID ID of the item * @param array $options * @return boolean */ function showForm($ID, $options = []) { global $CFG_GLPI; $this->initForm($ID, $options); $this->showFormHeader($options); $canedit = $this->can($ID, UPDATE); echo ""; // Software echo "" . __('Software', 'cve') . ""; echo ""; if ($this->fields['softwares_id'] > 0) { $software = new Software(); if ($software->getFromDB($this->fields['softwares_id'])) { echo $software->getLink(); } else { echo __('Unknown software', 'cve'); } } else { echo __('N/A', 'cve'); } echo ""; // Version echo "" . __('Version', 'cve') . ""; echo ""; if ($this->fields['softwareversions_id'] > 0) { $version = new SoftwareVersion(); if ($version->getFromDB($this->fields['softwareversions_id'])) { echo $version->getName(); } else { echo __('Unknown version', 'cve'); } } else { echo __('N/A', 'cve'); } echo ""; echo ""; echo ""; // CVE echo "" . __('CVE', 'cve') . ""; echo ""; if ($this->fields['cves_id'] > 0) { $cve = new PluginCveCve(); if ($cve->getFromDB($this->fields['cves_id'])) { echo ""; echo $cve->fields['cve_id']; echo ""; } else { echo __('Unknown CVE', 'cve'); } } else { echo __('N/A', 'cve'); } echo ""; // Severity echo "" . __('Severity', 'cve') . ""; echo ""; echo ""; echo $this->fields['severity']; echo ""; echo ""; echo ""; echo ""; // Status echo "" . __('Status', 'cve') . ""; echo ""; if ($canedit) { $status_options = [ 'NEW' => __('New', 'cve'), 'PROCESSED' => __('Processed', 'cve'), 'IGNORED' => __('Ignored', 'cve') ]; Dropdown::showFromArray('status', $status_options, ['value' => $this->fields['status']]); } else { echo $this->fields['status']; } echo ""; // Associated ticket echo "" . __('Ticket', 'cve') . ""; echo ""; if ($this->fields['tickets_id'] > 0) { $ticket = new Ticket(); if ($ticket->getFromDB($this->fields['tickets_id'])) { echo ""; echo $ticket->fields['name'] . " (" . $this->fields['tickets_id'] . ")"; echo ""; } else { echo __('Unknown ticket', 'cve'); } } else { if ($canedit && $this->fields['status'] == 'NEW') { echo ""; } else { echo __('No ticket associated', 'cve'); } } echo ""; echo ""; // Add entity dropdown if needed echo ""; echo "" . __('Entity', 'cve') . ""; echo ""; echo Dropdown::getDropdownName('glpi_entities', $this->fields['entities_id']); echo ""; // Creation date echo "" . __('Creation Date', 'cve') . ""; echo "" . Html::convDateTime($this->fields['date_creation']) . ""; echo ""; $this->showFormButtons($options); return true; } /** * Actions done after the PURGE of the item in the database * * @return void */ function post_purgeItem() { // Nothing special } /** * Actions done after the UPDATE of the item in the database * * @param integer $history store changes history ? * @return void */ function post_updateItem($history = 1) { // If status changed to IGNORED, we might want to do something if (in_array('status', $this->updates) && $this->fields['status'] == 'IGNORED') { // Add a record to ignore this specific software-CVE combination in the future // This would be implemented here } } /** * Get search function for the class * * @return array of search options */ function rawSearchOptions() { $tab = []; $tab[] = [ 'id' => 'common', 'name' => self::getTypeName(2) ]; $tab[] = [ 'id' => '1', 'table' => $this->getTable(), 'field' => 'id', 'name' => __('ID', 'cve'), 'massiveaction' => false, 'datatype' => 'number' ]; $tab[] = [ 'id' => '2', 'table' => 'glpi_softwares', 'field' => 'name', 'name' => __('Software', 'cve'), 'massiveaction' => false, 'datatype' => 'dropdown', 'joinparams' => [ 'jointype' => 'child', 'condition' => 'AND NEWTABLE.`id` = REFTABLE.`softwares_id`' ] ]; $tab[] = [ 'id' => '3', 'table' => 'glpi_softwareversions', 'field' => 'name', 'name' => __('Version', 'cve'), 'massiveaction' => false, 'datatype' => 'dropdown', 'joinparams' => [ 'jointype' => 'child', 'condition' => 'AND NEWTABLE.`id` = REFTABLE.`softwareversions_id`' ] ]; $tab[] = [ 'id' => '4', 'table' => 'glpi_plugin_cve_cves', 'field' => 'cve_id', 'name' => __('CVE ID', 'cve'), 'massiveaction' => false, 'datatype' => 'dropdown', 'joinparams' => [ 'jointype' => 'child', 'condition' => 'AND NEWTABLE.`id` = REFTABLE.`cves_id`' ] ]; $tab[] = [ 'id' => '5', 'table' => $this->getTable(), 'field' => 'severity', 'name' => __('Severity', 'cve'), 'datatype' => 'specific', 'searchtype' => ['equals', 'notequals'] ]; $tab[] = [ 'id' => '6', 'table' => $this->getTable(), 'field' => 'status', 'name' => __('Status', 'cve'), 'datatype' => 'specific', 'searchtype' => ['equals', 'notequals'] ]; $tab[] = [ 'id' => '7', 'table' => 'glpi_tickets', 'field' => 'name', 'name' => __('Ticket', 'cve'), 'massiveaction' => false, 'datatype' => 'dropdown', 'joinparams' => [ 'jointype' => 'child', 'condition' => 'AND NEWTABLE.`id` = REFTABLE.`tickets_id`' ] ]; $tab[] = [ 'id' => '8', 'table' => 'glpi_entities', 'field' => 'completename', 'name' => __('Entity', 'cve'), 'massiveaction' => false, 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '9', 'table' => $this->getTable(), 'field' => 'date_creation', 'name' => __('Creation date', 'cve'), 'datatype' => 'datetime', 'massiveaction' => false ]; $tab[] = [ 'id' => '10', 'table' => $this->getTable(), 'field' => 'date_mod', 'name' => __('Last update', 'cve'), 'datatype' => 'datetime', 'massiveaction' => false ]; return $tab; } /** * Get dashboard count of alerts by severity * * @return array */ static function getAlertStats() { global $DB; $stats = []; // Count by severity $query = "SELECT severity, status, COUNT(*) as count FROM `" . self::getTable() . "` GROUP BY severity, status"; $result = $DB->query($query); $stats['by_severity'] = [ 'CRITICAL' => 0, 'HIGH' => 0, 'MEDIUM' => 0, 'LOW' => 0 ]; $stats['by_status'] = [ 'NEW' => 0, 'PROCESSED' => 0, 'IGNORED' => 0 ]; if ($result) { while ($data = $DB->fetchAssoc($result)) { // Add to severity stats if (isset($stats['by_severity'][$data['severity']])) { $stats['by_severity'][$data['severity']] += $data['count']; } // Add to status stats if (isset($stats['by_status'][$data['status']])) { $stats['by_status'][$data['status']] += $data['count']; } } } // Get total count $query = "SELECT COUNT(*) as total FROM `" . self::getTable() . "`"; $result = $DB->query($query); $stats['total'] = 0; if ($result && $data = $DB->fetchAssoc($result)) { $stats['total'] = $data['total']; } return $stats; } /** * Get alerts for dashboard * * @param integer $limit Maximum number of alerts to return * @return array */ static function getRecentAlerts($limit = 10) { global $DB; $alerts = []; $query = "SELECT a.*, c.cve_id, c.severity AS cve_severity, s.name AS software_name, v.name AS version_name FROM `" . self::getTable() . "` AS a LEFT JOIN `glpi_plugin_cve_cves` AS c ON c.id = a.cves_id LEFT JOIN `glpi_softwares` AS s ON s.id = a.softwares_id LEFT JOIN `glpi_softwareversions` AS v ON v.id = a.softwareversions_id ORDER BY a.date_creation DESC LIMIT $limit"; $result = $DB->query($query); if ($result) { while ($data = $DB->fetchAssoc($result)) { $alerts[] = $data; } } return $alerts; } }