mirror of
https://github.com/tips-of-mine/GLPI-Plugin-CVE-Prototype.git
synced 2025-06-27 14:48:45 +02:00
Update plugin configuration files for proper GLPI detection
This commit is contained in:
3
css/README
Normal file
3
css/README
Normal file
@ -0,0 +1,3 @@
|
||||
This directory contains all CSS styles for the CVE plugin.
|
||||
|
||||
The main file, cve.css, is automatically loaded by GLPI via the plugin's setup.php file.
|
207
css/cve.css
Normal file
207
css/cve.css
Normal file
@ -0,0 +1,207 @@
|
||||
/**
|
||||
* GLPI CVE Plugin - Main CSS
|
||||
* This file contains styles specific to the CVE plugin
|
||||
*/
|
||||
|
||||
/* Dashboard styles */
|
||||
.dashboard-card-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.dashboard-card {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dashboard-card-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 15px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.dashboard-card-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.dashboard-card-title {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.dashboard-card-value {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Card types */
|
||||
.dashboard-card-critical .dashboard-card-icon {
|
||||
background-color: #ffcdd2;
|
||||
color: #d32f2f;
|
||||
}
|
||||
|
||||
.dashboard-card-high .dashboard-card-icon {
|
||||
background-color: #ffe0b2;
|
||||
color: #ef6c00;
|
||||
}
|
||||
|
||||
.dashboard-card-new .dashboard-card-icon {
|
||||
background-color: #bbdefb;
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
.dashboard-card-resolved .dashboard-card-icon {
|
||||
background-color: #c8e6c9;
|
||||
color: #388e3c;
|
||||
}
|
||||
|
||||
/* Chart styles */
|
||||
.dashboard-chart-container {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
||||
padding: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.dashboard-chart-container h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.severity-chart-bars {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
height: 200px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.severity-chart-bar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.severity-chart-bar {
|
||||
width: 40px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
min-height: 5px;
|
||||
}
|
||||
|
||||
.severity-chart-label {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.severity-chart-value {
|
||||
margin-top: 5px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Table styles */
|
||||
.dashboard-table-container {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
||||
padding: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.dashboard-table-container h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Severity classes */
|
||||
.cve-severity-critical {
|
||||
background-color: #d32f2f;
|
||||
color: #fff;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cve-severity-high {
|
||||
background-color: #f57c00;
|
||||
color: #fff;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cve-severity-medium {
|
||||
background-color: #fbc02d;
|
||||
color: #333;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cve-severity-low {
|
||||
background-color: #2196f3;
|
||||
color: #fff;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Status classes */
|
||||
.cve-status-new {
|
||||
background-color: #2196f3;
|
||||
color: #fff;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cve-status-analyzed {
|
||||
background-color: #ff9800;
|
||||
color: #fff;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cve-status-assigned {
|
||||
background-color: #9c27b0;
|
||||
color: #fff;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cve-status-resolved {
|
||||
background-color: #4caf50;
|
||||
color: #fff;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Badge style for dashboard */
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
88
front/cve.form.php
Normal file
88
front/cve.form.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* GLPI CVE Plugin - CVE Form
|
||||
*/
|
||||
|
||||
include ("../../../inc/includes.php");
|
||||
|
||||
Session::checkRight("plugin_cve_cve", READ);
|
||||
|
||||
$cve = new PluginCveCve();
|
||||
|
||||
if (isset($_POST["add"])) {
|
||||
$cve->check(-1, CREATE, $_POST);
|
||||
if ($cve->add($_POST)) {
|
||||
Event::log(
|
||||
$cve->fields['id'],
|
||||
"plugin_cve_cve",
|
||||
4,
|
||||
"inventory",
|
||||
sprintf(__('%1$s adds the CVE %2$s'), $_SESSION["glpiname"], $_POST["cve_id"])
|
||||
);
|
||||
}
|
||||
Html::back();
|
||||
} else if (isset($_POST["delete"])) {
|
||||
$cve->check($_POST["id"], DELETE);
|
||||
if ($cve->delete($_POST)) {
|
||||
Event::log(
|
||||
$_POST["id"],
|
||||
"plugin_cve_cve",
|
||||
4,
|
||||
"inventory",
|
||||
sprintf(__('%1$s deletes the CVE %2$s'), $_SESSION["glpiname"], $_POST["id"])
|
||||
);
|
||||
}
|
||||
$cve->redirectToList();
|
||||
} else if (isset($_POST["restore"])) {
|
||||
$cve->check($_POST["id"], DELETE);
|
||||
if ($cve->restore($_POST)) {
|
||||
Event::log(
|
||||
$_POST["id"],
|
||||
"plugin_cve_cve",
|
||||
4,
|
||||
"inventory",
|
||||
sprintf(__('%1$s restores the CVE %2$s'), $_SESSION["glpiname"], $_POST["id"])
|
||||
);
|
||||
}
|
||||
$cve->redirectToList();
|
||||
} else if (isset($_POST["purge"])) {
|
||||
$cve->check($_POST["id"], PURGE);
|
||||
if ($cve->delete($_POST, 1)) {
|
||||
Event::log(
|
||||
$_POST["id"],
|
||||
"plugin_cve_cve",
|
||||
4,
|
||||
"inventory",
|
||||
sprintf(__('%1$s purges the CVE %2$s'), $_SESSION["glpiname"], $_POST["id"])
|
||||
);
|
||||
}
|
||||
$cve->redirectToList();
|
||||
} else if (isset($_POST["update"])) {
|
||||
$cve->check($_POST["id"], UPDATE);
|
||||
if ($cve->update($_POST)) {
|
||||
Event::log(
|
||||
$_POST["id"],
|
||||
"plugin_cve_cve",
|
||||
4,
|
||||
"inventory",
|
||||
sprintf(__('%1$s updates the CVE %2$s'), $_SESSION["glpiname"], $_POST["id"])
|
||||
);
|
||||
}
|
||||
Html::back();
|
||||
} else {
|
||||
Html::header(
|
||||
PluginCveCve::getTypeName(Session::getPluralNumber()),
|
||||
$_SERVER['PHP_SELF'],
|
||||
"tools",
|
||||
"PluginCveCveMenu",
|
||||
"cve"
|
||||
);
|
||||
|
||||
$id = 0;
|
||||
if (isset($_GET["id"])) {
|
||||
$id = $_GET["id"];
|
||||
}
|
||||
|
||||
$cve->display(['id' => $id]);
|
||||
Html::footer();
|
||||
}
|
20
front/cve.php
Normal file
20
front/cve.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* GLPI CVE Plugin - Main CVE list
|
||||
*/
|
||||
|
||||
include ("../../../inc/includes.php");
|
||||
|
||||
Session::checkRight("plugin_cve_cve", READ);
|
||||
|
||||
Html::header(
|
||||
PluginCveCve::getTypeName(Session::getPluralNumber()),
|
||||
$_SERVER['PHP_SELF'],
|
||||
"tools",
|
||||
"PluginCveCveMenu",
|
||||
"cve"
|
||||
);
|
||||
|
||||
Search::show('PluginCveCve');
|
||||
|
||||
Html::footer();
|
176
front/dashboard.php
Normal file
176
front/dashboard.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
* GLPI CVE Plugin - Dashboard Page
|
||||
*/
|
||||
|
||||
include ("../../../inc/includes.php");
|
||||
|
||||
Session::checkRight("plugin_cve_cve", READ);
|
||||
|
||||
Html::header(
|
||||
__('Dashboard', 'cve'),
|
||||
$_SERVER['PHP_SELF'],
|
||||
"tools",
|
||||
"PluginCveCveMenu",
|
||||
"dashboard"
|
||||
);
|
||||
|
||||
// Get statistical data
|
||||
$cve_stats = PluginCveCve::getCVEStatsDashboard();
|
||||
$severity_data = PluginCveCve::getCVESeverityDashboard();
|
||||
$recent_cves = PluginCveCve::getRecentCVEsDashboard();
|
||||
$alert_stats = PluginCveCveAlert::getAlertStats();
|
||||
|
||||
// Display dashboard
|
||||
echo "<div class='center'>";
|
||||
|
||||
// Statistics cards
|
||||
echo "<div class='dashboard-card-container'>";
|
||||
|
||||
// Critical vulnerabilities card
|
||||
echo "<div class='dashboard-card dashboard-card-critical'>";
|
||||
echo "<div class='dashboard-card-icon'><i class='fas fa-exclamation-triangle'></i></div>";
|
||||
echo "<div class='dashboard-card-content'>";
|
||||
echo "<div class='dashboard-card-title'>" . __('Critical Vulnerabilities', 'cve') . "</div>";
|
||||
echo "<div class='dashboard-card-value'>" . ($cve_stats['severity']['CRITICAL'] ?? 0) . "</div>";
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
|
||||
// High risk card
|
||||
echo "<div class='dashboard-card dashboard-card-high'>";
|
||||
echo "<div class='dashboard-card-icon'><i class='fas fa-exclamation-circle'></i></div>";
|
||||
echo "<div class='dashboard-card-content'>";
|
||||
echo "<div class='dashboard-card-title'>" . __('High Vulnerabilities', 'cve') . "</div>";
|
||||
echo "<div class='dashboard-card-value'>" . ($cve_stats['severity']['HIGH'] ?? 0) . "</div>";
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
|
||||
// New alerts card
|
||||
echo "<div class='dashboard-card dashboard-card-new'>";
|
||||
echo "<div class='dashboard-card-icon'><i class='fas fa-bell'></i></div>";
|
||||
echo "<div class='dashboard-card-content'>";
|
||||
echo "<div class='dashboard-card-title'>" . __('New Alerts', 'cve') . "</div>";
|
||||
echo "<div class='dashboard-card-value'>" . ($alert_stats['by_status']['NEW'] ?? 0) . "</div>";
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
|
||||
// Resolved card
|
||||
echo "<div class='dashboard-card dashboard-card-resolved'>";
|
||||
echo "<div class='dashboard-card-icon'><i class='fas fa-check-circle'></i></div>";
|
||||
echo "<div class='dashboard-card-content'>";
|
||||
echo "<div class='dashboard-card-title'>" . __('Resolved', 'cve') . "</div>";
|
||||
echo "<div class='dashboard-card-value'>" . ($cve_stats['status']['RESOLVED'] ?? 0) . "</div>";
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
|
||||
echo "</div>";
|
||||
|
||||
// Severity distribution chart
|
||||
if (!empty($severity_data)) {
|
||||
echo "<div class='dashboard-chart-container'>";
|
||||
echo "<h2>" . __('CVE Severity Distribution', 'cve') . "</h2>";
|
||||
|
||||
echo "<div id='severity-chart'>";
|
||||
// This would be replaced with an actual chart library in production
|
||||
echo "<div class='severity-chart-bars'>";
|
||||
foreach ($severity_data['labels'] as $i => $label) {
|
||||
$value = $severity_data['series'][$i]['data'][0] ?? 0;
|
||||
$color = $severity_data['series'][$i]['color'] ?? '#999999';
|
||||
|
||||
echo "<div class='severity-chart-bar-container'>";
|
||||
echo "<div class='severity-chart-label'>" . $label . "</div>";
|
||||
echo "<div class='severity-chart-bar' style='height: " . min(100, max(5, ($value / max(1, array_sum(array_column($severity_data['series'], 'data')[0])) * 100))) . "%; background-color: " . $color . ";'></div>";
|
||||
echo "<div class='severity-chart-value'>" . $value . "</div>";
|
||||
echo "</div>";
|
||||
}
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
// Recent CVEs table
|
||||
if (!empty($recent_cves)) {
|
||||
echo "<div class='dashboard-table-container'>";
|
||||
echo "<h2>" . __('Recent CVEs', 'cve') . "</h2>";
|
||||
|
||||
echo "<table class='tab_cadre_fixehov'>";
|
||||
echo "<tr>";
|
||||
foreach ($recent_cves['headers'] as $header) {
|
||||
echo "<th>" . $header . "</th>";
|
||||
}
|
||||
echo "</tr>";
|
||||
|
||||
foreach ($recent_cves['rows'] as $row) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td><a href='" . PluginCveCve::getFormURLWithID($row['id'] ?? 0) . "'>" . $row['cve_id'] . "</a></td>";
|
||||
echo "<td><span class='" . PluginCveCve::getSeverityClass($row['severity']) . "'>" . $row['severity'] . "</span></td>";
|
||||
echo "<td>" . $row['cvss_score'] . "</td>";
|
||||
echo "<td>" . Html::convDateTime($row['published']) . "</td>";
|
||||
echo "<td><span class='" . PluginCveCve::getStatusClass($row['status']) . "'>" . $row['status'] . "</span></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
echo "</table>";
|
||||
echo "<div class='center'><a href='cve.php'>" . __('View all CVEs', 'cve') . "</a></div>";
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
// Device Vulnerability Alerts
|
||||
echo "<div class='dashboard-table-container'>";
|
||||
echo "<h2>" . __('Alerts by Device', 'cve') . "</h2>";
|
||||
echo "<table class='tab_cadre_fixehov'>";
|
||||
echo "<tr>";
|
||||
echo "<th>" . __('Device', 'cve') . "</th>";
|
||||
echo "<th>" . __('Total Alerts', 'cve') . "</th>";
|
||||
echo "<th>" . __('Critical', 'cve') . "</th>";
|
||||
echo "<th>" . __('High', 'cve') . "</th>";
|
||||
echo "<th></th>";
|
||||
echo "</tr>";
|
||||
|
||||
// This would be populated with actual data from the database
|
||||
// Placeholder for demonstration purposes
|
||||
$deviceAlerts = [
|
||||
['name' => 'Windows Server 2019', 'alerts' => 12, 'critical' => 3, 'high' => 6],
|
||||
['name' => 'Ubuntu 20.04 LTS', 'alerts' => 8, 'critical' => 2, 'high' => 3],
|
||||
['name' => 'macOS Monterey', 'alerts' => 5, 'critical' => 0, 'high' => 2],
|
||||
['name' => 'Cisco IOS Router', 'alerts' => 7, 'critical' => 4, 'high' => 2],
|
||||
['name' => 'Database Server', 'alerts' => 9, 'critical' => 1, 'high' => 5],
|
||||
];
|
||||
|
||||
foreach ($deviceAlerts as $device) {
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>" . $device['name'] . "</td>";
|
||||
echo "<td>" . $device['alerts'] . "</td>";
|
||||
|
||||
// Critical alerts with badge
|
||||
echo "<td>";
|
||||
if ($device['critical'] > 0) {
|
||||
echo "<span class='cve-severity-critical badge'>" . $device['critical'] . "</span>";
|
||||
} else {
|
||||
echo "0";
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
// High alerts with badge
|
||||
echo "<td>";
|
||||
if ($device['high'] > 0) {
|
||||
echo "<span class='cve-severity-high badge'>" . $device['high'] . "</span>";
|
||||
} else {
|
||||
echo "0";
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
echo "<td class='center'>";
|
||||
echo "<a href='alert.php?criteria[0][field]=2&criteria[0][searchtype]=contains&criteria[0][value]=" . urlencode($device['name']) . "'>" . __('View', 'cve') . "</a>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
echo "</table>";
|
||||
echo "<div class='center'><a href='alert.php'>" . __('View all alerts', 'cve') . "</a></div>";
|
||||
echo "</div>";
|
||||
|
||||
echo "</div>"; // End of dashboard container
|
||||
|
||||
Html::footer();
|
3
js/README
Normal file
3
js/README
Normal file
@ -0,0 +1,3 @@
|
||||
This directory contains all JavaScript files for the CVE plugin.
|
||||
|
||||
The main file, cve.js, is automatically loaded by GLPI via the plugin's setup.php file.
|
@ -30,7 +30,7 @@
|
||||
<issues>https://github.com/tips-of-mine/GLPI-Plugin-CVE-Prototype/issues</issues>
|
||||
<readme>https://github.com/tips-of-mine/GLPI-Plugin-CVE-Prototype/blob/master/README.md</readme>
|
||||
<authors>
|
||||
<author>Hubert C. / Initiativa srl</author>
|
||||
<author>Hubert C. / Tips-Of-Mine</author>
|
||||
</authors>
|
||||
<versions>
|
||||
<version>
|
||||
@ -53,10 +53,12 @@
|
||||
<en>
|
||||
<tag>CVE-Prototype</tag>
|
||||
<tag>Security</tag>
|
||||
<tag>Vulnerability</tag>
|
||||
</en>
|
||||
<fr>
|
||||
<tag>CVE-Prototype</tag>
|
||||
<tag>Security</tag>
|
||||
<tag>Sécurité</tag>
|
||||
<tag>Vulnérabilité</tag>
|
||||
</fr>
|
||||
</tags>
|
||||
<screenshots>
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Handles plugin initialization, installation, and hooks
|
||||
*/
|
||||
|
||||
define('PLUGIN_CVE_VERSION', '1.0.0');
|
||||
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__);
|
||||
@ -115,9 +115,9 @@ function plugin_version_cve() {
|
||||
return [
|
||||
'name' => __('Vulnérabilité', 'cve'),
|
||||
'version' => PLUGIN_CVE_VERSION,
|
||||
'author' => 'Your Organization',
|
||||
'license' => 'GPL v2+',
|
||||
'homepage' => 'https://github.com/your-org/glpi-cve-plugin',
|
||||
'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,
|
||||
|
Reference in New Issue
Block a user