Plugins 0.3 - SQL support, UI CSS tweks, Lang fixes
This commit is contained in:
12
.github/workflows/docker_prod.yml
vendored
12
.github/workflows/docker_prod.yml
vendored
@@ -40,14 +40,12 @@ jobs:
|
||||
jokobsk/pi.alert
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}},value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}}.{{minor}},value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}},value=${{ inputs.version }}
|
||||
type=ref,event=branch,suffix=-{{ sha }}
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
|
||||
- name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
|
||||
132
back/pialert.py
132
back/pialert.py
@@ -52,8 +52,9 @@ sql_pholus_scan_all = "SELECT * FROM Pholus_Scan"
|
||||
sql_events_pending_alert = "SELECT * FROM Events where eve_PendingAlertEmail is not 0"
|
||||
sql_settings = "SELECT * FROM Settings"
|
||||
sql_plugins_objects = "SELECT * FROM Plugins_Objects"
|
||||
sql_language_strings = "SELECT * FROM Language_Strings"
|
||||
sql_language_strings = "SELECT * FROM Plugins_Language_Strings"
|
||||
sql_plugins_events = "SELECT * FROM Plugins_Events"
|
||||
sql_plugins_history = "SELECT * FROM Plugins_History ORDER BY 'Index' DESC LIMIT 50"
|
||||
sql_new_devices = """SELECT * FROM ( SELECT eve_IP as dev_LastIP, eve_MAC as dev_MAC FROM Events_Devices
|
||||
WHERE eve_PendingAlertEmail = 1
|
||||
AND eve_EventType = 'New Device'
|
||||
@@ -879,6 +880,10 @@ def cleanup_database ():
|
||||
mylog('verbose', [' Events: Delete all older than '+str(DAYS_TO_KEEP_EVENTS)+' days'])
|
||||
sql.execute ("DELETE FROM Events WHERE eve_DateTime <= date('now', '-"+str(DAYS_TO_KEEP_EVENTS)+" day')")
|
||||
|
||||
# Cleanup Plugin Events History
|
||||
mylog('verbose', [' Plugin Events History: Delete all older than '+str(DAYS_TO_KEEP_EVENTS)+' days'])
|
||||
sql.execute ("DELETE FROM Plugins_History WHERE DateTimeChanged <= date('now', '-"+str(DAYS_TO_KEEP_EVENTS)+" day')")
|
||||
|
||||
# Cleanup Pholus_Scan
|
||||
if PHOLUS_DAYS_DATA != 0:
|
||||
mylog('verbose', [' Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days'])
|
||||
@@ -2201,6 +2206,7 @@ def send_notifications ():
|
||||
global mail_text, mail_html, json_final, changedPorts_json_struc, partial_html, partial_txt, partial_json
|
||||
|
||||
deviceUrl = REPORT_DASHBOARD_URL + '/deviceDetails.php?mac='
|
||||
plugins_report = False
|
||||
|
||||
# Reporting section
|
||||
mylog('verbose', [' Check if something to report'])
|
||||
@@ -3168,6 +3174,25 @@ def upgradeDB ():
|
||||
); """
|
||||
sql.execute(sql_Plugins_Events)
|
||||
|
||||
# Plugin execution history
|
||||
sql_Plugins_History = """ CREATE TABLE IF NOT EXISTS Plugins_History(
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
); """
|
||||
sql.execute(sql_Plugins_History)
|
||||
|
||||
# Dynamically generated language strings
|
||||
# indicates, if Language_Strings table is available
|
||||
languageStringsMissing = sql.execute("""
|
||||
@@ -3252,6 +3277,7 @@ def update_api(isNotification = False, updateOnlyDataSources = []):
|
||||
["events_pending_alert", sql_events_pending_alert],
|
||||
["settings", sql_settings],
|
||||
["plugins_events", sql_plugins_events],
|
||||
["plugins_history", sql_plugins_history],
|
||||
["plugins_objects", sql_plugins_objects],
|
||||
["language_strings", sql_language_strings],
|
||||
["custom_endpoint", API_CUSTOM_SQL],
|
||||
@@ -3758,49 +3784,69 @@ def execute_plugin(plugin):
|
||||
# Execute command
|
||||
mylog('verbose', [' [Plugins] Executing: ', set_CMD])
|
||||
|
||||
try:
|
||||
# try runnning a subprocess with a forced timeout in case the subprocess hangs
|
||||
output = subprocess.check_output (command, universal_newlines=True, stderr=subprocess.STDOUT, timeout=(set_RUN_TIMEOUT))
|
||||
except subprocess.CalledProcessError as e:
|
||||
# An error occured, handle it
|
||||
mylog('none', [e.output])
|
||||
mylog('none', [' [Plugins] Error - enable LOG_LEVEL=debug and check logs'])
|
||||
except subprocess.TimeoutExpired as timeErr:
|
||||
mylog('none', [' [Plugins] TIMEOUT - the process forcefully terminated as timeout reached'])
|
||||
# python-script
|
||||
if plugin['data_source'] == 'python-script':
|
||||
|
||||
try:
|
||||
# try runnning a subprocess with a forced timeout in case the subprocess hangs
|
||||
output = subprocess.check_output (command, universal_newlines=True, stderr=subprocess.STDOUT, timeout=(set_RUN_TIMEOUT))
|
||||
except subprocess.CalledProcessError as e:
|
||||
# An error occured, handle it
|
||||
mylog('none', [e.output])
|
||||
mylog('none', [' [Plugins] Error - enable LOG_LEVEL=debug and check logs'])
|
||||
except subprocess.TimeoutExpired as timeErr:
|
||||
mylog('none', [' [Plugins] TIMEOUT - the process forcefully terminated as timeout reached'])
|
||||
|
||||
|
||||
# check the last run output
|
||||
f = open(pluginsPath + '/' + plugin["code_name"] + '/last_result.log', 'r+')
|
||||
newLines = f.read().split('\n')
|
||||
f.close()
|
||||
# check the last run output
|
||||
f = open(pluginsPath + '/' + plugin["code_name"] + '/last_result.log', 'r+')
|
||||
newLines = f.read().split('\n')
|
||||
f.close()
|
||||
|
||||
# cleanup - select only lines containing a separator to filter out unnecessary data
|
||||
newLines = list(filter(lambda x: '|' in x, newLines))
|
||||
# cleanup - select only lines containing a separator to filter out unnecessary data
|
||||
newLines = list(filter(lambda x: '|' in x, newLines))
|
||||
|
||||
if len(newLines) == 0: # check if the subprocess failed / there was no valid output
|
||||
mylog('none', [' [Plugins] No output received from the plugin - enable LOG_LEVEL=debug and check logs'])
|
||||
return
|
||||
else:
|
||||
mylog('verbose', ['[', timeNow(), '] [Plugins]: SUCCESS, received ', len(newLines), ' entries'])
|
||||
if len(newLines) == 0: # check if the subprocess failed / there was no valid output
|
||||
mylog('none', [' [Plugins] No output received from the plugin - enable LOG_LEVEL=debug and check logs'])
|
||||
return
|
||||
else:
|
||||
mylog('verbose', ['[', timeNow(), '] [Plugins]: SUCCESS, received ', len(newLines), ' entries'])
|
||||
|
||||
# # regular logging
|
||||
# for line in newLines:
|
||||
# append_line_to_file (pluginsPath + '/plugin.log', line +'\n')
|
||||
# # regular logging
|
||||
# for line in newLines:
|
||||
# append_line_to_file (pluginsPath + '/plugin.log', line +'\n')
|
||||
|
||||
# build SQL query parameters to insert into the DB
|
||||
sqlParams = []
|
||||
|
||||
for line in newLines:
|
||||
columns = line.split("|")
|
||||
# There has to be always 8 columns
|
||||
if len(columns) == 8:
|
||||
sqlParams.append((plugin["unique_prefix"], columns[0], columns[1], 'null', columns[2], columns[3], columns[4], columns[5], columns[6], 0, columns[7], 'null'))
|
||||
else:
|
||||
mylog('none', [' [Plugins]: Skipped invalid line in the output: ', line])
|
||||
|
||||
# build SQL query parameters to insert into the DB
|
||||
sqlParams = []
|
||||
# pialert-db-query
|
||||
if plugin['data_source'] == 'pialert-db-query':
|
||||
# build SQL query parameters to insert into the DB
|
||||
sqlParams = []
|
||||
|
||||
for line in newLines:
|
||||
columns = line.split("|")
|
||||
# There has to be always 8 columns
|
||||
if len(columns) == 8:
|
||||
sqlParams.append((plugin["unique_prefix"], columns[0], columns[1], 'null', columns[2], columns[3], columns[4], columns[5], columns[6], 0, columns[7], 'null'))
|
||||
else:
|
||||
mylog('none', [' [Plugins]: Skipped invalid line in the output: ', line])
|
||||
# set_CMD should contain a SQL query
|
||||
arr = get_sql_array (set_CMD)
|
||||
|
||||
for row in arr:
|
||||
# There has to be always 8 columns
|
||||
if len(row) == 8:
|
||||
sqlParams.append((plugin["unique_prefix"], row[0], row[1], 'null', row[2], row[3], row[4], row[5], row[6], 0, row[7], 'null'))
|
||||
else:
|
||||
mylog('none', [' [Plugins]: Skipped invalid sql result'])
|
||||
|
||||
if len(sqlParams) > 0:
|
||||
sql.executemany ("""INSERT INTO Plugins_Events ("Plugin", "Object_PrimaryID", "Object_SecondaryID", "DateTimeCreated", "DateTimeChanged", "Watched_Value1", "Watched_Value2", "Watched_Value3", "Watched_Value4", "Status" ,"Extra", "UserData") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", sqlParams)
|
||||
commitDB ()
|
||||
sql.executemany ("""INSERT INTO Plugins_History ("Plugin", "Object_PrimaryID", "Object_SecondaryID", "DateTimeCreated", "DateTimeChanged", "Watched_Value1", "Watched_Value2", "Watched_Value3", "Watched_Value4", "Status" ,"Extra", "UserData") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", sqlParams)
|
||||
commitDB ()
|
||||
|
||||
process_plugin_events(plugin)
|
||||
|
||||
@@ -3828,6 +3874,7 @@ def process_plugin_events(plugin):
|
||||
existingPluginObjectsCount = len(pluginObjects)
|
||||
|
||||
mylog('debug', [' [Plugins] Existing objects: ', existingPluginObjectsCount])
|
||||
mylog('debug', [' [Plugins] Events objects: ', len(plugEventsArr)])
|
||||
|
||||
# set status as new - will be changed later if conditions are fulfilled, e.g. entry found
|
||||
for eve in plugEventsArr:
|
||||
@@ -3844,9 +3891,6 @@ def process_plugin_events(plugin):
|
||||
if any(x.idsHash == tmpObject.idsHash for x in pluginObjects):
|
||||
mylog('debug', [' [Plugins] Found existing object'])
|
||||
pluginEvents[index].status = "exists"
|
||||
|
||||
# plugEventsArr.pop(index) # remove processed entry
|
||||
|
||||
index += 1
|
||||
|
||||
# Loop thru events and update the one that exist to determine if watched columns changed
|
||||
@@ -3858,11 +3902,8 @@ def process_plugin_events(plugin):
|
||||
# compare hash of the changed watched columns for uniqueness
|
||||
if any(x.watchedHash != tmpObject.watchedHash for x in pluginObjects):
|
||||
pluginEvents[index].status = "watched-changed"
|
||||
|
||||
# plugEventsArr.pop(index) # remove processed entry
|
||||
else:
|
||||
pluginEvents[index].status = "watched-not-changed"
|
||||
|
||||
index += 1
|
||||
|
||||
# Merge existing plugin objects with newly discovered ones and update existin ones with new values
|
||||
@@ -3882,20 +3923,21 @@ def process_plugin_events(plugin):
|
||||
# ----------------------------
|
||||
|
||||
# Update the Plugin_Objects
|
||||
|
||||
for plugObj in pluginObjects:
|
||||
|
||||
createdTime = plugObj.created
|
||||
|
||||
if plugObj.status == 'new':
|
||||
createdTime = plugObj.changed
|
||||
|
||||
q = f"UPDATE Plugins_Objects set Plugin = '{plugObj.pluginPref}', DateTimeChanged = '{plugObj.changed}', Watched_Value1 = '{plugObj.watched1}', Watched_Value2 = '{plugObj.watched2}', Watched_Value3 = '{plugObj.watched3}', Watched_Value4 = '{plugObj.watched4}', Status = '{plugObj.status}', Extra = '{plugObj.extra}' WHERE 'Index' = {plugObj.index}"
|
||||
|
||||
createdTime = plugObj.changed
|
||||
|
||||
sql.execute (q)
|
||||
sql.execute ("INSERT INTO Plugins_Objects (Plugin, Object_PrimaryID, Object_SecondaryID, DateTimeCreated, DateTimeChanged, Watched_Value1, Watched_Value2, Watched_Value3, Watched_Value4, Status, Extra, UserData) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", (plugObj.pluginPref, plugObj.primaryId , plugObj.secondaryId , createdTime, plugObj.changed , plugObj.watched1 , plugObj.watched2 , plugObj.watched3 , plugObj.watched4 , plugObj.status , plugObj.extra, plugObj.userData ))
|
||||
else:
|
||||
q = f"UPDATE Plugins_Objects set Plugin = '{plugObj.pluginPref}', DateTimeChanged = '{plugObj.changed}', Watched_Value1 = '{plugObj.watched1}', Watched_Value2 = '{plugObj.watched2}', Watched_Value3 = '{plugObj.watched3}', Watched_Value4 = '{plugObj.watched4}', Status = '{plugObj.status}', Extra = '{plugObj.extra}' WHERE 'Index' = {plugObj.index}"
|
||||
|
||||
sql.execute (q)
|
||||
|
||||
# Update the Plugins_Events with the new statuses
|
||||
|
||||
sql.execute ("DELETE FROM Plugins_Events")
|
||||
|
||||
for plugObj in pluginEvents:
|
||||
|
||||
@@ -7,9 +7,9 @@ services:
|
||||
network_mode: "host"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
|
||||
- ${APP_DATA_LOCATION}/pialert/config2:/home/pi/pialert/config
|
||||
# - ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
|
||||
- ${APP_DATA_LOCATION}/pialert/db:/home/pi/pialert/db
|
||||
- ${APP_DATA_LOCATION}/pialert/db2:/home/pi/pialert/db
|
||||
# (optional) useful for debugging if you have issues setting up the container
|
||||
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
|
||||
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
|
||||
|
||||
@@ -806,5 +806,18 @@ height: 50px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.plugin-content
|
||||
{
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
.plugin-content #tabs-content-location
|
||||
{
|
||||
margin-top: 20px;
|
||||
margin-left: 7px;
|
||||
margin-right: 7px;
|
||||
margin-bottom: 9px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -478,6 +478,7 @@ $lang['en_us'] = array(
|
||||
|
||||
'Plugins_Unprocessed_Events' => 'Unprocessed Events',
|
||||
'Plugins_Objects' => 'Plugin Objects',
|
||||
'Plugins_History' => 'Events History',
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Settings
|
||||
@@ -513,7 +514,7 @@ The arp-scan time itself depends on the number of IP addresses to check so set t
|
||||
'SCAN_CYCLE_MINUTES_name' => 'Scan cycle delay',
|
||||
'SCAN_CYCLE_MINUTES_description' => 'The delay between scans in minutes. If using arp-scan, the scan time itself depends on the number of IP addresses to check. This is influenced by the network mask set in the <a href="#SCAN_SUBNETS"><code>SCAN_SUBNETS</code> setting</a> at the top. Every IP takes a couple seconds to scan.',
|
||||
'DAYS_TO_KEEP_EVENTS_name' => 'Delete events older than',
|
||||
'DAYS_TO_KEEP_EVENTS_description' => 'This is a maintenance setting. This specifies the number of days worth of event entries that will be kept. All older events will be deleted periodically.',
|
||||
'DAYS_TO_KEEP_EVENTS_description' => 'This is a maintenance setting. This specifies the number of days worth of event entries that will be kept. All older events will be deleted periodically. Also applies on Plugin Events History.',
|
||||
'REPORT_DASHBOARD_URL_name' => 'Pi.Alert URL',
|
||||
'REPORT_DASHBOARD_URL_description' => 'This URL is used as the base for generating links in the emails. Enter full URL starting with <code>http://</code> including the port number (no trailig slash <code>/</code>).',
|
||||
'DIG_GET_IP_ARG_name' => 'Internet IP discovery',
|
||||
|
||||
@@ -19,7 +19,7 @@ switch($result){
|
||||
if (isset($pia_lang_selected) == FALSE or (strlen($pia_lang_selected) == 0)) {$pia_lang_selected = $defaultLang;}
|
||||
|
||||
//Language_Strings ("Language_Code", "String_Key", "String_Value", "Extra")
|
||||
$result = $db->query("SELECT * FROM Language_Strings");
|
||||
$result = $db->query("SELECT * FROM Plugins_Language_Strings");
|
||||
|
||||
// array
|
||||
$strings = array();
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
<!-- Main content ---------------------------------------------------------- -->
|
||||
<section class="content">
|
||||
<div class="nav-tabs-custom" style="margin-bottom: 0px;">
|
||||
<div class="nav-tabs-custom plugin-content" style="margin-bottom: 0px;">
|
||||
<ul id="tabs-location" class="nav nav-tabs">
|
||||
<!-- PLACEHOLDER -->
|
||||
</ul>
|
||||
<div id="tabs-content-location" class="nav nav-tabs">
|
||||
<!-- PLACEHOLDER -->
|
||||
</div>
|
||||
<div id="tabs-content-location" class="nav nav-tabs">
|
||||
<!-- PLACEHOLDER -->
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
@@ -146,6 +146,7 @@ function localize (obj, key) {
|
||||
pluginDefinitions = []
|
||||
pluginUnprocessedEvents = []
|
||||
pluginObjects = []
|
||||
pluginHistory = []
|
||||
|
||||
function getData(){
|
||||
|
||||
@@ -160,9 +161,14 @@ function getData(){
|
||||
$.get('api/table_plugins_objects.json', function(res) {
|
||||
|
||||
pluginObjects = res["data"];
|
||||
|
||||
$.get('api/table_plugins_history.json', function(res) {
|
||||
|
||||
generateTabs()
|
||||
pluginHistory = res["data"];
|
||||
|
||||
generateTabs()
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -194,6 +200,7 @@ function generateTabs()
|
||||
colDefinitions = []
|
||||
evRows = ""
|
||||
obRows = ""
|
||||
hiRows = ""
|
||||
|
||||
// Generate the header
|
||||
$.each(obj["database_column_definitions"], function(index, colDef){
|
||||
@@ -219,9 +226,22 @@ function generateTabs()
|
||||
}
|
||||
evRows += '<tr>' + clm + '</tr>'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generate the history rows
|
||||
for(i=0;i<pluginHistory.length;i++)
|
||||
{
|
||||
if(pluginHistory[i].Plugin == obj.unique_prefix)
|
||||
{
|
||||
clm = ""
|
||||
|
||||
for(j=0;j<colDefinitions.length;j++)
|
||||
{
|
||||
clm += '<td>'+ pluginHistory[i][colDefinitions[j].column] +'</td>'
|
||||
}
|
||||
hiRows += '<tr>' + clm + '</tr>'
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the object rows
|
||||
for(i=0;i<pluginObjects.length;i++)
|
||||
@@ -261,6 +281,14 @@ function generateTabs()
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#historyTarget" data-toggle="tab" >
|
||||
|
||||
<i class="fa fa-clock"></i> <?= lang('Plugins_History');?> (${pluginHistory.length})
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<ul>
|
||||
</div>
|
||||
|
||||
@@ -288,6 +316,17 @@ function generateTabs()
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="historyTarget" class="tab-pane">
|
||||
<table class="table table-striped">
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
${headersHtml}
|
||||
</tr>
|
||||
${hiRows}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
12
front/plugins/nmap_services/README.md
Executable file
12
front/plugins/nmap_services/README.md
Executable file
@@ -0,0 +1,12 @@
|
||||
## Overview
|
||||
|
||||
A simple sample plugin allowing for monitoring web services or urls. The status code corresponds to the commonly used [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status).
|
||||
|
||||
### Usage
|
||||
|
||||
- The user can specify which services (websites) to monitor via the `WEBMON_urls_to_check` setting.
|
||||
|
||||
### Notes
|
||||
|
||||
- Setting `(WEBMON_)SQL_internet_ip` is not used and specified for demonstration purposes only.
|
||||
- Parameters `macs` and `internet_ip` in the `config.json` file are not used and specified for demonstration purposes only.
|
||||
275
front/plugins/nmap_services/config.json
Executable file
275
front/plugins/nmap_services/config.json
Executable file
@@ -0,0 +1,275 @@
|
||||
{
|
||||
"code_name": "nmap_services",
|
||||
"unique_prefix": "NMAPSRV",
|
||||
"data_source": "pialert-db-query",
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name" : [{
|
||||
"language_code":"en_us",
|
||||
"string" : "Services"
|
||||
}],
|
||||
"icon":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "<i class=\"fa-solid fa-search\"></i>"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code":"en_us",
|
||||
"string" : "This plugin shows all services discovered by NMAP scans."
|
||||
}],
|
||||
"params" : [],
|
||||
"database_column_definitions":
|
||||
[
|
||||
{
|
||||
"column": "Index",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "N/A"
|
||||
}]
|
||||
} ,
|
||||
{
|
||||
"column": "Plugin",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "N/A"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Object_PrimaryID",
|
||||
"show": true,
|
||||
"type": "url",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Device name"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Object_SecondaryD",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Ip and Port"
|
||||
}]
|
||||
} ,
|
||||
{
|
||||
"column": "DateTimeCreated",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Created"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "DateTimeChanged",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Changed"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value1",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Service"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value2",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "State"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value3",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "N/A"
|
||||
}]
|
||||
} ,
|
||||
{
|
||||
"column": "Watched_Value4",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "N/A"
|
||||
}]
|
||||
} ,
|
||||
{
|
||||
"column": "Extra",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Extra"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Status",
|
||||
"show": true,
|
||||
"type": "replace",
|
||||
"default_value":"",
|
||||
"options": [
|
||||
{
|
||||
"equals": "watched-not-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
|
||||
},
|
||||
{
|
||||
"equals": "watched-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "new",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
|
||||
}
|
||||
],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Status"
|
||||
}]
|
||||
}
|
||||
],
|
||||
"settings":[
|
||||
{
|
||||
"function": "RUN",
|
||||
"type": "selecttext",
|
||||
"default_value":"disabled",
|
||||
"options": ["disabled", "once", "schedule", "always_after_scan", "on_new_device"],
|
||||
"localized": ["name", "description"],
|
||||
"name" :[{
|
||||
"language_code":"en_us",
|
||||
"string" : "When to run"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code":"en_us",
|
||||
"string" : "Specify when the SQL query is executed."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "CMD",
|
||||
"type": "text",
|
||||
"default_value":"SELECT dv.dev_Name as Object_PrimaryID, cast(dv.dev_LastIP as VARCHAR(100)) || ':' || cast( SUBSTR(ns.Port ,0, INSTR(ns.Port , '/')) as VARCHAR(100)) as Object_SecondaryID, datetime() as DateTime, ns.Service as Watched_Value1, ns.State as Watched_Value2, 'null' as Watched_Value3, 'null' as Watched_Value4, ns.Extra as Extra FROM (SELECT * FROM Nmap_Scan) ns LEFT JOIN (SELECT dev_Name, dev_MAC, dev_LastIP FROM Devices) dv ON ns.MAC = dv.dev_MAC",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code":"en_us",
|
||||
"string" : "SQL to run"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code":"en_us",
|
||||
"string" : "This SQL query is used to populate the coresponding UI tables under the Plugins section."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "RUN_SCHD",
|
||||
"type": "text",
|
||||
"default_value":"0 2 * * *",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code":"en_us",
|
||||
"string" : "Schedule"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code":"en_us",
|
||||
"string" : "Only enabled if you select <code>schedule</code> in the <a href=\"#NMAPSRV_RUN\"><code>NMAPSRV_RUN</code> setting</a>. Make sure you enter the schedule in the correct cron-like format (e.g. validate at <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). For example entering <code>0 4 * * *</code> will run the scan after 4 am in the <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> you set above</a>. Will be run NEXT time the time passes."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "RUN_TIMEOUT",
|
||||
"type": "integer",
|
||||
"default_value":5,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code":"en_us",
|
||||
"string" : "Run timeout"
|
||||
},
|
||||
{
|
||||
"language_code":"de_de",
|
||||
"string" : "Wartezeit"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code":"en_us",
|
||||
"string" : "Maximum time in seconds to wait for the call to finish. If this time is exceeded the script is aborted."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "WATCH",
|
||||
"type": "multiselect",
|
||||
"default_value":["Watched_Value1"],
|
||||
"options": ["Watched_Value1","Watched_Value2","Watched_Value3","Watched_Value4"],
|
||||
"localized": ["name", "description"],
|
||||
"name" :[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Watched"
|
||||
}] ,
|
||||
"description":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Send a notification if selected values change. Use <code>CTRL + Click</code> to select/deselect. <ul> <li><code>Watched_Value1</code> is service type (e.g.: http, ssh)</li><li><code>Watched_Value2</code> is Status (open or closed)</li><li><code>Watched_Value3</code> unused </li><li><code>Watched_Value4</code> unused </li></ul>"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "REPORT_ON",
|
||||
"type": "multiselect",
|
||||
"default_value":["new","watched-changed"],
|
||||
"options": ["new","watched-changed","watched-not-changed"],
|
||||
"localized": ["name", "description"],
|
||||
"name" :[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Report on"
|
||||
}] ,
|
||||
"description":[{
|
||||
"language_code":"en_us",
|
||||
"string" : "Send a notification only on these statuses. <code>new</code> means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered. <code>watched-changed</code> means that selected <code>Watched_ValueN</code> columns changed."
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"code_name": "website_monitor",
|
||||
"unique_prefix": "WEBMON",
|
||||
"unique_prefix": "WEBMON",
|
||||
"data_source": "python-script",
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name" : [{
|
||||
"language_code":"en_us",
|
||||
@@ -192,15 +193,15 @@
|
||||
"options": [
|
||||
{
|
||||
"equals": "watched-not-changed",
|
||||
"replacement": "<i class='fa-solid fa-square-check'></i>"
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
|
||||
},
|
||||
{
|
||||
"equals": "watched-changed",
|
||||
"replacement": "<i class='fa-solid fa-triangle-exclamation'></i>"
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "new",
|
||||
"replacement": "<i class='fa-solid fa-circle-plus'></i>"
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
|
||||
}
|
||||
],
|
||||
"localized": ["name"],
|
||||
@@ -276,7 +277,7 @@
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code":"en_us",
|
||||
"string" : "API endpoint"
|
||||
"string" : "API endpoint (not implemented)"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code":"en_us",
|
||||
@@ -299,7 +300,7 @@
|
||||
}],
|
||||
"description": [{
|
||||
"language_code":"en_us",
|
||||
"string" : "Maximum time in seconds to wait for a Website monitor check to finish for any url."
|
||||
"string" : "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
|
||||
}]
|
||||
},
|
||||
{
|
||||
@@ -335,7 +336,7 @@
|
||||
{
|
||||
"function": "urls_to_check",
|
||||
"type": "list",
|
||||
"default_value":[],
|
||||
"default_value":["https://google.com", "https://duck.com"],
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
|
||||
Reference in New Issue
Block a user