mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Compare commits
44 Commits
8e7e0afb1e
...
v24.7.18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4453ea59af | ||
|
|
31ecd6ac8c | ||
|
|
8e8493f638 | ||
|
|
adf24cebb6 | ||
|
|
5ac609e68e | ||
|
|
7f0debb04a | ||
|
|
a51571bd70 | ||
|
|
3af1f67956 | ||
|
|
9143b90bdf | ||
|
|
a892b8b5fb | ||
|
|
db621a110e | ||
|
|
4a3598e840 | ||
|
|
a19e268ea7 | ||
|
|
e9319cace3 | ||
|
|
74b2432729 | ||
|
|
d65b07685f | ||
|
|
a8dc4099e8 | ||
|
|
9c368982ce | ||
|
|
662394618b | ||
|
|
147166e46e | ||
|
|
fb8a7432cd | ||
|
|
fa00fa3004 | ||
|
|
294cfe80f2 | ||
|
|
b45e82b2a0 | ||
|
|
bf2ce3262d | ||
|
|
f468903b00 | ||
|
|
d706a156c0 | ||
|
|
71c631d784 | ||
|
|
460d2f4658 | ||
|
|
f502d93854 | ||
|
|
68fb1b7cbb | ||
|
|
942908d074 | ||
|
|
1aeed6b433 | ||
|
|
698876065c | ||
|
|
7e554242c2 | ||
|
|
129ae92141 | ||
|
|
25647023d0 | ||
|
|
fe752192e1 | ||
|
|
0ea0cd5ee0 | ||
|
|
bac78e926d | ||
|
|
d6125ef4e2 | ||
|
|
bf90ee81c7 | ||
|
|
ae74f1f538 | ||
|
|
3ae0daad3c |
4
.github/ISSUE_TEMPLATE/i-have-an-issue.yml
vendored
4
.github/ISSUE_TEMPLATE/i-have-an-issue.yml
vendored
@@ -1,5 +1,5 @@
|
||||
name: Bug Report
|
||||
description: 'When submitting an issue enable debug and have a look at the docs.'
|
||||
description: 'When submitting an issue enable LOG_LEVEL="trace" and have a look at the docs.'
|
||||
labels: ['bug 🐛']
|
||||
body:
|
||||
- type: checkboxes
|
||||
@@ -64,7 +64,7 @@ body:
|
||||
***Generally speaking, all bug reports should have logs provided.***
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
Additionally, any additional info? Screenshots? References? Anything that will give us more context about the issue you are encountering!
|
||||
You can use `tail -100 /app/front/log/app.log` in the container if you have troubles getting to the log files.
|
||||
You can use `tail -100 /app/front/log/app.log` in the container if you have trouble getting to the log files.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
|
||||
@@ -92,7 +92,6 @@ Thank you to all the wonderful people who are sponsoring this project.
|
||||
<!-- SPONSORS-LIST DO NOT MODIFY BELOW -->
|
||||
| All Sponsors |
|
||||
|---|
|
||||
| [fama-lama](https://github.com/fama-lama) |
|
||||
| [iptvcld](https://github.com/iptvcld) |
|
||||
|
||||
<!-- SPONSORS-LIST DO NOT MODIFY ABOVE -->
|
||||
|
||||
@@ -6,7 +6,7 @@ Please follow tips 1 - 4 to get a more detailed error.
|
||||
|
||||
When debugging an issue always set the highest log level:
|
||||
|
||||
`LOG_LEVEL='debug'`
|
||||
`LOG_LEVEL='trace'`
|
||||
|
||||
|
||||
## 2. Surfacing errors when container restarts 🔁
|
||||
|
||||
@@ -91,6 +91,16 @@ More on specifics below.
|
||||
|
||||
The `config.json` file is the manifest of the plugin. It contains mainly settings definitions and the mapping of Plugin objects to NetAlertX objects.
|
||||
|
||||
## Execution order
|
||||
|
||||
The execution order is used to specify wwhen a plugin is executed. This is useful if a plugin has access and surfaces more information than others. If a device is detected by 2 plugins and inserted into the `CurrentScan` table, the plugin with the higher priority (e.g.: `Level_0` is a higher priority than `Level_1`) will insert it's values first. These values (devices) will be then prioritized over any values inserted later.
|
||||
|
||||
```json
|
||||
{
|
||||
"execution_order" : "Layer_0"
|
||||
}
|
||||
```
|
||||
|
||||
## Supported data sources
|
||||
|
||||
Currently, these data sources are supported (valid `data_source` value).
|
||||
|
||||
@@ -240,6 +240,7 @@
|
||||
display: grid;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.main-header .logo {
|
||||
width: 100%;
|
||||
@@ -254,6 +255,15 @@
|
||||
.main-footer {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.fixed .content-wrapper, .fixed .right-side {
|
||||
padding-top: 50px;
|
||||
}
|
||||
.main-sidebar {
|
||||
padding-top: 50px;
|
||||
}
|
||||
.content-header {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-open .content-wrapper,
|
||||
@@ -1135,7 +1145,7 @@ input[readonly] {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#dropdownIcon li svg, #dropdownIcon li i{
|
||||
#dropdownIcon li svg, #dropdownIcon li i, .dropdownIcon li svg, .dropdownIcon li i, .icon-maxsize svg, .icon-maxsize i{
|
||||
height: 1.5em !important;
|
||||
}
|
||||
|
||||
@@ -1270,6 +1280,21 @@ input[readonly] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.networkNodeTabHeaders
|
||||
{
|
||||
max-width: 200px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
|
||||
.networkNodeTabHeaders .node-name
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* PLUGINS page */
|
||||
|
||||
@@ -379,55 +379,84 @@ function initListInteractionOptions(element) {
|
||||
// -------------------------------------------------------------------
|
||||
// Function to filter rows based on input text
|
||||
function filterRows(inputText) {
|
||||
|
||||
// open everything if input text is empty
|
||||
if (!inputText) {
|
||||
inputText = "";
|
||||
}
|
||||
|
||||
$(".panel").each(function () {
|
||||
var $panel = $(this);
|
||||
var $panelHeader = $panel.find('.panel-heading');
|
||||
var $panelBody = $panel.find('.panel-collapse');
|
||||
$(".panel").each(function () {
|
||||
var $panel = $(this);
|
||||
var $panelHeader = $panel.find('.panel-heading');
|
||||
var $panelBody = $panel.find('.panel-collapse');
|
||||
|
||||
var anyVisible = false; // Flag to check if any row is visible
|
||||
$panel.show()
|
||||
$panelHeader.show()
|
||||
$panelBody.collapse('show');
|
||||
|
||||
$panelBody.find(".table_row:not(.docs)").each(function () {
|
||||
var $row = $(this);
|
||||
$panelBody.find(".table_row:not(.docs)").each(function () {
|
||||
var $row = $(this)
|
||||
var rowId = $row.attr("id");
|
||||
var isMetadataRow = rowId && rowId.endsWith("__metadata");
|
||||
if (!isMetadataRow) {
|
||||
$row.show()
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
} else{
|
||||
// filter
|
||||
|
||||
// Check if the row ID ends with "__metadata"
|
||||
var rowId = $row.attr("id");
|
||||
var isMetadataRow = rowId && rowId.endsWith("__metadata");
|
||||
|
||||
// Always hide metadata rows
|
||||
if (isMetadataRow) {
|
||||
$row.hide();
|
||||
return; // Skip further processing for metadata rows
|
||||
}
|
||||
|
||||
var description = $row.find(".setting_description").text().toLowerCase();
|
||||
var codeName = $row.find(".setting_name code").text().toLowerCase();
|
||||
|
||||
if (
|
||||
description.includes(inputText.toLowerCase()) ||
|
||||
codeName.includes(inputText.toLowerCase())
|
||||
) {
|
||||
$row.show();
|
||||
anyVisible = true; // Set the flag to true if at least one row is visible
|
||||
$(".panel").each(function () {
|
||||
var $panel = $(this);
|
||||
var $panelHeader = $panel.find('.panel-heading');
|
||||
var $panelBody = $panel.find('.panel-collapse');
|
||||
|
||||
var anyVisible = false; // Flag to check if any row is visible
|
||||
|
||||
$panelBody.find(".table_row:not(.docs)").each(function () {
|
||||
var $row = $(this);
|
||||
|
||||
// Check if the row ID ends with "__metadata"
|
||||
var rowId = $row.attr("id");
|
||||
var isMetadataRow = rowId && rowId.endsWith("__metadata");
|
||||
|
||||
// Always hide metadata rows
|
||||
if (isMetadataRow) {
|
||||
$row.hide();
|
||||
return; // Skip further processing for metadata rows
|
||||
}
|
||||
|
||||
var description = $row.find(".setting_description").text().toLowerCase();
|
||||
var codeName = $row.find(".setting_name code").text().toLowerCase();
|
||||
|
||||
if (
|
||||
description.includes(inputText.toLowerCase()) ||
|
||||
codeName.includes(inputText.toLowerCase())
|
||||
) {
|
||||
$row.show();
|
||||
anyVisible = true; // Set the flag to true if at least one row is visible
|
||||
} else {
|
||||
$row.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Determine whether to hide or show the panel based on visibility of rows
|
||||
if (anyVisible) {
|
||||
$panelBody.collapse('show'); // Ensure the panel body is shown if there are visible rows
|
||||
$panelHeader.show(); // Show the panel header
|
||||
$panel.show(); // Show the entire panel if there are visible rows
|
||||
} else {
|
||||
$row.hide();
|
||||
$panelBody.collapse('hide'); // Hide the panel body if no rows are visible
|
||||
$panelHeader.hide(); // Hide the panel header if no rows are visible
|
||||
$panel.hide(); // Hide the entire panel if no rows are visible
|
||||
}
|
||||
});
|
||||
|
||||
// Determine whether to hide or show the panel based on visibility of rows
|
||||
if (anyVisible) {
|
||||
$panelBody.collapse('show'); // Ensure the panel body is shown if there are visible rows
|
||||
$panelHeader.show(); // Show the panel header
|
||||
$panel.show(); // Show the entire panel if there are visible rows
|
||||
} else {
|
||||
$panelBody.collapse('hide'); // Hide the panel body if no rows are visible
|
||||
$panelHeader.hide(); // Hide the panel header if no rows are visible
|
||||
$panel.hide(); // Hide the entire panel if no rows are visible
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -580,7 +609,6 @@ function reverseTransformers(val, transformers) {
|
||||
break;
|
||||
case "base64":
|
||||
// Implement base64 decoding logic
|
||||
console.log("💌");
|
||||
if (isBase64(val)) {
|
||||
val = atob(val);
|
||||
}
|
||||
@@ -772,7 +800,7 @@ function genListWithInputSet(options, valuesArray, targetField, transformers, pl
|
||||
if(labelName != '❌None')
|
||||
{
|
||||
labelName = reverseTransformers(labelName, transformers)
|
||||
console.log(transformers);
|
||||
// console.log(transformers);
|
||||
}
|
||||
|
||||
listHtml += `<li ${selected}>
|
||||
|
||||
@@ -370,9 +370,27 @@ $db->close();
|
||||
</div>
|
||||
<div class="tab-pane" id="tab_BackupRestore">
|
||||
<div class="db_info_table">
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
<button type="button" class="btn btn-default pa-btn bg-green dbtools-button" id="btnExportCSV" onclick="ExportCSV()"><?= lang('Maintenance_Tool_ExportCSV');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_ExportCSV_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
<button type="button" class="btn btn-default pa-btn pa-btn-delete bg-red dbtools-button" id="btnPiaBackupDBtoArchive" onclick="askPiaBackupDBtoArchive()"><?= lang('Maintenance_Tool_backup');?></button>
|
||||
<button type="button" class="btn btn-default pa-btn pa-btn-delete bg-red dbtools-button" id="btnImportCSV" onclick="askImportCSV()"><?= lang('Maintenance_Tool_ImportCSV');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_ImportCSV_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
<button type="button" class="btn btn-default pa-btn pa-btn-delete bg-red dbtools-button" id="btnImportPastedCSV" onclick="askImportPastedCSV()"><?= lang('Maintenance_Tool_ImportPastedCSV');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_ImportPastedCSV_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
<button type="button" class="btn btn-default pa-btn bg-green dbtools-button" id="btnPiaBackupDBtoArchive" onclick="askPiaBackupDBtoArchive()"><?= lang('Maintenance_Tool_backup');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_backup_text');?></div>
|
||||
</div>
|
||||
@@ -388,18 +406,6 @@ $db->close();
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_purgebackup_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
<button type="button" class="btn btn-default pa-btn bg-green dbtools-button" id="btnExportCSV" onclick="ExportCSV()"><?= lang('Maintenance_Tool_ExportCSV');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_ExportCSV_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
<button type="button" class="btn btn-default pa-btn pa-btn-delete bg-red dbtools-button" id="btnImportCSV" onclick="askImportCSV()"><?= lang('Maintenance_Tool_ImportCSV');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_ImportCSV_text');?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ---------------------------Logging-------------------------------------------- -->
|
||||
@@ -424,7 +430,7 @@ $db->close();
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="form-inline toggle">
|
||||
<input class="form-control" type="text" id="logsFilter" onchange="toggleFilter()" oninput="applyFilter()" placeholder="Filter lines with text..." />
|
||||
<input class="form-control" type="text" id="logsFilter" oninput="applyFilter()" placeholder="Filter lines with text..." />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -686,6 +692,26 @@ function ImportCSV()
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Import pasted CSV
|
||||
function askImportPastedCSV() {
|
||||
|
||||
// Add new icon as base64 string
|
||||
showModalInput ('<i class="fa fa-square-plus pointer"></i> <?= lang('Maintenance_Tool_ImportCSV_noti');?>', '<?= lang('Maintenance_Tool_ImportPastedCSV_noti_text');?>',
|
||||
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Okay');?>', 'ImportPastedCSV');
|
||||
}
|
||||
|
||||
function ImportPastedCSV()
|
||||
{
|
||||
var csv = $('#modal-input-textarea').val();
|
||||
csvBase64 = btoa(csv)
|
||||
// Execute
|
||||
$.post('php/server/devices.php?action=ImportCSV', { content: csvBase64 }, function(msg) {
|
||||
showMessage(msg);
|
||||
write_notification(`[Maintenance] Devices imported from pasted content`, 'info');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Switch Darkmode
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
|
||||
$decoded_icon = base64_decode($icon);
|
||||
$idFromMac = str_replace(":", "_", $node_mac);
|
||||
$str_tab_header = '<li class="'.$activetab.'">
|
||||
$str_tab_header = '<li class="networkNodeTabHeaders '.$activetab.' " >
|
||||
|
||||
<a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" >' // _id is added so it doesn't conflict with AdminLTE tab behavior
|
||||
.'<div class="icon">'.$decoded_icon.' </div>'.$node_name.' ' .$str_port.$node_badge.
|
||||
<a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" title="'.$node_name.' ">' // _id is added so it doesn't conflict with AdminLTE tab behavior
|
||||
.'<div class="icon">'.$decoded_icon.' </div> <span class="node-name">'.$node_name.'</span>' .$str_port.$node_badge.
|
||||
'</a>
|
||||
</li>';
|
||||
|
||||
@@ -464,7 +464,7 @@
|
||||
<script src="lib/treeviz/require.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
<script defer>
|
||||
$.get('php/server/devices.php?action=getDevicesList&status=all&forceDefaultOrder', function(data) {
|
||||
|
||||
rawData = JSON.parse (data)
|
||||
@@ -548,7 +548,6 @@
|
||||
{
|
||||
parentNodesCount++
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
name: node.name,
|
||||
@@ -616,7 +615,7 @@
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Handle network node click - select correct tab in teh bottom table
|
||||
// Handle network node click - select correct tab in the bottom table
|
||||
function handleNodeClick(event)
|
||||
{
|
||||
// console.log(event.target.offsetParent.offsetParent)
|
||||
@@ -631,14 +630,24 @@
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
var myTree;
|
||||
var visibleTreeArea = $(window).height()-135;
|
||||
var treeAreaHeight = visibleTreeArea > 800 ? 800 : visibleTreeArea;
|
||||
var visibleTreeArea = $(window).height()-155;
|
||||
var nodeWidth = 160;
|
||||
var emSize;
|
||||
var nodeHeight;
|
||||
var sizeCoefficient = 1
|
||||
|
||||
function initTree(myHierarchy)
|
||||
{
|
||||
console.log(myHierarchy)
|
||||
|
||||
// calculate the drawing area based on teh tree width and available screen size
|
||||
var treeAreaHeight = visibleTreeArea > 800 ? 800 : visibleTreeArea;
|
||||
let screenWidth = $('.content-header').width();
|
||||
let treeWidth = (nodeWidth + 20) * parentNodesCount;
|
||||
let treeAreaWidth = screenWidth < treeWidth ? treeWidth : screenWidth;
|
||||
|
||||
// init the drawing area size
|
||||
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${treeAreaWidth}px`)
|
||||
|
||||
if(myHierarchy.type == "")
|
||||
{
|
||||
@@ -655,7 +664,7 @@
|
||||
// nodeHeight = ((emSize*100*0.30).toFixed(0))
|
||||
nodeHeight = ((emSize*100*0.30).toFixed(0))
|
||||
|
||||
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${$('.content-header').width()}px`)
|
||||
console.log(Treeviz);
|
||||
|
||||
myTree = Treeviz.create({
|
||||
htmlId: "networkTree",
|
||||
@@ -704,7 +713,7 @@
|
||||
>
|
||||
<div class="netNodeText">
|
||||
<strong>${devicePort} ${deviceIcon}
|
||||
<span class="spanNetworkTree anonymizeDev">${nodeData.data.name}</span>
|
||||
<span class="spanNetworkTree anonymizeDev" >${nodeData.data.name}</span>
|
||||
</strong>
|
||||
${collapseExpandHtml}
|
||||
</div>
|
||||
@@ -719,8 +728,8 @@
|
||||
secondaryAxisNodeSpacing: 0.3,
|
||||
nodeHeight: nodeHeight.toString(),
|
||||
marginTop: '5',
|
||||
hasZoom: false,
|
||||
hasPan: false,
|
||||
hasZoom: true,
|
||||
hasPan: true,
|
||||
// marginLeft: '15',
|
||||
idKey: "id",
|
||||
hasFlatData: false,
|
||||
@@ -730,7 +739,7 @@
|
||||
relationnalField: "children",
|
||||
});
|
||||
|
||||
console.log(myHierarchy)
|
||||
|
||||
|
||||
myTree.refresh(myHierarchy);
|
||||
|
||||
|
||||
@@ -463,15 +463,29 @@ function ExportCSV() {
|
||||
// Import CSV of devices
|
||||
//------------------------------------------------------------------------------
|
||||
function ImportCSV() {
|
||||
$file = '../../../config/devices.csv';
|
||||
|
||||
if (file_exists($file)) {
|
||||
global $db;
|
||||
$skipped = "";
|
||||
$error = "";
|
||||
global $db;
|
||||
$file = '../../../config/devices.csv';
|
||||
$data = "";
|
||||
$skipped = "";
|
||||
$error = "";
|
||||
|
||||
// check if content passed in query string
|
||||
if(isset ($_POST['content']) && !empty ($_POST['content']))
|
||||
{
|
||||
// Decode the Base64 string
|
||||
$data = base64_decode($_POST['content']);
|
||||
|
||||
} else if (file_exists($file)) { // try to get the data form the file
|
||||
|
||||
// Read the CSV file
|
||||
$data = file_get_contents($file);
|
||||
} else {
|
||||
echo lang('BackDevices_DBTools_ImportCSVMissing');
|
||||
}
|
||||
|
||||
if($data != "")
|
||||
{
|
||||
$lines = explode("\n", $data);
|
||||
|
||||
// Get the column headers from the first line of the CSV
|
||||
@@ -517,8 +531,6 @@ function ImportCSV() {
|
||||
// An error occurred while writing to the DB, display the last error message
|
||||
echo lang('BackDevices_DBTools_ImportCSVError') . "\n" . $error . "\n" . $sql . "\n\n" . $result;
|
||||
}
|
||||
} else {
|
||||
echo lang('BackDevices_DBTools_ImportCSVMissing');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ if ($ENABLED_DARKMODE === True) {
|
||||
</a>
|
||||
<ul class="treeview-menu" style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('settings.php') ) ){ echo 'block'; } else {echo 'none';} ?>;">
|
||||
<li>
|
||||
<a href="settings.php#pageTitle"> <?= lang("settings_enabled");?> </a>
|
||||
<a href="settings.php#settingsOverview"> <?= lang("settings_enabled");?> </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="settings.php#core_content_header"> <?= lang("settings_core_label");?> </a>
|
||||
@@ -350,13 +350,13 @@ if ($ENABLED_DARKMODE === True) {
|
||||
<a href="settings.php#system_content_header"> <?= lang("settings_system_label");?> </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="settings.php#device_scanner_content_header"> <?= lang("settings_device_scanners_label");?> </a>
|
||||
<a href="settings.php#device_scanners_content_header"> <?= lang("settings_device_scanners_label");?> </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="settings.php#other_content_header"> <?= lang("settings_other_scanners_label");?> </a>
|
||||
<a href="settings.php#other_scanners_content_header"> <?= lang("settings_other_scanners_label");?> </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="settings.php#publisher_content_header"> <?= lang("settings_publishers_label");?> </a>
|
||||
<a href="settings.php#publishers_content_header"> <?= lang("settings_publishers_label");?> </a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
@@ -416,7 +416,7 @@ if ($ENABLED_DARKMODE === True) {
|
||||
// Generate work-in-progress icons
|
||||
function workInProgress() {
|
||||
|
||||
if($(".work-in-progress").html().trim() == "")
|
||||
if($(".work-in-progress").length > 0 && $(".work-in-progress").html().trim() == "")
|
||||
{
|
||||
$(".work-in-progress").append(`
|
||||
<a href="https://github.com/jokob-sk/NetAlertX/issues" target="_blank">
|
||||
|
||||
39
front/php/templates/language/de_de.json
Executable file → Normal file
39
front/php/templates/language/de_de.json
Executable file → Normal file
@@ -13,7 +13,7 @@
|
||||
"APPRISE_URL_name": "Apprise notification URL",
|
||||
"About_Design": "Designed for:",
|
||||
"About_Exit": "Abmelden",
|
||||
"About_Title": "Open Source Network Guard",
|
||||
"About_Title": "Netzwerksicherheitsscanner und Benachrichtigungsframework",
|
||||
"AppEvents_DateTimeCreated": "protokolliert",
|
||||
"AppEvents_Extra": "Extra",
|
||||
"AppEvents_GUID": "Anwendungsereignis-GUID",
|
||||
@@ -93,17 +93,17 @@
|
||||
"DevDetail_MainInfo_Group": "Gruppe",
|
||||
"DevDetail_MainInfo_Location": "Standort",
|
||||
"DevDetail_MainInfo_Name": "Name",
|
||||
"DevDetail_MainInfo_Network": "Netzwerk Knoten",
|
||||
"DevDetail_MainInfo_Network_Port": "Netzwerk Knoten Port",
|
||||
"DevDetail_MainInfo_Network": "<i class=\"fa fa-server\"></i> Knoten (MAC)",
|
||||
"DevDetail_MainInfo_Network_Port": "<i class=\"fa fa-ethernet\"></i> Port",
|
||||
"DevDetail_MainInfo_Network_Site": "",
|
||||
"DevDetail_MainInfo_Network_Title": "<i class=\"fa fa-network-wired\"></i> Network",
|
||||
"DevDetail_MainInfo_Owner": "Eigen­tümer",
|
||||
"DevDetail_MainInfo_SSID": "",
|
||||
"DevDetail_MainInfo_Title": "Haupt Infos",
|
||||
"DevDetail_MainInfo_Title": "<i class=\"fa fa-pencil\"></i> Hauptinformation",
|
||||
"DevDetail_MainInfo_Type": "Typ",
|
||||
"DevDetail_MainInfo_Vendor": "Hersteller",
|
||||
"DevDetail_MainInfo_mac": "MAC",
|
||||
"DevDetail_Network_Node_hover": "Select the parent network device the current device is connected to to populate the Network tree.",
|
||||
"DevDetail_Network_Node_hover": "Wählen Sie das Elternnetzgerät aus, an das das aktuelle Gerät angeschlossen ist, um den Netzwerkbaum zu erstellen.",
|
||||
"DevDetail_Network_Port_hover": "The port this device is connected to on the parent network device. If left empty a wifi icon is displayed in the Network tree.",
|
||||
"DevDetail_Nmap_Scans": "Nmap Scans",
|
||||
"DevDetail_Nmap_Scans_desc": "Hier kannst du manuelle NMAP Scans starten. Reguläre automatische NMAP Scans können mit dem Services & Ports (NMAP) Plugin geplant werden. Gehe zu den <a href='/settings.php' target='_blank'>Einstellungen</a> um mehr herauszufinden.",
|
||||
@@ -129,7 +129,7 @@
|
||||
"DevDetail_SessionInfo_LastSession": "Letzte Sitzung",
|
||||
"DevDetail_SessionInfo_StaticIP": "Statische IP",
|
||||
"DevDetail_SessionInfo_Status": "Status",
|
||||
"DevDetail_SessionInfo_Title": "Sitzungsinfos",
|
||||
"DevDetail_SessionInfo_Title": "<i class=\"fa fa-calendar\"></i> Sitzungsinformation",
|
||||
"DevDetail_SessionTable_Additionalinfo": "Zusätzliche Info",
|
||||
"DevDetail_SessionTable_Connection": "Verbindung",
|
||||
"DevDetail_SessionTable_Disconnection": "Trennung",
|
||||
@@ -140,13 +140,13 @@
|
||||
"DevDetail_Shortcut_DownAlerts": "Down Meldungen",
|
||||
"DevDetail_Shortcut_Presence": "Anwesenheit",
|
||||
"DevDetail_Shortcut_Sessions": "Sitzungen",
|
||||
"DevDetail_Tab_Details": "Details",
|
||||
"DevDetail_Tab_Events": "Ereignisse",
|
||||
"DevDetail_Tab_Details": "<i class=\"fa fa-info-circle\"></i> Details",
|
||||
"DevDetail_Tab_Events": "<i class=\"fa fa-bolt\"></i> Ereignisse",
|
||||
"DevDetail_Tab_EventsTableDate": "Datum",
|
||||
"DevDetail_Tab_EventsTableEvent": "Ereignistype",
|
||||
"DevDetail_Tab_EventsTableIP": "IP",
|
||||
"DevDetail_Tab_EventsTableInfo": "Zusätzliche Informationen",
|
||||
"DevDetail_Tab_Nmap": "Nmap",
|
||||
"DevDetail_Tab_Nmap": "<i class=\"fa fa-ethernet\"></i> Nmap",
|
||||
"DevDetail_Tab_NmapEmpty": "An diesem Gerät wurden keine offenen Ports mit Nmap gefunden.",
|
||||
"DevDetail_Tab_NmapTableExtra": "Extra",
|
||||
"DevDetail_Tab_NmapTableHeader": "Ergebnisse geplanter Scans",
|
||||
@@ -157,8 +157,8 @@
|
||||
"DevDetail_Tab_NmapTableText": "Erstelle einen Plan über die<a href=\"/settings.php#NMAP_ACTIVE\">Einstellungen</a>",
|
||||
"DevDetail_Tab_NmapTableTime": "Zeit",
|
||||
"DevDetail_Tab_Plugins": "<i class=\"fa fa-plug\"></i> Plugins",
|
||||
"DevDetail_Tab_Presence": "Anwesenheit",
|
||||
"DevDetail_Tab_Sessions": "Sitzungen",
|
||||
"DevDetail_Tab_Presence": "<i class=\"fa fa-calendar\"></i> Anwesenheit",
|
||||
"DevDetail_Tab_Sessions": "<i class=\"fa fa-list-ol\"></i> Sitzungen",
|
||||
"DevDetail_Tab_Tools": "<i class=\"fa fa-screwdriver-wrench\"></i> Tools",
|
||||
"DevDetail_Tab_Tools_Internet_Info_Description": "Das Internet-Info-Tool zeigt Informationen über die Internetverbindung an, wie z. B. IP-Adresse, Stadt, Land, Ortsvorwahl und Zeitzone.",
|
||||
"DevDetail_Tab_Tools_Internet_Info_Error": "Es ist ein Fehler aufgetreten",
|
||||
@@ -314,17 +314,17 @@
|
||||
"Gen_Work_In_Progress": "Keine Finalversion, feedback bitte unter: https://github.com/jokob-sk/NetAlertX/issues",
|
||||
"General_display_name": "Allgemein",
|
||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Dies ist eine Wartungseinstellung. Geräte markiert als <b>Neues Gerät</b> werden gelöscht, wenn ihre <b>Erste Sitzung</b> länger her ist als die angegebenen Stunden in dieser Einstellung. <code>0</code> deaktiviert diese Funktion. Nutzen Sie diese Einstellung, um <b>Neue Geräte</b> automatisch nach <code>X</code> Stunden zu löschen.",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Dies ist eine Wartungseinstellung. Wenn aktiviert (<code>0</code> bedeutet deaktiviert), werden als <b>\"Neues Gerät\"</b> markierte Geräte gelöscht, wenn ihre <b>erste Sitzung</b> länger her ist als in dieser Einstellung angegeben. Verwenden Sie diese Einstellung, wenn Sie <b>Neue Geräte</b> nach <code>X</code> Stunden automatisch löschen wollen.",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "Neue Geräte speichern für",
|
||||
"HelpFAQ_Cat_Detail": "Detailansicht",
|
||||
"HelpFAQ_Cat_Detail_300_head": "Was bedeutet ",
|
||||
"HelpFAQ_Cat_Detail_300_text_a": "meint ein Netzwerkgerät (welches den typ AP, Gateway, Firewall, Hypervisor, Powerline, Switch, WLAN, PLC, Router,USB LAN Adapter, USB WIFI Adapter, or Internet eingestellt hat)",
|
||||
"HelpFAQ_Cat_Detail_300_text_a": "meint ein Netzwerkgerät (ein Gerät vom Typ AP, Gateway, Firewall, Hypervisor, Powerline, Switch, WLAN, PLC, Router, USB-LAN-Adapter oder Internet). Benutzerdefinierte Typen können über die <code>NETWORK_DEVICE_TYPES</code> Einstellung hinzugefügt werden.",
|
||||
"HelpFAQ_Cat_Detail_300_text_b": "bezeichnet die Anschlussnummer/Portnummer, an der das gerade bearbeitete Gerät mit diesem Netzwerkgerät verbunden ist. Siehe <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md\">diese Dokumentation</a> für mehr informationen.",
|
||||
"HelpFAQ_Cat_Detail_301_head_a": "Wann wird nun gescannt? Bei ",
|
||||
"HelpFAQ_Cat_Detail_301_head_b": " steht 1min aber der Graph zeigt 5min - Abstände an.",
|
||||
"HelpFAQ_Cat_Detail_301_text": "Den zeitlichen Abstand zwischen den Scans legt der \"Cronjob\" fest, welcher standardmäßig auf 5min eingestellt ist. Die Benennung \"1min\" bezieht sich auf die zu erwartende Dauer des Scans. Abhängig vor der Netzwerkkonfiguration kann diese Zeitangabe variieren. Um den Cronjob zu bearbeiten, kannst du im Terminal/der Konsole <span class=\"text-danger help_faq_code\">crontab -e</span> eingeben und den Intervall ändern.",
|
||||
"HelpFAQ_Cat_Detail_302_head_a": "Was bedeutet ",
|
||||
"HelpFAQ_Cat_Detail_302_head_b": " und warum kann ich das nicht auswählen?",
|
||||
"HelpFAQ_Cat_Detail_302_head_b": "und warum kann ich das nicht auswählen?",
|
||||
"HelpFAQ_Cat_Detail_302_text": "Einige moderne Geräte generieren aus Datenschutzgründen zufällige MAC-Adressen, die keinem Hersteller mehr zugeordnet werden können und welche sich mit jeder neuen Verbindung ändern. NetAlertX erkennt, ob es sich um eine solche zufällige MAC-Adresse handelt und aktiviert dieses \"Feld\" automatisch. Um das Verhalten abzustellen, musst du in deinem Endgerät schauen, wie du die MAC-Adressen-Generierung deaktivierst.",
|
||||
"HelpFAQ_Cat_Detail_303_head": "Was ist Nmap und wozu dient es?",
|
||||
"HelpFAQ_Cat_Detail_303_text": "Nmap ist ein Netzwerkscanner mit vielfältigen Möglichkeiten.<br> Wenn ein neues Gerät in deiner Liste auftaucht, hast du die Möglichkeit über den Nmap-Scan genauere Informationen über das Gerät zu erhalten.",
|
||||
@@ -393,11 +393,14 @@
|
||||
"Maintenance_Tool_ExportCSV": "CSV Export",
|
||||
"Maintenance_Tool_ExportCSV_noti": "CSV Export",
|
||||
"Maintenance_Tool_ExportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei erstellen wollen?",
|
||||
"Maintenance_Tool_ExportCSV_text": "Generiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Dies kann auch durch das Besuchen dieser URL <code>your NetAlertX url/php/server/devices.php?action=ExportCSV</code> ausgelöst werden.",
|
||||
"Maintenance_Tool_ExportCSV_text": "Generiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Dies kann auch durch das Besuchen der URL <code>your NetAlertX url/php/server/devices.php?action=ExportCSV</code> oder durch Aktivieren des <a href=\"settings.php#CSVBCKP_header\">CSV-Backups</a> ausgelöst werden.",
|
||||
"Maintenance_Tool_ImportCSV": "CSV Import",
|
||||
"Maintenance_Tool_ImportCSV_noti": "CSV Import",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei importieren wollen? Dies wird alle Geräte in der Datenbank überschreiben.",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei importieren wollen? Dies wird <b>alle Geräte in der Datenbank überschreiben</b>.",
|
||||
"Maintenance_Tool_ImportCSV_text": "Machen Sie ein Backup, bevor Sie diese Funktion nutzen. Importiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Um dies zu tun platziere die <b>devices.csv</b> benannte CSV-Datei in deinen <b>/config</b> Ordner.",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "arp-Scan stoppen/starten",
|
||||
"Maintenance_Tool_arpscansw_noti": "arp-Scan stoppen/starten",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "Wenn der Scan aus ist, bleibt er so lange aus bis er wieder aktiviert wird.",
|
||||
@@ -733,7 +736,7 @@
|
||||
"Webhooks_display_name": "Webhooks",
|
||||
"Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>",
|
||||
"devices_old": "Aktualisiert...",
|
||||
"general_event_description": " The event you have triggered might take a while until background processes finish. The execution ended once you see <code>finished</code> below. Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you didn not get the expected result. <br/> <br/> Status: ",
|
||||
"general_event_description": "Das Ereignis, das Sie ausgelöst haben, könnte eine Weile dauern, bis Hintergrundprozesse abgeschlossen sind. Die Ausführung endet, wenn die unten ausgeführte Warteschlangen abgearbeitet ist. (Siehe <a href='/maintenance.php#tab_Logging'>error log</a>, wenn Probleme auftreten.)<br/> <br/> Ausführungsschlange:",
|
||||
"general_event_title": "Executing an ad-hoc event",
|
||||
"report_guid": "",
|
||||
"report_guid_missing": "",
|
||||
@@ -768,4 +771,4 @@
|
||||
"settings_update_item_warning": "",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Save your changes at first before you test your settings."
|
||||
}
|
||||
}
|
||||
|
||||
9
front/php/templates/language/en_us.json
Executable file → Normal file
9
front/php/templates/language/en_us.json
Executable file → Normal file
@@ -370,8 +370,11 @@
|
||||
"Maintenance_Tool_ExportCSV_text": "Generate a CSV (comma separated value) file containing the list of Devices including the Network relationships between Network Nodes and connected devices. You can also trigger this by accessing this URL <code>your NetAlertX url/php/server/devices.php?action=ExportCSV</code> or by enabling the <a href=\"settings.php#CSVBCKP_header\">CSV Backup</a> plugin.",
|
||||
"Maintenance_Tool_ImportCSV": "CSV Import",
|
||||
"Maintenance_Tool_ImportCSV_noti": "CSV Import",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Are you sure you want to import the CSV file? This will completely overwrite the devices in your database.",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Are you sure you want to import the CSV file? This will completely <b>overwrite</b> the devices in your database.",
|
||||
"Maintenance_Tool_ImportCSV_text": "Before using this function, please make a backup. Import a CSV (comma separated value) file containing the list of Devices including the Network relationships between Network Nodes and connected devices. To do that place the CSV file named <b>devices.csv</b> into your <b>/config</b> folder.",
|
||||
"Maintenance_Tool_ImportPastedCSV": "CSV Import (Paste)",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "Are you sure you want to import the pasted CSV? This will completely <b>overwrite</b> the devices in your database.",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "Before using this function, please make a backup. Import a CSV (comma separated value) file containing the list of Devices including the Network relationships between Network Nodes and connected devices.",
|
||||
"Maintenance_Tool_arpscansw": "Toggle arp-Scan (on/off)",
|
||||
"Maintenance_Tool_arpscansw_noti": "Toggle arp-Scan on or off",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "When the scan has been switched off it remains off until it is activated again.",
|
||||
@@ -652,7 +655,7 @@
|
||||
"UI_REFRESH_description": "Enter number of seconds after which the UI reloads. Set to <code>0</code> to disable.",
|
||||
"UI_REFRESH_name": "Auto-refresh UI",
|
||||
"devices_old": "Refreshing...",
|
||||
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
|
||||
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
|
||||
"general_event_title": "Executing an ad-hoc event",
|
||||
"report_guid": "Notification guid:",
|
||||
"report_guid_missing": "Linked notification not found. There is a small delay between recently sent notifications and them being available. Referesh your page and cache after a few seconds. It's also possible the selected notification have been deleted during maintenance as specified in the <code>DBCLNP_NOTIFI_HIST</code> setting. <br/> <br/>The latest notification is displayed instead. The missing notification has the following GUID:",
|
||||
@@ -687,4 +690,4 @@
|
||||
"settings_update_item_warning": "Update the value below. Be careful to follow the previous format. <b>Validation is not performed.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Save your changes at first before you test your settings."
|
||||
}
|
||||
}
|
||||
|
||||
9
front/php/templates/language/es_es.json
Executable file → Normal file
9
front/php/templates/language/es_es.json
Executable file → Normal file
@@ -396,6 +396,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "Importación CSV",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "¿Está seguro de que quiere importar el archivo CSV? Esto sobrescribirá completamente los dispositivos de su base de datos.",
|
||||
"Maintenance_Tool_ImportCSV_text": "Antes de usar esta función, haga una copia de seguridad. Importe un archivo CSV (valor separado por comas) que contiene la lista de dispositivos, incluidas las relaciones de red entre nodos de red y dispositivos conectados. Para hacer eso, coloque el archivo CSV llamado <b> devices.csv </b> en su carpeta <b>/config </b>.",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "Activar arp-scan (on/off)",
|
||||
"Maintenance_Tool_arpscansw_noti": "Activar arp-scan on or off",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "Cuando el escaneo se ha apagado, permanece apagado hasta que se active nuevamente.",
|
||||
@@ -744,7 +747,7 @@
|
||||
"settings_core_label": "Núcleo",
|
||||
"settings_device_scanners": "Los escáneres de los dispositivos se utilizan para descubrir dispositivos que escriben en la tabla de base de datos de CurrentScan.",
|
||||
"settings_device_scanners_icon": "fa-solid fa-magnifying-glass-plus",
|
||||
"settings_device_scanners_info": "",
|
||||
"settings_device_scanners_info": "Cargue aún más escáneres de dispositivos con el ajuste <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_label": "Escáneres de dispositivos",
|
||||
"settings_enabled": "Configuración activada",
|
||||
"settings_enabled_icon": "fa-solid fa-toggle-on",
|
||||
@@ -759,7 +762,7 @@
|
||||
"settings_other_scanners_label": "Otros escáneres",
|
||||
"settings_publishers": "Puertas de enlace para las notificación habilitadas: editores, que enviarán una notificación según su configuración.",
|
||||
"settings_publishers_icon": "fa-solid fa-paper-plane",
|
||||
"settings_publishers_info": "",
|
||||
"settings_publishers_info": "Cargue más editor@s con el ajuste <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_publishers_label": "Editores",
|
||||
"settings_saved": "<br/>Ajustes guardados. <br/><br/> Recargando... <br/><i class=\"ion ion-ios-loop-strong fa-spin fa-2x fa-fw\"></i> <br/>",
|
||||
"settings_system_icon": "fa-solid fa-gear",
|
||||
@@ -767,4 +770,4 @@
|
||||
"settings_update_item_warning": "Actualice el valor a continuación. Tenga cuidado de seguir el formato anterior. <b>O la validación no se realiza.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Guarda tus cambios antes de probar nuevos ajustes."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
{
|
||||
"API_CUSTOM_SQL_description": "",
|
||||
"API_CUSTOM_SQL_description": "Vous pouvez specifier votre propre requête SQL qui retournera un fichier JSON et l'exposer via <a href=\"/api/table_custom_endpoint.json\" target=\"_blank\"><code>table_custom_endpoint.json</code> file endpoint</a>.",
|
||||
"API_CUSTOM_SQL_name": "Point de terminaison personnalisé",
|
||||
"API_display_name": "API",
|
||||
"API_icon": "",
|
||||
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
|
||||
"About_Design": "Conçu pour :",
|
||||
"About_Exit": "Quitter",
|
||||
"About_Title": "Analyse de la sécurité du réseau et cadre de notification",
|
||||
"AppEvents_DateTimeCreated": "Journalisé",
|
||||
"AppEvents_Extra": "Extra",
|
||||
"AppEvents_GUID": "",
|
||||
"AppEvents_Helper1": "",
|
||||
"AppEvents_Helper2": "",
|
||||
"AppEvents_Helper3": "",
|
||||
"AppEvents_Helper1": "Helper 1",
|
||||
"AppEvents_Helper2": "Helper 2",
|
||||
"AppEvents_Helper3": "Helper 3",
|
||||
"AppEvents_ObjectForeignKey": "Clé étrangère",
|
||||
"AppEvents_ObjectIndex": "Index",
|
||||
"AppEvents_ObjectIsArchived": "Est archivé (au moment de l'enregistrement)",
|
||||
"AppEvents_ObjectIsNew": "",
|
||||
"AppEvents_ObjectIsNew": "nouveau (au moment de l'enregistrement dans le journal)",
|
||||
"AppEvents_ObjectPlugin": "Greffon lié",
|
||||
"AppEvents_ObjectPrimaryID": "",
|
||||
"AppEvents_ObjectSecondaryID": "",
|
||||
"AppEvents_ObjectStatus": "Statut (au moment de l'enregistrement)",
|
||||
"AppEvents_ObjectPrimaryID": "Identité primaire",
|
||||
"AppEvents_ObjectSecondaryID": "Indentité secondaire",
|
||||
"AppEvents_ObjectStatus": "Status (au moment de l'enregistrement)",
|
||||
"AppEvents_ObjectStatusColumn": "Colonne d'état",
|
||||
"AppEvents_ObjectType": "Type d'objet",
|
||||
"AppEvents_Plugin": "Greffon",
|
||||
"AppEvents_Type": "Type",
|
||||
"BackDevDetail_Actions_Ask_Run": "",
|
||||
"BackDevDetail_Actions_Not_Registered": "",
|
||||
"BackDevDetail_Actions_Title_Run": "",
|
||||
"BackDevDetail_Copy_Ask": "",
|
||||
"BackDevDetail_Actions_Ask_Run": "Voulez vous executer cette commande ?",
|
||||
"BackDevDetail_Actions_Not_Registered": "Action non enregistrée ",
|
||||
"BackDevDetail_Actions_Title_Run": "Execute Action",
|
||||
"BackDevDetail_Copy_Ask": "Copie les details des objets selectioné dans la liste (tout ce qui est sur cette page sura remplacé)?",
|
||||
"BackDevDetail_Copy_Title": "Copier les détails",
|
||||
"BackDevDetail_Tools_WOL_error": "",
|
||||
"BackDevDetail_Tools_WOL_okay": "",
|
||||
"BackDevices_Arpscan_disabled": "",
|
||||
"BackDevices_Arpscan_enabled": "",
|
||||
"BackDevices_Backup_CopError": "",
|
||||
"BackDevices_Backup_Failed": "",
|
||||
"BackDevDetail_Tools_WOL_error": "Cette commande N'A PAS été exécutée.",
|
||||
"BackDevDetail_Tools_WOL_okay": "Commande Exécutée.",
|
||||
"BackDevices_Arpscan_disabled": "Arp-Scan Suspendu",
|
||||
"BackDevices_Arpscan_enabled": "Apr-Scan Activé",
|
||||
"BackDevices_Backup_CopError": "La base de donnée initiale n'a pas pu être sauvegardée.",
|
||||
"BackDevices_Backup_Failed": "La sauvegarde a été partiellement complétée. L'archive n'a pas pu être crée ou est vide.",
|
||||
"BackDevices_Backup_okay": "",
|
||||
"BackDevices_DBTools_DelDevError_a": "Erreur lors de la suppression de l'appareil",
|
||||
"BackDevices_DBTools_DelDevError_b": "Erreur lors de la suppression des appareils",
|
||||
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "Importation CSV",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Êtes-vous sûr de vouloir importer le fichier CSV ? Cela écrasera complètement les appareils de votre base de données.",
|
||||
"Maintenance_Tool_ImportCSV_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "Basculer l'arp-Scan (activé/désactivé)",
|
||||
"Maintenance_Tool_arpscansw_noti": "Activer ou désactiver l'arp-Scan",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "Une fois le scan désactivé, il reste désactivé jusqu'à ce qu'il soit réactivé.",
|
||||
@@ -687,4 +690,4 @@
|
||||
"settings_update_item_warning": "",
|
||||
"test_event_icon": "",
|
||||
"test_event_tooltip": ""
|
||||
}
|
||||
}
|
||||
|
||||
5
front/php/templates/language/it_it.json
Executable file → Normal file
5
front/php/templates/language/it_it.json
Executable file → Normal file
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "Importa CSV",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Sei sicuro di voler importare il file CSV? Questa operazione sovrascriverà tutti i dispositivi presenti nel database.",
|
||||
"Maintenance_Tool_ImportCSV_text": "Prima di utilizzare questa funzione, esegui un backup. Importa un file CSV (comma separated value) contenente la lista dei dispositivi incluse le relazioni di rete tra i nodi di rete e i dispositivi connessi. Per far ciò posiziona il file CSV denominato <b>devices.csv</b> nella cartella <b>/config</b>.",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "Attiva/disattiva arp-Scan",
|
||||
"Maintenance_Tool_arpscansw_noti": "Attiva o disattiva arp-Scan",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "Una volta disattivata la scansione rimane disattivata finché non viene nuovamente attivata.",
|
||||
@@ -687,4 +690,4 @@
|
||||
"settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,8 @@ function lang($key)
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
// HTML encode the result before returning
|
||||
return str_replace("'", ''', $result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
5
front/php/templates/language/nb_no.json
Executable file → Normal file
5
front/php/templates/language/nb_no.json
Executable file → Normal file
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "Importer CSV",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Er du sikker på at du vil importere CSV-filen? Dette vil fullstendig overskrive enhetene i databasen din.",
|
||||
"Maintenance_Tool_ImportCSV_text": "Før du bruker denne funksjonen, vennligst ta en sikkerhetskopi. Importer en CSV-fil (kommaseparert verdi) som inneholder listen over enheter, inkludert nettverksrelasjoner mellom nettverksnoder og tilkoblede enheter. For å gjøre det, plasser CSV-filen med navnet <b>devices.csv</b> i mappen <b>/config</b>.",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "Slå arp-Scan (på/av)",
|
||||
"Maintenance_Tool_arpscansw_noti": "Slå arp-Scan på eller av",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "Når skanningen er slått av, forblir den slått av til den aktiveres igjen.",
|
||||
@@ -687,4 +690,4 @@
|
||||
"settings_update_item_warning": "Oppdater verdien nedenfor. Pass på å følge forrige format. <b>Validering etterpå utføres ikke.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Lagre endringene først, før du tester innstillingene dine."
|
||||
}
|
||||
}
|
||||
|
||||
5
front/php/templates/language/pl_pl.json
Executable file → Normal file
5
front/php/templates/language/pl_pl.json
Executable file → Normal file
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "Import CSV",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Jesteś pewien że chcesz zaimportować plik CSV? Nadpisze to wszystkie urządzenie w bazie danych.",
|
||||
"Maintenance_Tool_ImportCSV_text": "Przed użyciem tej funkcji, wykonaj proszę kopię zapasową. Zaimportuj plik CSV (wartości oddzielone przecinkami) zawierający listę Urządzeń, w tym Relacji Sieci między sieciowymi węzłami i podłączonymi urządzeniami. By to zrobić umieść plik CSV nazwany <b>devices.csv</b> do twojego folderu <b>/config</b>.",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "Przełącz Skan-arp (wł/wył)",
|
||||
"Maintenance_Tool_arpscansw_noti": "Przełącz Skan-arp na włączony lub wyłączony",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "Kiedy skan zostanie przełączony na wył zostaje wyłączony do czasu ponownej aktywacji.",
|
||||
@@ -687,4 +690,4 @@
|
||||
"settings_update_item_warning": "Zaktualizuj poniższą wartość. Zachowaj ostrożność i postępuj zgodnie z poprzednim formatem. <b>Walidacja nie jest wykonywana.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Zapisz zmiany zanim będziesz testować swoje ustawienia."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportCSV_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "",
|
||||
"Maintenance_Tool_arpscansw_noti": "",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "",
|
||||
|
||||
15
front/php/templates/language/ru_ru.json
Executable file → Normal file
15
front/php/templates/language/ru_ru.json
Executable file → Normal file
@@ -358,9 +358,9 @@
|
||||
"Login_Toggle_Alert_headline": "Предупреждение о пароле!",
|
||||
"Login_Toggle_Info": "Информация о пароле",
|
||||
"Login_Toggle_Info_headline": "Информация о пароле",
|
||||
"Maint_PurgeLog": "",
|
||||
"Maint_RestartServer": "",
|
||||
"Maint_Restart_Server_noti_text": "",
|
||||
"Maint_PurgeLog": "Журнал очистки",
|
||||
"Maint_RestartServer": "Перезапустить сервер",
|
||||
"Maint_Restart_Server_noti_text": "Вы уверены, что хотите перезапустить внутренний сервер? Это может привести к несогласованности работы приложения. Сначала создайте резервную копию настроек. <br/> <br/> Примечание: Это может занять несколько минут.",
|
||||
"Maintenance_Running_Version": "Установленная версия",
|
||||
"Maintenance_Status": "Статус",
|
||||
"Maintenance_Title": "Инструменты обслуживания",
|
||||
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "CSV Импорт",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "Вы уверены, что хотите импортировать файл CSV? Это полностью перезапишет устройства в вашей базе данных.",
|
||||
"Maintenance_Tool_ImportCSV_text": "Прежде чем использовать эту функцию, сделайте резервную копию. Импортируйте файл CSV (значения, разделенные запятыми), содержащий список устройств, включая сетевые отношения между сетевыми узлами и подключенными устройствами. Для этого поместите файл CSV с именем <b>devices.csv</b> в папку <b>/config</b>.",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "Переключить arp-скан (ВКЛ./ВЫКЛ.)",
|
||||
"Maintenance_Tool_arpscansw_noti": "Включить или выключить arp-скан",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "Когда сканирование было выключено, оно остается выключенным до тех пор, пока не будет активировано снова.",
|
||||
@@ -664,7 +667,7 @@
|
||||
"settings_core_label": "Основные",
|
||||
"settings_device_scanners": "Сканеры устройств, используемые для обнаружения устройств, записывающих данные в таблицу базы данных CurrentScan.",
|
||||
"settings_device_scanners_icon": "fa-solid fa-magnifying-glass-plus",
|
||||
"settings_device_scanners_info": "",
|
||||
"settings_device_scanners_info": "Загрузите еще больше сканеров устройств с помощью параметра <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_device_scanners_label": "Сканеры устройств",
|
||||
"settings_enabled": "Вкл. настройки",
|
||||
"settings_enabled_icon": "fa-solid fa-toggle-on",
|
||||
@@ -679,7 +682,7 @@
|
||||
"settings_other_scanners_label": "Другие сканеры",
|
||||
"settings_publishers": "Включенные шлюзы уведомлений - сервисы, которые будут отправлять уведомления в зависимости от ваших настроек.",
|
||||
"settings_publishers_icon": "fa-solid fa-paper-plane",
|
||||
"settings_publishers_info": "",
|
||||
"settings_publishers_info": "Загрузите больше нотификаторов с помощью настройки <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a>",
|
||||
"settings_publishers_label": "Уведомления",
|
||||
"settings_saved": "<br/>Настройки сохранены. <br/> Перезагрузка... <br/><i class=\"ion ion-ios-loop-strong fa-spin fa-2x fa-fw\"></i> <br/>",
|
||||
"settings_system_icon": "fa-solid fa-gear",
|
||||
@@ -687,4 +690,4 @@
|
||||
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportCSV_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "",
|
||||
"Maintenance_Tool_arpscansw_noti": "",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "",
|
||||
|
||||
@@ -372,6 +372,9 @@
|
||||
"Maintenance_Tool_ImportCSV_noti": "",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportCSV_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "",
|
||||
"Maintenance_Tool_arpscansw_noti": "",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "",
|
||||
|
||||
@@ -24,39 +24,41 @@ NetAlertX supports additional plugins to extend its functionality, each with its
|
||||
Device-detecting plugins insert values into the `CurrentScan` database table. The plugins that are not required are safe to ignore, however, it makes sense to have at least some device-detecting plugins enabled, such as `ARPSCAN` or `NMAPDEV`.
|
||||
|
||||
|
||||
| ID | Type | Description | Required | Data source | Detailed docs |
|
||||
|---------------|---------|---------------------------------------------|----------|--------------------|---------------------------------------------------------------|
|
||||
| `APPRISE` | ▶️ | Apprise notification proxy | | Script | [📚_publisher_apprise](/front/plugins/_publisher_apprise/) |
|
||||
| `ARPSCAN` | 🔍 | ARP-scan on current network | | Script | [📚arp_scan](/front/plugins/arp_scan/) |
|
||||
| `CSVBCKP` | ⚙ | CSV devices backup | | Script | [📚csv_backup](/front/plugins/csv_backup/) |
|
||||
| `DBCLNP` | ⚙ | Database cleanup | Yes* | Script | [📚db_cleanup](/front/plugins/db_cleanup/) |
|
||||
| `DDNS` | ⚙ | DDNS update | | Script | [📚ddns_update](/front/plugins/ddns_update/) |
|
||||
| `DHCPLSS` | 🔍/📥 | Import devices from DHCP leases | | Script | [📚dhcp_leases](/front/plugins/dhcp_leases/) |
|
||||
| `DHCPSRVS` | ♻ | DHCP servers | | Script | [📚dhcp_servers](/front/plugins/dhcp_servers/) |
|
||||
| `INTRNT` | 🔍 | Internet IP scanner | | Script | [📚internet_ip](/front/plugins/internet_ip/) |
|
||||
| `INTRSPD` | ♻ | Internet speed test | | Script | [📚internet_speedtest](/front/plugins/internet_speedtest/) |
|
||||
| `MAINT` | ⚙ | Maintenance of logs, etc. | | Script | [📚maintenance](/front/plugins/maintenance/) |
|
||||
| `MQTT` | ▶️ | MQTT for synching to Home Assistant | | Script | [📚_publisher_mqtt](/front/plugins/_publisher_mqtt/) |
|
||||
| `NEWDEV` | ⚙ | New device template | Yes | Template | [📚newdev_template](/front/plugins/newdev_template/) |
|
||||
| `NMAP` | ♻ | Nmap port scanning & discovery | | Script | [📚nmap_scan](/front/plugins/nmap_scan/) |
|
||||
| `NMAPDEV` | 🔍 | Nmap dev scan on current network | | Script | [📚nmap_dev_scan](/front/plugins/nmap_dev_scan/) |
|
||||
| `NSLOOKUP` | ♻ | NSLookup name resolution | | Script | [📚nslookup_scan](/front/plugins/nslookup_scan/) |
|
||||
| `NTFPRCS` | ⚙ | Notification processing | Yes | Template | [📚notification_processing](/front/plugins/notification_processing/)|
|
||||
| `NTFY` | ▶️ | NTFY notifications | | Script | [📚_publisher_ntfy](/front/plugins/_publisher_ntfy/) |
|
||||
| `PHOLUS` | ♻ | Pholus name resolution | | Script | [📚pholus_scan](/front/plugins/pholus_scan/) |
|
||||
| `PIHOLE` | 🔍/📥 | Pi-hole device import & sync | | SQLite DB | [📚pihole_scan](/front/plugins/pihole_scan/) |
|
||||
| `PUSHSAFER` | ▶️ | Pushsafer notifications | | Script | [📚_publisher_pushsafer](/front/plugins/_publisher_pushsafer/) |
|
||||
| `PUSHOVER` | ▶️ | Pushover notifications | | Script | [📚_publisher_pushover](/front/plugins/_publisher_pushover/) |
|
||||
| `SETPWD` | ⚙ | Set password | Yes | Template | [📚set_password](/front/plugins/set_password/) |
|
||||
| `SMTP` | ▶️ | Email notifications | | Script | [📚_publisher_email](/front/plugins/_publisher_email/) |
|
||||
| `SNMPDSC` | 🔍/📥 | SNMP device import & sync | | Script | [📚snmp_discovery](/front/plugins/snmp_discovery/) |
|
||||
| `SYNC` | 🔍/⚙/📥| Sync & import from other NetAlertX instances | | Script | [📚snmp_discovery](/front/plugins/snmp_discovery/) |
|
||||
| `UNDIS` | 🔍/📥 | Create dummy devices | | Script | [📚undiscoverables](/front/plugins/undiscoverables/) |
|
||||
| `UNFIMP` | 🔍/📥 | UniFi device import & sync | | Script | [📚unifi_import](/front/plugins/unifi_import/) |
|
||||
| `VNDRPDT` | ⚙ | Vendor database update | | Script | [📚vendor_update](/front/plugins/vendor_update/) |
|
||||
| `WEBHOOK` | ▶️ | Webhook notifications | | Script | [📚_publisher_webhook](/front/plugins/_publisher_webhook/) |
|
||||
| `WEBMON` | ♻ | Website down monitoring | | Script | [📚website_monitor](/front/plugins/website_monitor/)
|
||||
|
||||
| ID | Type | Description | Features | Required | Data source | Detailed docs |
|
||||
|---------------|---------|--------------------------------------------|----------|----------|--------------------|---------------------------------------------------------------|
|
||||
| `APPRISE` | ▶️ | Apprise notification proxy | | | Script | [_publisher_apprise](/front/plugins/_publisher_apprise/) |
|
||||
| `ARPSCAN` | 🔍 | ARP-scan on current network | | | Script | [arp_scan](/front/plugins/arp_scan/) |
|
||||
| `CSVBCKP` | ⚙ | CSV devices backup | | | Script | [csv_backup](/front/plugins/csv_backup/) |
|
||||
| `DBCLNP` | ⚙ | Database cleanup | | Yes* | Script | [db_cleanup](/front/plugins/db_cleanup/) |
|
||||
| `DDNS` | ⚙ | DDNS update | | | Script | [ddns_update](/front/plugins/ddns_update/) |
|
||||
| `DHCPLSS` | 🔍/📥 | Import devices from DHCP leases | | | Script | [dhcp_leases](/front/plugins/dhcp_leases/) |
|
||||
| `DHCPSRVS` | ♻ | DHCP servers | | | Script | [dhcp_servers](/front/plugins/dhcp_servers/) |
|
||||
| `INTRNT` | 🔍 | Internet IP scanner | | | Script | [internet_ip](/front/plugins/internet_ip/) |
|
||||
| `INTRSPD` | ♻ | Internet speed test | | | Script | [internet_speedtest](/front/plugins/internet_speedtest/) |
|
||||
| `MAINT` | ⚙ | Maintenance of logs, etc. | | | Script | [maintenance](/front/plugins/maintenance/) |
|
||||
| `MQTT` | ▶️ | MQTT for synching to Home Assistant | | | Script | [_publisher_mqtt](/front/plugins/_publisher_mqtt/) |
|
||||
| `NBTSCAN` | ♻ | Nbtscan (NetBIOS-based) name resolution | | | Script | [nbtscan_scan](/front/plugins/nbtscan_scan/) |
|
||||
| `NEWDEV` | ⚙ | New device template | | Yes | Template | [newdev_template](/front/plugins/newdev_template/) |
|
||||
| `NMAP` | ♻ | Nmap port scanning & discovery | | | Script | [nmap_scan](/front/plugins/nmap_scan/) |
|
||||
| `NMAPDEV` | 🔍 | Nmap dev scan on current network | | | Script | [nmap_dev_scan](/front/plugins/nmap_dev_scan/) |
|
||||
| `NSLOOKUP` | ♻ | NSLookup (DNS-based) name resolution | | | Script | [nslookup_scan](/front/plugins/nslookup_scan/) |
|
||||
| `NTFPRCS` | ⚙ | Notification processing | | Yes | Template | [notification_processing](/front/plugins/notification_processing/)|
|
||||
| `NTFY` | ▶️ | NTFY notifications | | | Script | [_publisher_ntfy](/front/plugins/_publisher_ntfy/) |
|
||||
| `OMDSDN` | 📥 | OMADA TP-Link import | 📊🔄 | | Script | [omada_sdn_imp](/front/plugins/omada_sdn_imp/) |
|
||||
| `PHOLUS` | ♻ | Pholus name resolution | | | Script | [pholus_scan](/front/plugins/pholus_scan/) |
|
||||
| `PIHOLE` | 🔍/📥 | Pi-hole device import & sync | | | SQLite DB | [pihole_scan](/front/plugins/pihole_scan/) |
|
||||
| `PUSHSAFER` | ▶️ | Pushsafer notifications | | | Script | [_publisher_pushsafer](/front/plugins/_publisher_pushsafer/) |
|
||||
| `PUSHOVER` | ▶️ | Pushover notifications | | | Script | [_publisher_pushover](/front/plugins/_publisher_pushover/) |
|
||||
| `SETPWD` | ⚙ | Set password | | Yes | Template | [set_password](/front/plugins/set_password/) |
|
||||
| `SMTP` | ▶️ | Email notifications | | | Script | [_publisher_email](/front/plugins/_publisher_email/) |
|
||||
| `SNMPDSC` | 🔍/📥 | SNMP device import & sync | | | Script | [snmp_discovery](/front/plugins/snmp_discovery/) |
|
||||
| `SYNC` | 🔍/⚙/📥| Sync & import from NetAlertX instances | 📊🔄 | | Script | [sync](/front/plugins/sync/) |
|
||||
| `UNDIS` | 🔍/📥 | Create dummy devices | | | Script | [undiscoverables](/front/plugins/undiscoverables/) |
|
||||
| `UNFIMP` | 🔍/📥 | UniFi device import & sync | | | Script | [unifi_import](/front/plugins/unifi_import/) |
|
||||
| `VNDRPDT` | ⚙ | Vendor database update | | | Script | [vendor_update](/front/plugins/vendor_update/) |
|
||||
| `WEBHOOK` | ▶️ | Webhook notifications | | | Script | [_publisher_webhook](/front/plugins/_publisher_webhook/) |
|
||||
| `WEBMON` | ♻ | Website down monitoring | | | Script | [website_monitor](/front/plugins/website_monitor/) |
|
||||
|
||||
|
||||
> \* The database cleanup plugin (`DBCLNP`) is not _required_ but the app will become unusable after a while if not executed.
|
||||
>
|
||||
@@ -75,11 +77,19 @@ Device-detecting plugins insert values into the `CurrentScan` database table. T
|
||||
| system | ⚙ | Providing core system functionality. | `schedule` / always on | ✖/✔ | Script / Template |
|
||||
| other | ♻ | Other scanners, e.g. for name resolution | misc | ✖ | Script / Template |
|
||||
|
||||
## Features
|
||||
|
||||
| Icon | Description |
|
||||
|------|---------------------------------------------------------------|
|
||||
| 📊 | Auto-imports the network topology diagram |
|
||||
| 🔄 | Has the option to sync some data back into the plugin source |
|
||||
|
||||
|
||||
## ✅Enabling plugins
|
||||
|
||||
Plugins can be enabled via Settings, and can be disabled as needed.
|
||||
|
||||
1. Research which plugin you'd like to use below and then load the required plugins in Settings via the `LOADED_PLUGINS` setting.
|
||||
1. Research which plugin you'd like to use and load the required plugins in Settings via the `LOADED_PLUGINS` setting.
|
||||
1. Save the changes and review the Settings of the newly loaded plugins.
|
||||
1. Change the `<prefix>_RUN` Setting to the recommended or custom value as per the documentation of the given setting
|
||||
- If using `schedule` on a `🔍 dev scanner` plugin, make sure the schedules are the same across all `🔍 dev scanner` plugins
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "__template",
|
||||
"unique_prefix": "TMP",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_0",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"mapped_to_table": "CurrentScan",
|
||||
|
||||
@@ -60,11 +60,11 @@ def main():
|
||||
print(subnets)
|
||||
|
||||
for rgx in regexes:
|
||||
mylog('debug', ["[cleanDeviceName] applying regex : " + rgx])
|
||||
mylog('debug', ["[cleanDeviceName] name before regex : " + str])
|
||||
mylog('trace', ["[cleanDeviceName] applying regex : " + rgx])
|
||||
mylog('trace', ["[cleanDeviceName] name before regex : " + str])
|
||||
|
||||
str = re.sub(rgx, "", str)
|
||||
mylog('debug', ["[cleanDeviceName] name after regex : " + str])
|
||||
mylog('trace', ["[cleanDeviceName] name after regex : " + str])
|
||||
|
||||
mylog('debug', ["[cleanDeviceName] output: " + str])
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"code_name": "arp_scan",
|
||||
"unique_prefix": "ARPSCAN",
|
||||
"execution_order" : "Layer_2",
|
||||
"plugin_type": "device_scanner",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "dhcp_leases",
|
||||
"unique_prefix": "DHCPLSS",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_3",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"data_filters": [
|
||||
@@ -513,12 +514,23 @@
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{ "onClick": "addList(this, false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-sm-3" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeAllOptions(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
@@ -529,23 +541,12 @@
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-sm-3" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeFromList(this)" },
|
||||
{ "getStringKey": "Gen_Remove_Last" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-sm-2" },
|
||||
{ "onClick": "addList(this, false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "dhcp_servers",
|
||||
"unique_prefix": "DHCPSRVS",
|
||||
"plugin_type": "other",
|
||||
"execution_order" : "Layer_3",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": true,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "internet_ip",
|
||||
"unique_prefix": "INTRNT",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_3",
|
||||
"enabled": true,
|
||||
"mapped_to_table": "CurrentScan",
|
||||
"data_filters": [
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"plugin_type": "other",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"execution_order" : "Layer_3",
|
||||
"show_ui": true,
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name": [
|
||||
|
||||
@@ -104,7 +104,7 @@ def execute_name_lookup (ip, timeout):
|
||||
# Look for the first line containing a valid NetBIOS name entry
|
||||
index = 0
|
||||
for line in lines:
|
||||
if ip in line:
|
||||
if 'Doing NBT name scan' not in line and ip in line:
|
||||
# Split the line and extract the primary NetBIOS name
|
||||
parts = line.split()
|
||||
if parts:
|
||||
|
||||
@@ -176,34 +176,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "LESS_NAME_CLEANUP",
|
||||
"type": {
|
||||
"dataType": "boolean",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "checkbox" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": 0,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Less Name Cleanup"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Check to start using the new code for cleaning device names. Removes all labels starting with underscore and removes network domain and search list."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "NAME_CLEANUP_REGEX",
|
||||
"type": {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "nmap_dev_scan",
|
||||
"unique_prefix": "NMAPDEV",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_3",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"mapped_to_table": "CurrentScan",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "nmap_scan",
|
||||
"unique_prefix": "NMAP",
|
||||
"plugin_type": "other",
|
||||
"execution_order" : "Layer_4",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"data_filters": [
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "nslookup_scan",
|
||||
"unique_prefix": "NSLOOKUP",
|
||||
"plugin_type": "other",
|
||||
"execution_order" : "Layer_4",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": true,
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
## Overview
|
||||
|
||||
Plugin functionality overview and links to external resources if relevant. Include use cases if available.
|
||||
The OMADA SDN plugin aims at synchronizing data between NetAlertX and a TPLINK OMADA SND controler by leveraging a tplink omada python library.
|
||||
#### features:
|
||||
1. extract list of OMADA Clients from OMADA and sync them up with NetAlertX
|
||||
2. extract list of OAMDA Devices (switches and access points) and sync them up with NetAlertX
|
||||
|
||||
> [!TIP]
|
||||
> Some tip.
|
||||
> some omada devices are apparently not fully compatible with the API which might lead to partial results.
|
||||
|
||||
### Quick setup guide
|
||||
|
||||
To set up the plugin correctly, make sure...
|
||||
1. You SHOULD (ie: strongly recommend) set up an account in your OMADA SDN console dedicated to NetAlertX OMADA_SDN plugin.
|
||||
- you should set USER TYPE = Local USer
|
||||
- you should set USER ROLE = Administrator (if you use a read-only role you won't be able to sync names from NetAlerX to OMADA SDN)
|
||||
- you can set Site Privileges = All Sites (or limit it to specific sites )
|
||||
|
||||
2. populate the variables in NetAlertX as instructed in the config plugin page.
|
||||
|
||||
|
||||
|
||||
|
||||
#### Required Settings
|
||||
|
||||
- When to run `PREF_RUN`
|
||||
-
|
||||
- OMDSDN_url
|
||||
- OMDSDN_sites
|
||||
- OMDSDN_username
|
||||
- OMDSDN_password
|
||||
- OMDSDN_force_overwrite
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
@@ -20,6 +35,37 @@ To set up the plugin correctly, make sure...
|
||||
|
||||
### Notes
|
||||
|
||||
- Additional notes, limitations, Author info.
|
||||
#### features not implemented yet:
|
||||
3. extract list of OAMDA router Devices (er605...) and sync them up with NetAlertX
|
||||
(I need to setup my own er605 however due to its limitations I have no use for it, and due to limitations of opensense dhcp servers, I can't deploy it yet without breaking dhcp self registration into opnsense unbound - see below)
|
||||
|
||||
#### know limitations:
|
||||
OMADA SDN limitation fixed by the plugin:
|
||||
0. OMADA SDN can't use DNS for names and keep using MAC ref: https://community.tp-link.com/en/business/forum/topic/503782
|
||||
- when you use an OMADA user Role = Administrator, the plugin will attempt to fix OMADA's shortcoming and populat the NAME field from NetAlertX (from DNS/DHCP/...)
|
||||

|
||||
-
|
||||
|
||||
Made with ❤ by [@FlyingToto](https://github.com/FlyingToto) 🙏
|
||||
can not fix some of tplinks OMADA SDN own limitations/bugs:
|
||||
1. OMADA SDN switches uplinks/downlinks is broken if the default router is not an OMADA native device
|
||||
- (I try to circumvent that through a tree parsing heuristic but your mileage might vary...)
|
||||
- ref: https://community.tp-link.com/en/business/forum/topic/673628
|
||||
2. OMADA SDN clients are sometimes mapped to the wrong switch/port... for instance:
|
||||
- client -> access_switch1/port1 -> core_switch2/port2 sometimes shows as client -> core_switch2/port2
|
||||
- it is unclear if this issue is realted to (1)
|
||||
3. OMADA er605 routers do not self register DHCP names with a remote unbound DNS (nor embded DNS):
|
||||
- ref: https://community.tp-link.com/en/business/forum/topic/542472
|
||||
- it looks like some release candidate firmware might provide this feature... I will test when opnsesne Kea self registration get fixed as well(4)and I can get it dhcp proxy to work.
|
||||
4. Opnsense dhcp doesn't support relay and self-registration at the same time...
|
||||
- opnsense legacy ISC dhcp server doesn't support dhcp proxies: ref: https://forum.opnsense.org/index.php?topic=34254.0
|
||||
- opnsense new kea dhcp server doesn't support dns self registration (yet) ref: https://github.com/opnsense/core/pull/7362
|
||||
5. incompatible devices:
|
||||
- OMADA EAP245 - to be fair to tp-link, this access point works inside OMADA SDN, so it might be an issue with our omada python library but we can't extract data from it.
|
||||
|
||||
|
||||
|
||||
|
||||
### Other infos
|
||||
|
||||
- Author : Flying Toto
|
||||
- Date : 04-Jul-2024 - version 1.0
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "omada_sdn_imp",
|
||||
"unique_prefix": "OMDSDN",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_0",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"mapped_to_table": "CurrentScan",
|
||||
@@ -124,7 +125,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Enter full URL with protocol <code>https://CHANGEME_omada.mylocaldomain</code>."
|
||||
"string": "Enter full URL with protocol <code>https://CHANGEME_omada.mylocaldomain:PORT</code>."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -199,7 +200,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Omada SDN site IDs. You can get it by..."
|
||||
"string": "Omada SDN site IDs. For now, we only process the first site listed since NetAlertX's other probes won't traverse across NAT and routers. But if needed please submit an issue in github with your specific use case for consideration: <code>https://github.com/jokob-sk/NetAlertX/issues </code> "
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -253,7 +254,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Omada SDN instance password"
|
||||
"string": "Omada SDN instance password."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -281,7 +282,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "The plugin synchronizes names from NetAlertX to OMADA. By default NetAlertX will only populate missing names in OMADASDN devices (i.e.: where the name is defaulting to the device MAC address); with this setting toggled, it will overwrite existing values regardless."
|
||||
"string": "The plugin synchronizes names from NetAlertX to OMADA Clients. By default NetAlertX will only populate missing names in OMADASDN devices (i.e.: where the name is defaulting to the device MAC address); with this setting toggled, it will overwrite existing values regardless."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
BIN
front/plugins/omada_sdn_imp/omada_account_sample.png
Executable file
BIN
front/plugins/omada_sdn_imp/omada_account_sample.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
@@ -1,12 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
__author__ = "ffsb"
|
||||
__version__ = "0.1" #initial
|
||||
__version__ = "0.2" # added logic to retry omada api call once as it seems to sometimes fail for some reasons, and error handling logic...
|
||||
__version__ = "0.3" # split devices API calls to allow multithreading but had to stop due to concurency issues.
|
||||
__version__ = "0.6" # found issue with multithreading - my omada calls redirect stdout which gets clubbered by normal stdout... not sure how to fix for now...
|
||||
# query OMADA SDN to populate NetAlertX witch omada switches, access points, clients.
|
||||
# try to identify and populate their connections by switch/accesspoints and ports/SSID
|
||||
# try to differentiate root bridges from accessory
|
||||
|
||||
|
||||
#
|
||||
# sample code to update unbound on opnsense - for reference...
|
||||
# curl -X POST -d '{"host":{"enabled":"1","hostname":"test","domain":"testdomain.com","rr":"A","mxprio":"","mx":"","server":"10.0.1.1","description":""}}' -H "Content-Type: application/json" -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/unbound/settings/AddHostOverride
|
||||
#
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import json
|
||||
import sqlite3
|
||||
import tplink_omada_client
|
||||
import importlib.util
|
||||
import time
|
||||
import io
|
||||
import re
|
||||
import concurrent.futures
|
||||
|
||||
|
||||
#import netifaces
|
||||
|
||||
# Define the installation path and extend the system path for plugin imports
|
||||
INSTALL_PATH = "/app"
|
||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
@@ -22,26 +43,168 @@ from notification import write_notification
|
||||
CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
|
||||
LOG_FILE = os.path.join(CUR_PATH, 'script.log')
|
||||
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
|
||||
OMADA_API_RETURN_FILE = os.path.join(CUR_PATH, 'omada_api_return')
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
#
|
||||
# sample target output:
|
||||
# 0 MAC, 1 IP, 2 Name, 3 switch/AP, 4 port/SSID, 5 TYPE
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-6F', '192.168.0.217', '1A-2B-3C-4D-5E-6F', '17', '40-AE-30-A5-A7-50, 'Switch']"
|
||||
|
||||
# Constants for array indices
|
||||
MAC, IP, NAME, SWITCH_AP, PORT_SSID, TYPE = range(6)
|
||||
|
||||
# sample omada devices input format:
|
||||
#
|
||||
# 0.MAC 1.IP 2.type 3.status 4.name 5.model
|
||||
#40-AE-30-A5-A7-50 192.168.0.11 ap CONNECTED office_Access_point EAP773(US) v1.0
|
||||
#B0-95-75-46-0C-39 192.168.0.4 switch CONNECTED pantry12 T1600G-52PS v4.0
|
||||
dMAC, dIP, dTYPE, dSTATUS, dNAME, dMODEL = range(6)
|
||||
|
||||
# sample omada clients input format:
|
||||
# 0 MAC, 1 IP, 2 Name, 3 switch/AP, 4 port/SSID,
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-6F', '192.168.0.217', '1A-2B-3C-4D-5E-6F', 'myssid_name2', '(office_Access_point)']"
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-01', '192.168.0.153', 'frontyard_ESP_29E753', 'pantry12', '(48)']"
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-02', '192.168.0.1', 'bastion', 'office24', '(23)']"
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-03', '192.168.0.226', 'brick', 'myssid_name3', '(office_Access_point)']"
|
||||
cMAC, cIP, cNAME, cSWITCH_AP, cPORT_SSID = range(5)
|
||||
|
||||
OMDLOGLEVEL = 'debug'
|
||||
pluginName = 'OMDSDN'
|
||||
#
|
||||
# translate MAC address from standard ieee model to ietf draft
|
||||
# AA-BB-CC-DD-EE-FF to aa:bb:cc:dd:ee:ff
|
||||
# tplink adheres to ieee, Nax adheres to ietf
|
||||
def ieee2ietf_mac_formater(inputmac):
|
||||
return(inputmac.lower().replace('-',':'))
|
||||
|
||||
def ietf2ieee_mac_formater(inputmac):
|
||||
return(inputmac.upper().replace(':','-'))
|
||||
|
||||
def get_mac_from_IP(target_IP):
|
||||
from scapy.all import ARP, Ether, srp
|
||||
try:
|
||||
arp_request = ARP(pdst=target_IP)
|
||||
ether = Ether(dst="ff:ff:ff:ff:ff:ff")
|
||||
packet = ether/arp_request
|
||||
result = srp(packet, timeout=3, verbose=0)[0]
|
||||
if result:
|
||||
return result[0][1].hwsrc
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
mylog('minimal', [f'[{pluginName}] get_mac_from_IP ERROR:{e}'])
|
||||
return None
|
||||
|
||||
|
||||
|
||||
#
|
||||
# wrapper to call the omada python library's own wrapper
|
||||
# it returns the output as a multiline python string
|
||||
#
|
||||
def callomada(myargs):
|
||||
arguments=" ".join(myargs)
|
||||
mylog('verbose', [f'[{pluginName}] callomada:{arguments}'])
|
||||
from tplink_omada_client.cli import main as omada
|
||||
from contextlib import redirect_stdout
|
||||
omada_output = ''
|
||||
retries = 2
|
||||
while omada_output == '' and retries > 1:
|
||||
retries = retries - 1
|
||||
try:
|
||||
mf = io.StringIO()
|
||||
with redirect_stdout(mf):
|
||||
bar = omada(myargs)
|
||||
omada_output = mf.getvalue()
|
||||
except Exception as e:
|
||||
mylog('minimal', [f'[{pluginName}] ERROR WHILE CALLING callomada:{arguments}\n {mf}'])
|
||||
omada_output= ''
|
||||
return(omada_output)
|
||||
|
||||
#
|
||||
# extract all the mac addresses from a multilines text...
|
||||
# return a list of MAC as 'string'
|
||||
#
|
||||
def extract_mac_addresses(text):
|
||||
mac_pattern = r"([0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2})"
|
||||
mac_addresses = re.findall(mac_pattern, text)
|
||||
return ["".join(parts) for parts in mac_addresses]
|
||||
|
||||
def find_default_gateway_ip ():
|
||||
#import netifaces
|
||||
#gw = netifaces.gateways()
|
||||
#return(gw['default'][netifaces.AF_INET][0])
|
||||
from scapy.all import conf, Route, sr1, IP, ICMP
|
||||
default_route = conf.route.route("0.0.0.0")
|
||||
return default_route[2] if default_route[2] else None
|
||||
|
||||
|
||||
#return('192.168.0.1')
|
||||
|
||||
|
||||
def add_uplink (uplink_mac, switch_mac, device_data_bymac, sadevices_linksbymac,port_byswitchmac_byclientmac):
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}] trying to add uplink="{uplink_mac}" to switch="{switch_mac}"'])
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}] before adding:"{device_data_bymac[switch_mac]}"'])
|
||||
if device_data_bymac[switch_mac][SWITCH_AP] == 'null':
|
||||
device_data_bymac[switch_mac][SWITCH_AP] = uplink_mac
|
||||
if device_data_bymac[switch_mac][TYPE] == 'Switch' and device_data_bymac[uplink_mac][TYPE] == 'Switch':
|
||||
port_to_uplink = port_byswitchmac_byclientmac[switch_mac][uplink_mac]
|
||||
#find_port_of_uplink_switch(switch_mac, uplink_mac)
|
||||
else:
|
||||
port_to_uplink=device_data_bymac[uplink_mac][PORT_SSID]
|
||||
device_data_bymac[switch_mac][PORT_SSID] = port_to_uplink
|
||||
# mylog(OMDLOGLEVEL, [f'[{pluginName}] after adding:"{device_data_bymac[switch_mac]}"'])
|
||||
for link in sadevices_linksbymac[switch_mac]:
|
||||
if device_data_bymac[link][SWITCH_AP] == 'null' and device_data_bymac[switch_mac][TYPE] == 'Switch':
|
||||
add_uplink(switch_mac, link, device_data_bymac, sadevices_linksbymac,port_byswitchmac_byclientmac)
|
||||
|
||||
|
||||
pluginName = '<unique_prefix>'
|
||||
|
||||
# ----------------------------------------------
|
||||
# Main initialization
|
||||
def main():
|
||||
mylog('verbose', [f'[{pluginName}] In script'])
|
||||
|
||||
start_time = time.time()
|
||||
mylog('verbose', [f'[{pluginName}] starting execution'])
|
||||
from database import DB
|
||||
from device import Device_obj
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
# Create a Device_obj instance
|
||||
device_handler = Device_obj(db)
|
||||
# Retrieve configuration settings
|
||||
some_setting = get_setting_value('OMDSDN_url')
|
||||
# these should be self-explanatory
|
||||
omada_sites = []
|
||||
omada_username = get_setting_value('OMDSDN_username')
|
||||
omada_password = get_setting_value('OMDSDN_password')
|
||||
omada_sites = get_setting_value('OMDSDN_sites')
|
||||
omada_site = omada_sites[0]
|
||||
omada_url = get_setting_value('OMDSDN_url')
|
||||
|
||||
omada_login = callomada(['-t','myomada','target','--url',omada_url,'--user',omada_username,
|
||||
'--password',omada_password,'--site',omada_site,'--set-default'])
|
||||
mylog('verbose', [f'[{pluginName}] login to omada result is: {omada_login}'])
|
||||
|
||||
clients_list = callomada(['-t','myomada','clients'])
|
||||
mylog('verbose', [f'[{pluginName}] clients found:"{clients_list.count("\n")}"\n{clients_list}'])
|
||||
|
||||
switches_and_aps = callomada(['-t','myomada','devices'])
|
||||
mylog('verbose', [f'[{pluginName}] omada devices (switches, access points) found:"{switches_and_aps.count("\n")}" \n {switches_and_aps}'])
|
||||
|
||||
|
||||
#some_setting = get_setting_value('OMDSDN_url')
|
||||
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}] some_setting value {some_setting}'])
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] ffsb'])
|
||||
|
||||
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] some_setting calue {some_setting}'])
|
||||
|
||||
# retrieve data
|
||||
device_data = get_device_data(some_setting)
|
||||
device_data = get_device_data(clients_list, switches_and_aps, device_handler)
|
||||
|
||||
# Process the data into native application tables
|
||||
mylog('verbose', [f'[{pluginName}] New entries to create: "{len(device_data)}"'])
|
||||
if len(device_data) > 0:
|
||||
|
||||
# insert devices into the lats_result.log
|
||||
@@ -50,36 +213,238 @@ def main():
|
||||
# {
|
||||
# "column": "Object_PrimaryID", <--------- the value I save into primaryId
|
||||
# "mapped_to_column": "cur_MAC", <--------- gets unserted into the CurrentScan DB table column cur_MAC
|
||||
#
|
||||
for device in device_data:
|
||||
plugin_objects.add_object(
|
||||
primaryId = device['some_id'], # MAC
|
||||
secondaryId = device['some_id'], # IP
|
||||
watched1 = device['some_id'], # NAME/HOSTNAME
|
||||
watched2 = device['some_id'], # PARENT NETWORK NODE MAC
|
||||
watched3 = device['some_id'], # PORT
|
||||
watched4 = device['some_id'], # SSID
|
||||
extra = device['some_id'], # SITENAME (cur_NetworkSite) or VENDOR (cur_Vendor) (PICK one and adjust config.json -> "column": "Extra")
|
||||
foreignKey = device['some_id']) # usually MAC
|
||||
# watched1 = 'null' ,
|
||||
# figure a way to run my udpate script delayed
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] New entries: "{len(new_devices)}"'])
|
||||
for device in device_data:
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] main parsing device: "{device}"'])
|
||||
myport = device[PORT_SSID] if device[PORT_SSID].isdigit() else ''
|
||||
myssid = device[PORT_SSID] if not device[PORT_SSID].isdigit() else ''
|
||||
ParentNetworkNode = ieee2ietf_mac_formater(device[SWITCH_AP]) if device[SWITCH_AP] != 'Internet' else 'Internet'
|
||||
mymac = ieee2ietf_mac_formater(device[MAC])
|
||||
plugin_objects.add_object(
|
||||
primaryId = mymac, # MAC
|
||||
secondaryId = device[IP], # IP
|
||||
watched1 = device[NAME], # NAME/HOSTNAME
|
||||
watched2 = ParentNetworkNode, # PARENT NETWORK NODE MAC
|
||||
watched3 = myport, # PORT
|
||||
watched4 = myssid, # SSID
|
||||
extra = device[TYPE],
|
||||
#omada_site, # SITENAME (cur_NetworkSite) or VENDOR (cur_Vendor) (PICK one and adjust config.json -> "column": "Extra")
|
||||
foreignKey = device[MAC].lower().replace('-',':')) # usually MAC
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] New entries: "{mymac:<18}, {device[IP]:<16}, {device[NAME]:<63}, {ParentNetworkNode:<18}, {myport:<4}, {myssid:<32}, {device[TYPE]}"'])
|
||||
mylog('verbose', [f'[{pluginName}] New entries: "{len(device_data)}"'])
|
||||
|
||||
# log result
|
||||
# plugin_objects.write_result_file()
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}] TEST name from MAC: {device_handler.getValueWithMac('dev_Name','00:e2:59:00:a0:8e')}'])
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}] TEST MAC from IP: {get_mac_from_IP('192.168.0.1')} also {ietf2ieee_mac_formater(get_mac_from_IP('192.168.0.1'))}'])
|
||||
end_time = time.time()
|
||||
mylog('verbose', [f'[{pluginName}] execution completed in {end_time - start_time:.2f} seconds'])
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
def get_omada_devices_details(msadevice_data):
|
||||
mthisswitch = msadevice_data[dMAC]
|
||||
mtype = msadevice_data[dTYPE]
|
||||
mswitch_detail = ''
|
||||
mswitch_dump = ''
|
||||
if mtype == 'ap':
|
||||
mswitch_detail = callomada(['access-point', mthisswitch])
|
||||
elif mtype == 'switch':
|
||||
mswitch_detail = callomada(['switch', mthisswitch])
|
||||
mswitch_dump = callomada(['-t','myomada','switch','-d',mthisswitch])
|
||||
else:
|
||||
mswitch_detail = ''
|
||||
nswitch_dump = ''
|
||||
return mswitch_detail, mswitch_dump
|
||||
|
||||
|
||||
|
||||
# ----------------------------------------------
|
||||
# retrieve data
|
||||
def get_device_data(some_setting):
|
||||
def get_device_data(omada_clients_output,switches_and_aps,device_handler):
|
||||
|
||||
device_data = []
|
||||
|
||||
# sample omada devices input format:
|
||||
# 0.MAC 1.IP 2.type 3.status 4.name 5.model
|
||||
#40-AE-30-A5-A7-50 192.168.0.11 ap CONNECTED office_Access_point EAP773(US) v1.0
|
||||
#B0-95-75-46-0C-39 192.168.0.4 switch CONNECTED pantry12 T1600G-52PS v4.0
|
||||
#
|
||||
# sample target output:
|
||||
# 0 MAC, 1 IP, 2 Name, 3 switch/AP, 4 port/SSID, 5 TYPE
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-6F', '192.168.0.217', '1A-2B-3C-4D-5E-6F', '17', '40-AE-30-A5-A7-50, 'Switch']"
|
||||
#constants
|
||||
sadevices_macbyname = {}
|
||||
sadevices_macbymac = {}
|
||||
sadevices_linksbymac = {}
|
||||
port_byswitchmac_byclientmac = {}
|
||||
device_data_bymac = {}
|
||||
device_data_mac_byip = {}
|
||||
omada_force_overwrite = get_setting_value('OMDSDN_force_overwrite')
|
||||
switch_details = {}
|
||||
switch_dumps = {}
|
||||
|
||||
sadevices = switches_and_aps.splitlines()
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] switches_and_aps rows: "{len(sadevices)}"'])
|
||||
|
||||
for sadevice in sadevices:
|
||||
sadevice_data = sadevice.split()
|
||||
thisswitch = sadevice_data[dMAC]
|
||||
thistype = sadevice_data[dTYPE]
|
||||
switch_details[thisswitch], switch_dumps[thisswitch] = get_omada_devices_details(sadevice_data)
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] switches details collected "{len(switch_details)}"'])
|
||||
mylog('verbose', [f'[{pluginName}] dump details collected "{len(switch_details)}"'])
|
||||
# Using ThreadPoolExecutor for parallel execution
|
||||
|
||||
for sadevice in sadevices:
|
||||
sadevice_data = sadevice.split()
|
||||
thisswitch = sadevice_data[dMAC]
|
||||
sadevices_macbyname[sadevice_data[4]] = thisswitch
|
||||
if sadevice_data[dTYPE] == 'ap':
|
||||
sadevice_type = 'AP'
|
||||
#sadevice_details = callomada(['access-point', thisswitch])
|
||||
sadevice_details = switch_details[thisswitch]
|
||||
if sadevice_details == '':
|
||||
sadevice_links = [thisswitch]
|
||||
else:
|
||||
sadevice_links = extract_mac_addresses(sadevice_details)
|
||||
sadevices_linksbymac[thisswitch] = sadevice_links[1:]
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}]adding switch details: "{sadevice_details}"'])
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}]links are: "{sadevice_links}"'])
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}]linksbymac are: "{sadevices_linksbymac[thisswitch]}"'])
|
||||
elif sadevice_data[dTYPE] == 'switch':
|
||||
sadevice_type = 'Switch'
|
||||
#sadevice_details=callomada(['switch', thisswitch])
|
||||
sadevice_details = switch_details[thisswitch]
|
||||
if sadevice_details == '':
|
||||
sadevice_links = [thisswitch]
|
||||
else:
|
||||
sadevice_links=extract_mac_addresses(sadevice_details)
|
||||
sadevices_linksbymac[thisswitch] = sadevice_links[1:]
|
||||
# recovering the list of switches connected to sadevice switch and on which port...
|
||||
#switchdump = callomada(['-t','myomada','switch','-d',thisswitch])
|
||||
switchdump = switch_dumps[thisswitch]
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] switchdump: {switchdump}'])
|
||||
port_byswitchmac_byclientmac[thisswitch] = {}
|
||||
for link in sadevices_linksbymac[thisswitch]:
|
||||
port_pattern = r"(?:{[^}]*\"port\"\: )([0-9]+)(?=[^}]*"+re.escape(link)+r")"
|
||||
myport = re.findall(port_pattern, switchdump,re.DOTALL)
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}] switchdump: link={link} myport:{myport}'])
|
||||
port_byswitchmac_byclientmac[thisswitch][link] = myport[0] if myport else ''
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}]links are: "{sadevice_links}"'])
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}]linksbymac are: "{sadevices_linksbymac[thisswitch]}"'])
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}]ports of each links are: "{port_byswitchmac_byclientmac[thisswitch]}"'])
|
||||
#mylog(OMDLOGLEVEL, [f'[{pluginName}]adding switch details: "{sadevice_details}"'])
|
||||
else:
|
||||
sadevice_type = 'null'
|
||||
sadevice_details='null'
|
||||
device_data_bymac[thisswitch] = [thisswitch, sadevice_data[dIP], sadevice_data[dNAME], 'null', 'null',sadevice_type]
|
||||
device_data_mac_byip[sadevice_data[dIP]] = thisswitch
|
||||
foo=[thisswitch, sadevice_data[1], sadevice_data[4], 'null', 'null']
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}]adding switch: "{foo}"'])
|
||||
|
||||
|
||||
|
||||
|
||||
# sadevices_macbymac[thisswitch] = thisswitch
|
||||
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] switch_macbyname: "{sadevices_macbyname}"'])
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] switches: "{device_data_bymac}"'])
|
||||
|
||||
|
||||
# do some processing, call exteranl APIs, and return a device list
|
||||
# ...
|
||||
#
|
||||
# sample omada clients input format:
|
||||
# 0 MAC, 1 IP, 2 Name, 3 switch/AP, 4 port/SSID,
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-6F', '192.168.0.217', '1A-2B-3C-4D-5E-6F', 'myssid_name2', '(office_Access_point)']"
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-01', '192.168.0.153', 'frontyard_ESP_29E753', 'pantry12', '(48)']"
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-02', '192.168.0.1', 'bastion', 'office24', '(23)']"
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-03', '192.168.0.226', 'brick', 'myssid_name3', '(office_Access_point)']"
|
||||
|
||||
# sample target output:
|
||||
# 0 MAC, 1 IP, 2 Name, 3 MAC of switch/AP, 4 port/SSID, 5 TYPE
|
||||
#17:27:10 [<unique_prefix>] token: "['1A-2B-3C-4D-5E-6F', '192.168.0.217', 'brick', 'office_Access_point','myssid_name2', , 'Switch']"
|
||||
|
||||
return device_data
|
||||
odevices = omada_clients_output.splitlines()
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] omada_clients_outputs rows: "{len(odevices)}"'])
|
||||
for odevice in odevices:
|
||||
odevice_data = odevice.split()
|
||||
odevice_data_reordered = [ MAC, IP, NAME, SWITCH_AP, PORT_SSID, TYPE]
|
||||
odevice_data_reordered[MAC]=odevice_data[cMAC]
|
||||
odevice_data_reordered[IP]=odevice_data[cIP]
|
||||
real_naxname = device_handler.getValueWithMac('dev_Name',ieee2ietf_mac_formater(odevice_data[cMAC]))
|
||||
|
||||
#
|
||||
# if the name stored in Nax for a device is empty or the MAC addres or has some parenthhesis or is the same as in omada
|
||||
# don't bother updating omada's name at all.
|
||||
#
|
||||
|
||||
naxname = real_naxname
|
||||
if real_naxname != None:
|
||||
if '(' in real_naxname:
|
||||
# removing parenthesis and domains from the name
|
||||
naxname = real_naxname.split('(')[0]
|
||||
if naxname != None and '.' in naxname:
|
||||
naxname = naxname.split('.')[0]
|
||||
if naxname in ( None, 'null', '' ):
|
||||
naxname = odevice_data[cNAME] if odevice_data[cNAME] != '' else odevice_data[cMAC]
|
||||
naxname = naxname.strip()
|
||||
mylog('debug', [f'[{pluginName}] TEST name from MAC: {naxname}'])
|
||||
if odevice_data[cNAME] in (odevice_data[cMAC], 'null', ''):
|
||||
mylog('verbose', [f'[{pluginName}] updating omada server because odevice_data is: {odevice_data[cNAME]} and naxname is: "{naxname}"'])
|
||||
callomada(['set-client-name', odevice_data[cMAC], naxname])
|
||||
odevice_data_reordered[NAME] = naxname
|
||||
else:
|
||||
if omada_force_overwrite and naxname != odevice_data[cNAME] :
|
||||
mylog('verbose', [f'[{pluginName}] updating omada server because odevice_data is: "{odevice_data[cNAME]} and naxname is: "{naxname}"'])
|
||||
callomada(['set-client-name', odevice_data[cMAC], naxname])
|
||||
odevice_data_reordered[NAME] = naxname
|
||||
mightbeport = odevice_data[cPORT_SSID].lstrip('(')
|
||||
mightbeport = mightbeport.rstrip(')')
|
||||
if mightbeport.isdigit():
|
||||
odevice_data_reordered[SWITCH_AP] = odevice_data[cSWITCH_AP]
|
||||
odevice_data_reordered[PORT_SSID] = mightbeport
|
||||
else:
|
||||
odevice_data_reordered[SWITCH_AP] = mightbeport
|
||||
odevice_data_reordered[PORT_SSID] = odevice_data[cSWITCH_AP]
|
||||
|
||||
# replacing the switch name with its MAC...
|
||||
try:
|
||||
mightbemac = sadevices_macbyname[odevice_data_reordered[SWITCH_AP]]
|
||||
odevice_data_reordered[SWITCH_AP] = mightbemac
|
||||
except KeyError:
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] could not find the mac adddress for: "{odevice_data_reordered[SWITCH_AP]}"'])
|
||||
# adding the type
|
||||
odevice_data_reordered[TYPE] = 'null'
|
||||
device_data_bymac[odevice_data_reordered[MAC]] = odevice_data_reordered
|
||||
device_data_mac_byip[odevice_data_reordered[IP]] = odevice_data_reordered[MAC]
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] tokens: "{odevice_data}"'])
|
||||
mylog(OMDLOGLEVEL, [f'[{pluginName}] tokens_reordered: "{odevice_data_reordered}"'])
|
||||
# populating the uplinks nodes of the omada switches and access points manually
|
||||
# since OMADA SDN makes is unreliable if the gateway is not their own tplink hardware...
|
||||
|
||||
|
||||
# step1 let's find the the default router
|
||||
#
|
||||
default_router_ip = find_default_gateway_ip()
|
||||
default_router_mac = ietf2ieee_mac_formater(get_mac_from_IP(default_router_ip))
|
||||
device_data_bymac[default_router_mac][TYPE] = 'Firewall'
|
||||
# step2 let's find the first switch and set the default router parent to internet
|
||||
first_switch=device_data_bymac[default_router_mac][SWITCH_AP]
|
||||
device_data_bymac[default_router_mac][SWITCH_AP] = 'Internet'
|
||||
# step3 let's set the switch connected to the default gateway uplink to the default gateway and hardcode port to 1 for now:
|
||||
#device_data_bymac[first_switch][SWITCH_AP]=default_router_mac
|
||||
#device_data_bymac[first_switch][SWITCH_AP][PORT_SSID] = '1'
|
||||
# step4, let's go recursively through switches other links to mark update their uplinks
|
||||
# and pray it ends one day...
|
||||
#
|
||||
add_uplink(default_router_mac,first_switch, device_data_bymac,sadevices_linksbymac,port_byswitchmac_byclientmac)
|
||||
return device_data_bymac.values()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "pihole_scan",
|
||||
"unique_prefix": "PIHOLE",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_2",
|
||||
"enabled": true,
|
||||
"data_source": "sqlite-db-query",
|
||||
"mapped_to_table": "CurrentScan",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"code_name": "snmp_discovery",
|
||||
"unique_prefix": "SNMPDSC",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_1",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"data_filters": [
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"show_ui": true,
|
||||
"unique_prefix": "UNFIMP",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_1",
|
||||
"data_source": "script",
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name": [
|
||||
|
||||
@@ -114,21 +114,21 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
<div class =" col-sm-12" id="system_content"></div>
|
||||
</div>
|
||||
|
||||
<div class ="bg-grey-dark color-palette panel panel-default col-sm-12 box-default box-info" id="device_scanner_content_header" >
|
||||
<div class ="bg-grey-dark color-palette panel panel-default col-sm-12 box-default box-info" id="device_scanners_content_header" >
|
||||
<div class ="settings-group col-sm-12">
|
||||
<i class="<?= lang("settings_device_scanners_icon");?>"></i> <?= lang("settings_device_scanners_label");?>
|
||||
</div>
|
||||
<div class =" col-sm-12" id="device_scanner_content"> <?= lang("settings_device_scanners_info");?> </div>
|
||||
</div>
|
||||
|
||||
<div class ="bg-grey-dark color-palette panel panel-default col-sm-12 box-default box-info" id="other_content_header">
|
||||
<div class ="bg-grey-dark color-palette panel panel-default col-sm-12 box-default box-info" id="other_scanners_content_header">
|
||||
<div class ="settings-group col-sm-12">
|
||||
<i class="<?= lang("settings_other_scanners_icon");?>"></i> <?= lang("settings_other_scanners_label");?>
|
||||
</div>
|
||||
<div class =" col-sm-12" id="other_content"></div>
|
||||
</div>
|
||||
|
||||
<div class ="bg-grey-dark color-palette panel panel-default col-sm-12 box-default box-info" id="publisher_content_header" >
|
||||
<div class ="bg-grey-dark color-palette panel panel-default col-sm-12 box-default box-info" id="publishers_content_header" >
|
||||
<div class ="settings-group col-sm-12">
|
||||
<i class="<?= lang("settings_publishers_icon");?>"></i> <?= lang("settings_publishers_label");?>
|
||||
</div>
|
||||
@@ -285,12 +285,14 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
|
||||
overviewSections_html += `<div class="overview-section col-sm-12" id="${section}">
|
||||
<div class="col-sm-12 " title="${getString("settings_"+section)}">
|
||||
<div class="overview-group col-sm-12 col-xs-12">
|
||||
|
||||
<i title="${section}" class="${getString("settings_"+section+"_icon")}"></i>
|
||||
|
||||
${getString("settings_"+section+"_label")}
|
||||
</div>
|
||||
<a href="#${section}_content_header">
|
||||
<div class="overview-group col-sm-12 col-xs-12">
|
||||
|
||||
<i title="${section}" class="${getString("settings_"+section+"_icon")}"></i>
|
||||
|
||||
${getString("settings_"+section+"_label")}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
${overviewSectionsHtml[index]}
|
||||
|
||||
@@ -95,34 +95,34 @@ def print_scan_stats(db):
|
||||
mylog('verbose', f'[Scan Stats] Disconnections.........: {stats[0]["disconnections"]}')
|
||||
mylog('verbose', f'[Scan Stats] IP Changes.............: {stats[0]["ip_changes"]}')
|
||||
|
||||
if str(stats[0]["new_devices"]) != '0':
|
||||
mylog('debug', f' ================ DEVICES table content ================')
|
||||
sql.execute('select * from Devices')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('debug', f' {row_dict}')
|
||||
|
||||
mylog('debug', f' ================ CurrentScan table content ================')
|
||||
sql.execute('select * from CurrentScan')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('debug', f' {row_dict}')
|
||||
|
||||
mylog('debug', f' ================ Events table content where eve_PendingAlertEmail = 1 ================')
|
||||
sql.execute('select * from Events where eve_PendingAlertEmail = 1')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('debug', f' {row_dict}')
|
||||
# if str(stats[0]["new_devices"]) != '0':
|
||||
mylog('trace', f' ================ DEVICES table content ================')
|
||||
sql.execute('select * from Devices')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('trace', f' {row_dict}')
|
||||
|
||||
mylog('trace', f' ================ CurrentScan table content ================')
|
||||
sql.execute('select * from CurrentScan')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('trace', f' {row_dict}')
|
||||
|
||||
mylog('trace', f' ================ Events table content where eve_PendingAlertEmail = 1 ================')
|
||||
sql.execute('select * from Events where eve_PendingAlertEmail = 1')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('trace', f' {row_dict}')
|
||||
|
||||
mylog('debug', f' ================ Events table COUNT ================')
|
||||
sql.execute('select count(*) from Events')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('debug', f' {row_dict}')
|
||||
mylog('trace', f' ================ Events table COUNT ================')
|
||||
sql.execute('select count(*) from Events')
|
||||
rows = sql.fetchall()
|
||||
for row in rows:
|
||||
row_dict = dict(row)
|
||||
mylog('trace', f' {row_dict}')
|
||||
|
||||
|
||||
mylog('verbose', '[Scan Stats] Scan Method Statistics:')
|
||||
@@ -223,18 +223,32 @@ def create_new_devices (db):
|
||||
)
|
||||
SELECT
|
||||
cur_MAC,
|
||||
CASE WHEN LENGTH(TRIM(cur_Name)) > 0 THEN cur_Name ELSE '(unknown)' END,
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(cur_Name)) > 0 THEN cur_Name ELSE '(unknown)'
|
||||
END,
|
||||
cur_Vendor,
|
||||
cur_IP,
|
||||
?,
|
||||
?,
|
||||
cur_SyncHubNodeName,
|
||||
{sql_generateGuid},
|
||||
CASE WHEN LENGTH(TRIM(cur_NetworkNodeMAC)) > 0 THEN cur_NetworkNodeMAC ELSE '{get_setting_value('NEWDEV_dev_Network_Node_MAC_ADDR')}' END,
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(cur_NetworkNodeMAC)) > 0
|
||||
AND cur_MAC != 'Internet'
|
||||
THEN cur_NetworkNodeMAC
|
||||
ELSE
|
||||
CASE
|
||||
WHEN cur_MAC = 'Internet'
|
||||
THEN 'null'
|
||||
ELSE '{get_setting_value('NEWDEV_dev_Network_Node_MAC_ADDR')}'
|
||||
END
|
||||
END,
|
||||
cur_PORT,
|
||||
cur_NetworkSite,
|
||||
cur_SSID,
|
||||
CASE WHEN LENGTH(TRIM(cur_Type)) > 0 THEN cur_Type ELSE '{get_setting_value('NEWDEV_dev_DeviceType')}' END,
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(cur_Type)) > 0 THEN cur_Type ELSE '{get_setting_value('NEWDEV_dev_DeviceType')}'
|
||||
END,
|
||||
{newDevDefaults}
|
||||
FROM CurrentScan
|
||||
WHERE 1=1
|
||||
@@ -502,7 +516,7 @@ def update_devices_names (db):
|
||||
recordsToUpdate.append ([newName, device['dev_MAC']])
|
||||
|
||||
# Print log
|
||||
mylog('verbose', ['[Update Device Name] Names Found (DiG/NSLOOKUP/Pholus): ', len(recordsToUpdate), " (",foundDig,"/",foundNsLookup,"/",foundPholus ,")"] )
|
||||
mylog('verbose', ['[Update Device Name] Names Found (DiG/NSLOOKUP/NBTSCAN/Pholus): ', len(recordsToUpdate), " (",foundDig,"/",foundNsLookup,"/",foundNbtLookup,"/", foundPholus ,")"] )
|
||||
mylog('verbose', ['[Update Device Name] Names Not Found : ', notFound] )
|
||||
|
||||
# update not found devices with (name not found)
|
||||
|
||||
@@ -727,38 +727,6 @@ def cleanDeviceName(str, match_IP):
|
||||
# add matching info
|
||||
if match_IP:
|
||||
str = str + " (IP match)"
|
||||
|
||||
|
||||
if get_setting_value('NEWDEV_LESS_NAME_CLEANUP'):
|
||||
mylog('debug', ["[Name cleanup] Using new cleanDeviceName(" + str + ")"])
|
||||
|
||||
# replace all labels starting with underscore
|
||||
str = re.sub(r'^_[^\.]*\.', '', str) # leading label
|
||||
str = re.sub(r'\._[^\.]*\.', '.', str) # nested label
|
||||
|
||||
# get a stub resolver for access to resolv.conf configuration
|
||||
resolv = dns.resolver.Resolver()
|
||||
|
||||
# replace the local domain name
|
||||
str = re.sub(r'\.' + resolv.domain.to_text() + r'$', '', str)
|
||||
|
||||
# replace dns search list
|
||||
for name in resolv.search:
|
||||
str = re.sub(r'\.' + name.to_text() + r'$', '', str)
|
||||
|
||||
# removing last part of e.g. Nest-Audio-ff77ff77ff77ff77ff77ff77ff77ff77
|
||||
str = re.sub(r'-[a-fA-F0-9]{32}', '', str)
|
||||
|
||||
# Remove everything after '#' including the '#'
|
||||
str = re.sub(r'#.*', '', str)
|
||||
|
||||
# remove trailing dot
|
||||
if str.endswith('.'):
|
||||
str = str[:-1]
|
||||
|
||||
# done
|
||||
mylog('debug', ["[Name cleanup] cleanDeviceName = " + str])
|
||||
return str
|
||||
|
||||
# Applying cleanup REGEXEs
|
||||
mylog('debug', ["[Name cleanup] Using old cleanDeviceName(" + str + ")"])
|
||||
@@ -766,13 +734,14 @@ def cleanDeviceName(str, match_IP):
|
||||
regexes = get_setting_value('NEWDEV_NAME_CLEANUP_REGEX')
|
||||
|
||||
for rgx in regexes:
|
||||
mylog('debug', ["[cleanDeviceName] applying regex : " + rgx])
|
||||
mylog('debug', ["[cleanDeviceName] name before regex : " + str])
|
||||
mylog('trace', ["[cleanDeviceName] applying regex : " + rgx])
|
||||
mylog('trace', ["[cleanDeviceName] name before regex : " + str])
|
||||
str = re.sub(rgx, "", str)
|
||||
mylog('debug', ["[cleanDeviceName] name after regex : " + str])
|
||||
mylog('trace', ["[cleanDeviceName] name after regex : " + str])
|
||||
|
||||
str = re.sub(r'\.\b', '', str) # trailing dot after words
|
||||
str = re.sub(r'\.$', '', str) # trailing dot at the end of the string
|
||||
str = str.replace(". (IP match)", " (IP match)") # Remove dot if (IP match) is added
|
||||
|
||||
mylog('debug', ["[cleanDeviceName] output: " + str])
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ def importConfigs (db, all_plugins):
|
||||
|
||||
conf.LOADED_PLUGINS = ccd('LOADED_PLUGINS', [] , c_d, 'Loaded plugins', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.SCAN_SUBNETS = ccd('SCAN_SUBNETS', ['192.168.1.0/24 --interface=eth1', '192.168.1.0/24 --interface=eth0'] , c_d, 'Subnets to scan', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "192.168.1.0/24 --interface=eth1" },{ "suffix": "_in" },{ "cssClasses": "col-sm-10" },{ "prefillValue": "null" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": ["_in"] },{ "separator": "" },{ "cssClasses": "col-xs-12" },{ "onClick": "addList(this, false)" },{ "getStringKey": "Gen_Add" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeAllOptions(this)" },{ "getStringKey": "Gen_Remove_All" }],"transformers": []},{"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeFromList(this)" },{ "getStringKey": "Gen_Remove_Last" }],"transformers": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', '[]', 'General')
|
||||
conf.LOG_LEVEL = ccd('LOG_LEVEL', 'verbose' , c_d, 'Log verboseness', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['none', 'minimal', 'verbose', 'debug']", 'General')
|
||||
conf.LOG_LEVEL = ccd('LOG_LEVEL', 'verbose' , c_d, 'Log verboseness', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['none', 'minimal', 'verbose', 'debug', 'trace']", 'General')
|
||||
conf.TIMEZONE = ccd('TIMEZONE', 'Europe/Berlin' , c_d, 'Time zone', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.PLUGINS_KEEP_HIST = ccd('PLUGINS_KEEP_HIST', 250 , c_d, 'Keep history entries', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.REPORT_DASHBOARD_URL = ccd('REPORT_DASHBOARD_URL', 'http://netalertx/' , c_d, 'NetAlertX URL', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
|
||||
@@ -22,7 +22,7 @@ def timeNowTZ():
|
||||
#-------------------------------------------------------------------------------
|
||||
# More verbose as the numbers go up
|
||||
debugLevels = [
|
||||
('none', 0), ('minimal', 1), ('verbose', 2), ('debug', 3)
|
||||
('none', 0), ('minimal', 1), ('verbose', 2), ('debug', 3), ('trace', 4)
|
||||
]
|
||||
|
||||
currentLevel = 0
|
||||
|
||||
@@ -172,15 +172,25 @@ def resolve_wildcards_arr(commandArr, params):
|
||||
|
||||
return commandArr
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Function to extract layer number from "execution_order"
|
||||
def get_layer(plugin):
|
||||
order = plugin.get("execution_order", "Layer_N")
|
||||
if order == "Layer_N":
|
||||
return float('inf') # Treat as the last layer if "execution_order" is missing
|
||||
return int(order.split('_')[1])
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def get_plugins_configs():
|
||||
pluginsList = [] # Create an empty list to store plugin configurations
|
||||
pluginsListSorted = [] # Sorted by "execution_order" : "Layer_0" first, Layer_N last
|
||||
|
||||
# Get a list of top-level directories in the specified pluginsPath
|
||||
dirs = next(os.walk(pluginsPath))[1]
|
||||
|
||||
# Sort the directories list if needed
|
||||
dirs.sort() # This will sort the directories alphabetically
|
||||
|
||||
# Loop through each directory (plugin folder) in dirs
|
||||
for d in dirs:
|
||||
# Check if the directory name does not start with "__" to skip python cache
|
||||
@@ -194,7 +204,10 @@ def get_plugins_configs():
|
||||
# Load the contents of the config.json file as a JSON object and append it to pluginsList
|
||||
pluginsList.append(json.loads(get_file_content(config_path)))
|
||||
|
||||
return pluginsList # Return the list of plugin configurations
|
||||
# Sort pluginsList based on "execution_order"
|
||||
pluginsListSorted = sorted(pluginsList, key=get_layer)
|
||||
|
||||
return pluginsListSorted # Return the sorted list of plugin configurations
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user