mirror of
https://github.com/tips-of-mine/GLPI-Plugin-CVE-Prototype.git
synced 2025-06-28 07:08:44 +02:00
Start repository
This commit is contained in:
494
inc/cveticket.class.php
Normal file
494
inc/cveticket.class.php
Normal file
@ -0,0 +1,494 @@
|
||||
<?php
|
||||
/**
|
||||
* GLPI CVE Plugin - CVE Ticket Class
|
||||
* Manages links between CVEs and GLPI Tickets
|
||||
*/
|
||||
|
||||
if (!defined('GLPI_ROOT')) {
|
||||
die("Sorry. You can't access this file directly");
|
||||
}
|
||||
|
||||
/**
|
||||
* PluginCveCveTicket class for managing CVE-Ticket relations
|
||||
*/
|
||||
class PluginCveCveTicket extends CommonDBRelation {
|
||||
|
||||
// From CommonDBRelation
|
||||
static public $itemtype_1 = 'PluginCveCve';
|
||||
static public $items_id_1 = 'cves_id';
|
||||
static public $itemtype_2 = 'Ticket';
|
||||
static public $items_id_2 = 'tickets_id';
|
||||
|
||||
static $rightname = 'plugin_cve_ticket';
|
||||
|
||||
/**
|
||||
* Get name of this type by language of the user connected
|
||||
*
|
||||
* @param integer $nb number of elements
|
||||
* @return string name of this type
|
||||
*/
|
||||
static function getTypeName($nb = 0) {
|
||||
return _n('CVE Ticket', 'CVE Tickets', $nb, 'cve');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_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' => '3',
|
||||
'table' => 'glpi_tickets',
|
||||
'field' => 'name',
|
||||
'name' => __('Ticket', 'cve'),
|
||||
'massiveaction' => false,
|
||||
'datatype' => 'dropdown',
|
||||
'joinparams' => [
|
||||
'jointype' => 'child',
|
||||
'condition' => 'AND NEWTABLE.`id` = REFTABLE.`tickets_id`'
|
||||
]
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '4',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'creation_type',
|
||||
'name' => __('Creation Type', 'cve'),
|
||||
'massiveaction' => false,
|
||||
'datatype' => 'specific',
|
||||
'searchtype' => ['equals', 'notequals']
|
||||
];
|
||||
|
||||
$tab[] = [
|
||||
'id' => '5',
|
||||
'table' => $this->getTable(),
|
||||
'field' => 'date_creation',
|
||||
'name' => __('Creation date', 'cve'),
|
||||
'datatype' => 'datetime',
|
||||
'massiveaction' => false
|
||||
];
|
||||
|
||||
return $tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show tickets for a CVE
|
||||
*
|
||||
* @param PluginCveCve $cve CVE object
|
||||
* @return void
|
||||
*/
|
||||
static function showForCVE(PluginCveCve $cve) {
|
||||
global $DB;
|
||||
|
||||
$ID = $cve->getField('id');
|
||||
if (!$cve->can($ID, READ)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$canedit = $cve->can($ID, UPDATE);
|
||||
$rand = mt_rand();
|
||||
|
||||
$iterator = $DB->request([
|
||||
'SELECT' => [
|
||||
'glpi_plugin_cve_tickets.*',
|
||||
'glpi_tickets.name AS ticket_name',
|
||||
'glpi_tickets.status AS ticket_status',
|
||||
'glpi_tickets.date AS ticket_date',
|
||||
'glpi_tickets.priority AS ticket_priority'
|
||||
],
|
||||
'FROM' => 'glpi_plugin_cve_tickets',
|
||||
'LEFT JOIN' => [
|
||||
'glpi_tickets' => [
|
||||
'ON' => [
|
||||
'glpi_plugin_cve_tickets' => 'tickets_id',
|
||||
'glpi_tickets' => 'id'
|
||||
]
|
||||
]
|
||||
],
|
||||
'WHERE' => [
|
||||
'glpi_plugin_cve_tickets.cves_id' => $ID
|
||||
],
|
||||
'ORDER' => [
|
||||
'glpi_tickets.date DESC'
|
||||
]
|
||||
]);
|
||||
|
||||
$tickets = [];
|
||||
$used = [];
|
||||
|
||||
foreach ($iterator as $data) {
|
||||
$tickets[$data['id']] = $data;
|
||||
$used[$data['tickets_id']] = $data['tickets_id'];
|
||||
}
|
||||
|
||||
if ($canedit) {
|
||||
echo "<div class='firstbloc'>";
|
||||
echo "<form name='cveticket_form$rand' id='cveticket_form$rand' method='post'
|
||||
action='" . Toolbox::getItemTypeFormURL(__CLASS__) . "'>";
|
||||
|
||||
echo "<table class='tab_cadre_fixe'>";
|
||||
echo "<tr class='tab_bg_2'><th colspan='2'>" . __('Add a ticket', 'cve') . "</th></tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'><td class='right'>";
|
||||
echo "<input type='hidden' name='cves_id' value='$ID'>";
|
||||
Ticket::dropdown([
|
||||
'used' => $used,
|
||||
'entity' => $cve->getEntityID(),
|
||||
'entity_sons' => $cve->isRecursive(),
|
||||
'displaywith' => ['id']
|
||||
]);
|
||||
echo "</td><td class='center'>";
|
||||
echo "<input type='submit' name='add' value=\"" . _sx('button', 'Add') . "\" class='submit'>";
|
||||
echo "</td></tr>";
|
||||
|
||||
echo "</table>";
|
||||
Html::closeForm();
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
if ($canedit && count($tickets)) {
|
||||
$massiveactionparams = [
|
||||
'num_displayed' => min($_SESSION['glpilist_limit'], count($tickets)),
|
||||
'container' => 'mass' . __CLASS__ . $rand,
|
||||
'specific_actions' => [
|
||||
'purge' => _x('button', 'Delete permanently')
|
||||
]
|
||||
];
|
||||
Html::showMassiveActions($massiveactionparams);
|
||||
}
|
||||
|
||||
echo "<table class='tab_cadre_fixehov'>";
|
||||
$header_begin = "<tr>";
|
||||
$header_top = '';
|
||||
$header_bottom = '';
|
||||
$header_end = '';
|
||||
|
||||
if ($canedit && count($tickets)) {
|
||||
$header_top .= "<th width='10'>" . Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand) . "</th>";
|
||||
$header_bottom .= "<th width='10'>" . Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand) . "</th>";
|
||||
}
|
||||
|
||||
$header_end .= "<th>" . __('Ticket', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('Status', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('Priority', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('Opening date', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('Creation type', 'cve') . "</th>";
|
||||
$header_end .= "</tr>";
|
||||
|
||||
echo $header_begin . $header_top . $header_end;
|
||||
|
||||
foreach ($tickets as $data) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
|
||||
if ($canedit) {
|
||||
echo "<td width='10'>";
|
||||
Html::showMassiveActionCheckBox(__CLASS__, $data['id']);
|
||||
echo "</td>";
|
||||
}
|
||||
|
||||
$ticket = new Ticket();
|
||||
$ticket->getFromDB($data['tickets_id']);
|
||||
|
||||
echo "<td class='center'>";
|
||||
if ($ticket->can($data['tickets_id'], READ)) {
|
||||
echo "<a href=\"" . Ticket::getFormURLWithID($data['tickets_id']) . "\">";
|
||||
echo $data['ticket_name'] . " (" . $data['tickets_id'] . ")";
|
||||
echo "</a>";
|
||||
} else {
|
||||
echo $data['ticket_name'] . " (" . $data['tickets_id'] . ")";
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
// Status
|
||||
echo "<td class='center'>";
|
||||
echo Ticket::getStatus($data['ticket_status']);
|
||||
echo "</td>";
|
||||
|
||||
// Priority
|
||||
echo "<td class='center'>";
|
||||
echo Ticket::getPriorityName($data['ticket_priority']);
|
||||
echo "</td>";
|
||||
|
||||
// Date
|
||||
echo "<td class='center'>";
|
||||
echo Html::convDateTime($data['ticket_date']);
|
||||
echo "</td>";
|
||||
|
||||
// Creation type
|
||||
echo "<td class='center'>";
|
||||
echo $data['creation_type'] == 'AUTO' ? __('Automatic', 'cve') : __('Manual', 'cve');
|
||||
echo "</td>";
|
||||
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
if ($header_bottom) {
|
||||
echo $header_begin . $header_bottom . $header_end;
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
if ($canedit && count($tickets)) {
|
||||
$massiveactionparams['ontop'] = false;
|
||||
Html::showMassiveActions($massiveactionparams);
|
||||
Html::closeForm();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show CVEs for a ticket
|
||||
*
|
||||
* @param Ticket $ticket Ticket object
|
||||
* @return void
|
||||
*/
|
||||
static function showForTicket(Ticket $ticket) {
|
||||
global $DB;
|
||||
|
||||
$ID = $ticket->getField('id');
|
||||
if (!$ticket->can($ID, READ)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$canedit = $ticket->can($ID, UPDATE);
|
||||
$rand = mt_rand();
|
||||
|
||||
$iterator = $DB->request([
|
||||
'SELECT' => [
|
||||
'glpi_plugin_cve_tickets.*',
|
||||
'glpi_plugin_cve_cves.cve_id',
|
||||
'glpi_plugin_cve_cves.severity',
|
||||
'glpi_plugin_cve_cves.cvss_score',
|
||||
'glpi_plugin_cve_cves.status AS cve_status'
|
||||
],
|
||||
'FROM' => 'glpi_plugin_cve_tickets',
|
||||
'LEFT JOIN' => [
|
||||
'glpi_plugin_cve_cves' => [
|
||||
'ON' => [
|
||||
'glpi_plugin_cve_tickets' => 'cves_id',
|
||||
'glpi_plugin_cve_cves' => 'id'
|
||||
]
|
||||
]
|
||||
],
|
||||
'WHERE' => [
|
||||
'glpi_plugin_cve_tickets.tickets_id' => $ID
|
||||
]
|
||||
]);
|
||||
|
||||
$cvetickets = [];
|
||||
$used = [];
|
||||
|
||||
foreach ($iterator as $data) {
|
||||
$cvetickets[$data['id']] = $data;
|
||||
$used[$data['cves_id']] = $data['cves_id'];
|
||||
}
|
||||
|
||||
if ($canedit) {
|
||||
echo "<div class='firstbloc'>";
|
||||
echo "<form name='ticketcve_form$rand' id='ticketcve_form$rand' method='post'
|
||||
action='" . Toolbox::getItemTypeFormURL(__CLASS__) . "'>";
|
||||
|
||||
echo "<table class='tab_cadre_fixe'>";
|
||||
echo "<tr class='tab_bg_2'><th colspan='2'>" . __('Add a CVE', 'cve') . "</th></tr>";
|
||||
|
||||
echo "<tr class='tab_bg_1'><td class='right'>";
|
||||
echo "<input type='hidden' name='tickets_id' value='$ID'>";
|
||||
|
||||
$cve = new PluginCveCve();
|
||||
$cve->dropdown([
|
||||
'name' => 'cves_id',
|
||||
'entity' => $ticket->getEntityID(),
|
||||
'used' => $used
|
||||
]);
|
||||
|
||||
echo "</td><td class='center'>";
|
||||
echo "<input type='submit' name='add' value=\"" . _sx('button', 'Add') . "\" class='submit'>";
|
||||
echo "</td></tr>";
|
||||
|
||||
echo "</table>";
|
||||
Html::closeForm();
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
if ($canedit && count($cvetickets)) {
|
||||
$massiveactionparams = [
|
||||
'num_displayed' => min($_SESSION['glpilist_limit'], count($cvetickets)),
|
||||
'container' => 'mass' . __CLASS__ . $rand,
|
||||
'specific_actions' => [
|
||||
'purge' => _x('button', 'Delete permanently')
|
||||
]
|
||||
];
|
||||
Html::showMassiveActions($massiveactionparams);
|
||||
}
|
||||
|
||||
echo "<table class='tab_cadre_fixehov'>";
|
||||
$header_begin = "<tr>";
|
||||
$header_top = '';
|
||||
$header_bottom = '';
|
||||
$header_end = '';
|
||||
|
||||
if ($canedit && count($cvetickets)) {
|
||||
$header_top .= "<th width='10'>" . Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand) . "</th>";
|
||||
$header_bottom .= "<th width='10'>" . Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand) . "</th>";
|
||||
}
|
||||
|
||||
$header_end .= "<th>" . __('CVE ID', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('Severity', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('CVSS Score', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('Status', 'cve') . "</th>";
|
||||
$header_end .= "<th>" . __('Creation Type', 'cve') . "</th>";
|
||||
$header_end .= "</tr>";
|
||||
|
||||
echo $header_begin . $header_top . $header_end;
|
||||
|
||||
foreach ($cvetickets as $data) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
|
||||
if ($canedit) {
|
||||
echo "<td width='10'>";
|
||||
Html::showMassiveActionCheckBox(__CLASS__, $data['id']);
|
||||
echo "</td>";
|
||||
}
|
||||
|
||||
$cve = new PluginCveCve();
|
||||
$cve->getFromDB($data['cves_id']);
|
||||
|
||||
echo "<td class='center'>";
|
||||
if ($cve->can($data['cves_id'], READ)) {
|
||||
echo "<a href=\"" . PluginCveCve::getFormURLWithID($data['cves_id']) . "\">";
|
||||
echo $data['cve_id'];
|
||||
echo "</a>";
|
||||
} else {
|
||||
echo $data['cve_id'];
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
// Severity
|
||||
echo "<td class='center'>";
|
||||
echo "<span class='" . PluginCveCve::getSeverityClass($data['severity']) . "'>";
|
||||
echo $data['severity'];
|
||||
echo "</span>";
|
||||
echo "</td>";
|
||||
|
||||
// CVSS Score
|
||||
echo "<td class='center'>";
|
||||
echo $data['cvss_score'];
|
||||
echo "</td>";
|
||||
|
||||
// Status
|
||||
echo "<td class='center'>";
|
||||
echo "<span class='" . PluginCveCve::getStatusClass($data['cve_status']) . "'>";
|
||||
echo $data['cve_status'];
|
||||
echo "</span>";
|
||||
echo "</td>";
|
||||
|
||||
// Creation type
|
||||
echo "<td class='center'>";
|
||||
echo $data['creation_type'] == 'AUTO' ? __('Automatic', 'cve') : __('Manual', 'cve');
|
||||
echo "</td>";
|
||||
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
if ($header_bottom) {
|
||||
echo $header_begin . $header_bottom . $header_end;
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
if ($canedit && count($cvetickets)) {
|
||||
$massiveactionparams['ontop'] = false;
|
||||
Html::showMassiveActions($massiveactionparams);
|
||||
Html::closeForm();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add events to ticket notifications
|
||||
*
|
||||
* @param array $events Events array
|
||||
* @return array Modified events array
|
||||
*/
|
||||
static function addEvents(&$events) {
|
||||
$events['cve_added'] = __('CVE linked to ticket', 'cve');
|
||||
return $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the plugin database schema
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
static function install(Migration $migration) {
|
||||
global $DB;
|
||||
|
||||
$table = self::getTable();
|
||||
|
||||
if (!$DB->tableExists($table)) {
|
||||
$migration->displayMessage("Installing $table");
|
||||
|
||||
$query = "CREATE TABLE IF NOT EXISTS `$table` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`cves_id` int(11) NOT NULL,
|
||||
`tickets_id` int(11) NOT NULL,
|
||||
`creation_type` enum('AUTO','MANUAL') DEFAULT 'MANUAL',
|
||||
`date_creation` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `cves_id_tickets_id` (`cves_id`,`tickets_id`),
|
||||
KEY `cves_id` (`cves_id`),
|
||||
KEY `tickets_id` (`tickets_id`),
|
||||
KEY `creation_type` (`creation_type`),
|
||||
KEY `date_creation` (`date_creation`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
|
||||
|
||||
$DB->query($query) or die("Error creating $table " . $DB->error());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall the plugin database schema
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
static function uninstall(Migration $migration) {
|
||||
global $DB;
|
||||
|
||||
$table = self::getTable();
|
||||
|
||||
if ($DB->tableExists($table)) {
|
||||
$migration->displayMessage("Uninstalling $table");
|
||||
$migration->dropTable($table);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user