mirror of
https://github.com/tips-of-mine/GLPI-Plugin-CVE-Prototype.git
synced 2025-06-27 14:48:45 +02:00
403 lines
12 KiB
PHP
403 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* GLPI CVE Plugin - Main setup file
|
|
* Handles plugin initialization, installation, and hooks
|
|
*/
|
|
|
|
define('PLUGIN_CVE_VERSION', '0.0.1');
|
|
define('PLUGIN_CVE_MIN_GLPI', '10.0.0');
|
|
define('PLUGIN_CVE_MAX_GLPI', '10.99.99');
|
|
define('PLUGIN_CVE_DIR', __DIR__);
|
|
|
|
// Load plugin language definition
|
|
include_once(PLUGIN_CVE_DIR . '/inc/define.php');
|
|
|
|
/**
|
|
* Plugin initialization
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function plugin_init_cve() {
|
|
global $PLUGIN_HOOKS;
|
|
|
|
$PLUGIN_HOOKS['csrf_compliant']['cve'] = true;
|
|
|
|
// Add CSS and JS files
|
|
$PLUGIN_HOOKS['add_css']['cve'] = ['css/cve.css'];
|
|
$PLUGIN_HOOKS['add_javascript']['cve'] = ['js/cve.js'];
|
|
|
|
// Register classes for itemtype
|
|
Plugin::registerClass('PluginCveCve');
|
|
Plugin::registerClass('PluginCveCveSource');
|
|
Plugin::registerClass('PluginCveCveRule');
|
|
Plugin::registerClass('PluginCveCveTicket');
|
|
Plugin::registerClass('PluginCveCveInventory');
|
|
Plugin::registerClass('PluginCveCveAlert');
|
|
|
|
// Initialize localization
|
|
$PLUGIN_HOOKS['init_session']['cve'] = 'plugin_cve_load_language';
|
|
$PLUGIN_HOOKS['change_profile']['cve'] = 'plugin_cve_load_language';
|
|
|
|
// Add in objects
|
|
$PLUGIN_HOOKS['item_get_events']['cve'] = ['NotificationTargetTicket' =>
|
|
['PluginCveCveTicket', 'addEvents']];
|
|
|
|
// Add in database synchronization
|
|
$PLUGIN_HOOKS['plugin_datainjection_populate']['cve'] = ['PluginCveCve' =>
|
|
'plugin_datainjection_populate_cve'];
|
|
|
|
// Menu entry - Add to "Tools" menu only
|
|
$PLUGIN_HOOKS['menu_toadd']['cve'] = [
|
|
'tools' => 'PluginCveCveMenu'
|
|
];
|
|
|
|
// Dashboard widgets
|
|
$PLUGIN_HOOKS['dashboard_cards']['cve'] = 'plugin_cve_dashboard_cards';
|
|
|
|
// Cron tasks registration
|
|
CronTask::register('PluginCveCveSource', 'SyncCVESources', 6 * HOUR_TIMESTAMP,
|
|
['mode' => CronTask::MODE_EXTERNAL]);
|
|
CronTask::register('PluginCveCve', 'CleanOldCVEs', 7 * DAY_TIMESTAMP,
|
|
['mode' => CronTask::MODE_EXTERNAL]);
|
|
CronTask::register('PluginCveCveInventory', 'AnalyzeInventory', 12 * HOUR_TIMESTAMP,
|
|
['mode' => CronTask::MODE_EXTERNAL]);
|
|
|
|
// Item events (hooks)
|
|
$PLUGIN_HOOKS['item_add']['cve'] = ['Ticket' => 'plugin_cve_item_add_ticket'];
|
|
$PLUGIN_HOOKS['item_update']['cve'] = ['Ticket' => 'plugin_cve_item_update_ticket'];
|
|
$PLUGIN_HOOKS['pre_item_purge']['cve'] = ['Ticket' => 'plugin_cve_pre_item_purge_ticket'];
|
|
|
|
// Software inventory hook
|
|
$PLUGIN_HOOKS['item_add']['cve']['Software'] = 'plugin_cve_item_add_software';
|
|
$PLUGIN_HOOKS['item_add']['cve']['SoftwareVersion'] = 'plugin_cve_item_add_softwareversion';
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Handler for software addition
|
|
*
|
|
* @param Software $software Software that was added
|
|
*/
|
|
function plugin_cve_item_add_software(Software $software) {
|
|
// Schedule a vulnerability analysis when new software is added
|
|
$task = new CronTask();
|
|
if ($task->getFromDBbyName('PluginCveCveInventory', 'AnalyzeInventory')) {
|
|
$task->update([
|
|
'id' => $task->fields['id'],
|
|
'state' => CronTask::STATE_WAITING
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handler for software version addition
|
|
*
|
|
* @param SoftwareVersion $version Software version that was added
|
|
*/
|
|
function plugin_cve_item_add_softwareversion(SoftwareVersion $version) {
|
|
// Schedule a vulnerability analysis when new software version is added
|
|
$task = new CronTask();
|
|
if ($task->getFromDBbyName('PluginCveCveInventory', 'AnalyzeInventory')) {
|
|
$task->update([
|
|
'id' => $task->fields['id'],
|
|
'state' => CronTask::STATE_WAITING
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Plugin version information
|
|
*
|
|
* @return array Plugin version info
|
|
*/
|
|
function plugin_version_cve() {
|
|
return [
|
|
'name' => __('Vulnérabilité', 'cve'),
|
|
'version' => PLUGIN_CVE_VERSION,
|
|
'author' => 'Tips-Of-Mine',
|
|
'license' => 'GPL v3+',
|
|
'homepage' => 'https://github.com/tips-of-mine/GLPI-Plugin-CVE-Prototype',
|
|
'requirements' => [
|
|
'glpi' => [
|
|
'min' => PLUGIN_CVE_MIN_GLPI,
|
|
'max' => PLUGIN_CVE_MAX_GLPI,
|
|
'dev' => false
|
|
],
|
|
'php' => [
|
|
'min' => '7.4',
|
|
'max' => '8.2',
|
|
'required' => true
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Plugin initialization check
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function plugin_cve_check_prerequisites() {
|
|
// Check GLPI version
|
|
if (version_compare(GLPI_VERSION, PLUGIN_CVE_MIN_GLPI, 'lt') ||
|
|
version_compare(GLPI_VERSION, PLUGIN_CVE_MAX_GLPI, 'gt')) {
|
|
echo "This plugin requires GLPI >= " . PLUGIN_CVE_MIN_GLPI . " and GLPI <= " . PLUGIN_CVE_MAX_GLPI;
|
|
return false;
|
|
}
|
|
|
|
// Check curl extension
|
|
if (!extension_loaded('curl')) {
|
|
echo "This plugin requires the PHP cURL extension";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Plugin check config
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function plugin_cve_check_config() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Plugin installation process
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function plugin_cve_install() {
|
|
global $DB;
|
|
|
|
$migration = new Migration(PLUGIN_CVE_VERSION);
|
|
|
|
// Install core tables
|
|
PluginCveCve::install($migration);
|
|
PluginCveCveSource::install($migration);
|
|
PluginCveCveRule::install($migration);
|
|
PluginCveCveTicket::install($migration);
|
|
PluginCveCveInventory::install($migration);
|
|
PluginCveCveAlert::install($migration);
|
|
|
|
// Create default notification templates
|
|
// This would be implemented here...
|
|
|
|
$migration->executeMigration();
|
|
|
|
// Schedule the initial CVE data download as a background task
|
|
$task = new CronTask();
|
|
|
|
// Check if the synchronization task is already registered
|
|
$taskId = $task->find(['itemtype' => 'PluginCveCveSource', 'name' => 'SyncCVESources']);
|
|
|
|
if (count($taskId) == 0) {
|
|
// Register the task if it doesn't exist
|
|
$taskId = $task->add([
|
|
'itemtype' => 'PluginCveCveSource',
|
|
'name' => 'SyncCVESources',
|
|
'frequency' => 6 * HOUR_TIMESTAMP,
|
|
'param' => null,
|
|
'state' => CronTask::STATE_WAITING,
|
|
'mode' => CronTask::MODE_EXTERNAL,
|
|
'allowmode' => CronTask::MODE_EXTERNAL,
|
|
'hourmin' => 0,
|
|
'hourmax' => 24,
|
|
'logs_lifetime' => 30,
|
|
'date_creation' => $_SESSION['glpi_currenttime'],
|
|
'comment' => 'Synchronize CVE data from external sources'
|
|
]);
|
|
} else {
|
|
$taskData = array_shift($taskId);
|
|
$taskId = $taskData['id'];
|
|
}
|
|
|
|
// Register the inventory analysis task
|
|
$inventoryTaskId = $task->find(['itemtype' => 'PluginCveCveInventory', 'name' => 'AnalyzeInventory']);
|
|
|
|
if (count($inventoryTaskId) == 0) {
|
|
// Register the task if it doesn't exist
|
|
$inventoryTaskId = $task->add([
|
|
'itemtype' => 'PluginCveCveInventory',
|
|
'name' => 'AnalyzeInventory',
|
|
'frequency' => 12 * HOUR_TIMESTAMP,
|
|
'param' => null,
|
|
'state' => CronTask::STATE_WAITING,
|
|
'mode' => CronTask::MODE_EXTERNAL,
|
|
'allowmode' => CronTask::MODE_EXTERNAL,
|
|
'hourmin' => 0,
|
|
'hourmax' => 24,
|
|
'logs_lifetime' => 30,
|
|
'date_creation' => $_SESSION['glpi_currenttime'],
|
|
'comment' => 'Analyze software inventory for vulnerabilities'
|
|
]);
|
|
} else {
|
|
$taskData = array_shift($inventoryTaskId);
|
|
$inventoryTaskId = $taskData['id'];
|
|
}
|
|
|
|
// Force run the task immediately to download initial CVE data
|
|
if ($taskId > 0) {
|
|
// Log the action
|
|
Toolbox::logInFile('cve_plugin', 'Initial CVE data synchronization scheduled');
|
|
|
|
// Queue the task for immediate execution
|
|
$task->getFromDB($taskId);
|
|
$task->update([
|
|
'id' => $taskId,
|
|
'state' => CronTask::STATE_WAITING
|
|
]);
|
|
|
|
// Start background sync process via AJAX or CLI
|
|
$syncUrl = Plugin::getWebDir('cve') . '/ajax/sync_now.php';
|
|
|
|
// Use asynchronous curl request to start the sync process
|
|
plugin_cve_async_request($syncUrl);
|
|
}
|
|
|
|
// Schedule initial software inventory analysis
|
|
if ($inventoryTaskId > 0) {
|
|
// Log the action
|
|
Toolbox::logInFile('cve_plugin', 'Initial software vulnerability analysis scheduled');
|
|
|
|
// Queue the task for immediate execution after CVE data is synchronized
|
|
$task->getFromDB($inventoryTaskId);
|
|
$task->update([
|
|
'id' => $inventoryTaskId,
|
|
'state' => CronTask::STATE_WAITING
|
|
]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Make an asynchronous HTTP request
|
|
*
|
|
* @param string $url URL to request
|
|
* @return boolean Success
|
|
*/
|
|
function plugin_cve_async_request($url) {
|
|
$ch = curl_init();
|
|
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
|
|
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
|
|
|
|
// Add security token to the request
|
|
$params = [
|
|
'_glpi_csrf_token' => Session::getNewCSRFToken()
|
|
];
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
|
|
|
|
curl_exec($ch);
|
|
curl_close($ch);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Plugin uninstallation process
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function plugin_cve_uninstall() {
|
|
global $DB;
|
|
|
|
$migration = new Migration(PLUGIN_CVE_VERSION);
|
|
|
|
// Remove cron tasks
|
|
$crontask = new CronTask();
|
|
$crontask->deleteByCriteria(['itemtype' => 'PluginCveCveSource', 'name' => 'SyncCVESources']);
|
|
$crontask->deleteByCriteria(['itemtype' => 'PluginCveCve', 'name' => 'CleanOldCVEs']);
|
|
$crontask->deleteByCriteria(['itemtype' => 'PluginCveCveInventory', 'name' => 'AnalyzeInventory']);
|
|
|
|
// Uninstall core tables
|
|
PluginCveCve::uninstall($migration);
|
|
PluginCveCveSource::uninstall($migration);
|
|
PluginCveCveRule::uninstall($migration);
|
|
PluginCveCveTicket::uninstall($migration);
|
|
PluginCveCveInventory::uninstall($migration);
|
|
PluginCveCveAlert::uninstall($migration);
|
|
|
|
// Remove user preferences
|
|
$query = "DELETE FROM `glpi_configs` WHERE `context` = 'plugin:cve'";
|
|
$DB->query($query);
|
|
|
|
$migration->executeMigration();
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Define dropdown relations
|
|
*
|
|
* @return array
|
|
*/
|
|
function plugin_cve_getDatabaseRelations() {
|
|
$plugin = new Plugin();
|
|
|
|
if ($plugin->isActivated('cve')) {
|
|
return [
|
|
"glpi_entities" => [
|
|
"glpi_plugin_cve_cves" => "entities_id",
|
|
"glpi_plugin_cve_alerts" => "entities_id"
|
|
],
|
|
"glpi_tickets" => [
|
|
"glpi_plugin_cve_tickets" => "tickets_id",
|
|
"glpi_plugin_cve_alerts" => "tickets_id"
|
|
],
|
|
"glpi_softwares" => [
|
|
"glpi_plugin_cve_alerts" => "softwares_id"
|
|
],
|
|
"glpi_softwareversions" => [
|
|
"glpi_plugin_cve_alerts" => "softwareversions_id"
|
|
]
|
|
];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Define database table relations
|
|
*
|
|
* @return array
|
|
*/
|
|
function plugin_cve_getTablesNames() {
|
|
$plugin = new Plugin();
|
|
|
|
$tables = [];
|
|
if ($plugin->isActivated('cve')) {
|
|
$tables = [
|
|
'glpi_plugin_cve_cves',
|
|
'glpi_plugin_cve_sources',
|
|
'glpi_plugin_cve_rules',
|
|
'glpi_plugin_cve_tickets',
|
|
'glpi_plugin_cve_alerts'
|
|
];
|
|
}
|
|
|
|
return $tables;
|
|
}
|
|
|
|
/**
|
|
* Display a nice message when activated
|
|
*/
|
|
function plugin_cve_postinit() {
|
|
global $PLUGIN_HOOKS;
|
|
|
|
// Add nice message when activated for the first time
|
|
if (isset($_GET['activate']) && $_GET['activate'] === 'cve') {
|
|
Html::displayTitle(__('Plugin activated successfully!', 'cve'),
|
|
__('CVE Management plugin has been activated.', 'cve') . '<br>' .
|
|
__('Initial CVE data is being synchronized in the background.', 'cve') . '<br>' .
|
|
__('Software inventory will be analyzed for vulnerabilities automatically.', 'cve') . '<br>' .
|
|
__('You can now configure the data sources and rules.', 'cve'));
|
|
}
|
|
} |