From 960a3ebe14b7ded59c4cfd6f7916a818b5ac456a Mon Sep 17 00:00:00 2001 From: Jokob-sk Date: Fri, 4 Aug 2023 06:41:11 +1000 Subject: [PATCH] Flows work + #302 --- front/plugins/arp_scan/README.md | 27 +++ front/plugins/arp_scan/config.json | 217 +++++++++++++++++++++++ front/plugins/arp_scan/script.py | 48 +++++ front/plugins/known_template/config.json | 4 +- pialert/flows.py | 31 ++++ pialert/flows/apply_template.json | 69 +++++-- pialert/scanners/pholusscan.py | 1 + 7 files changed, 384 insertions(+), 13 deletions(-) create mode 100755 front/plugins/arp_scan/README.md create mode 100755 front/plugins/arp_scan/config.json create mode 100755 front/plugins/arp_scan/script.py create mode 100644 pialert/flows.py diff --git a/front/plugins/arp_scan/README.md b/front/plugins/arp_scan/README.md new file mode 100755 index 00000000..622c5306 --- /dev/null +++ b/front/plugins/arp_scan/README.md @@ -0,0 +1,27 @@ +## Overview + +A plugin allowing for importing Un-Discoverable devices from the settings page. +The main usecase is to add dumb network gear like unmanaged hubs and switches to the network view. +There might be other usecases, please let me know. + +### Usage + +- Go to settings and find Un-Discoverabe Devices in the list of plugins. +- Enable the plugin by changing the RUN parameter from disabled to `once` or `always_after_scan`. +- Add the name of your device to the list. (remove the sample entry first) +- SAVE +- wait for the next scan to finish + +#### Examples: +Settings: +![settings](https://github.com/Data-Monkey/Pi.Alert/assets/7224371/52883307-19a5-4602-b13a-9825461f6cc4) + +resulting in these devices: +![devices](https://github.com/Data-Monkey/Pi.Alert/assets/7224371/9f7659e7-75a8-4ae9-9f5f-781bdbcbc949) + +Allowing Un-Discoverable devices like hubs, switches or APs to be added to the network view. +![network](https://github.com/Data-Monkey/Pi.Alert/assets/7224371/b5ccc3b3-f5fd-4f5b-b0f0-e4e637c6da33) + +### Known Limitations + - Un-Discoverable Devices always show as offline. That is expected as they can not be discovered by Pi.Alert. + - All IPs are set to 0.0.0.0 therefore the "Random MAC" icon might show up. diff --git a/front/plugins/arp_scan/config.json b/front/plugins/arp_scan/config.json new file mode 100755 index 00000000..4f84c868 --- /dev/null +++ b/front/plugins/arp_scan/config.json @@ -0,0 +1,217 @@ +{ + "code_name": "undiscoverables", + "unique_prefix": "ARPSCAN", + "enabled": true, + "data_source": "python-script", + "mapped_to_table": "DHCP_Leases", + + "localized": ["display_name", "description", "icon"], + + "display_name": [ + { + "language_code": "en_us", + "string": "Un-Discoverable Devices" + } + ], + "icon": [ + { + "language_code": "en_us", + "string": "" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "This plugin is to import undiscoverable devices from a file." + } + ], + "params" : [ + { + "name" : "devices", + "type" : "setting", + "value" : "UNDIS_devices_to_import" + }], + + "settings": [ + { + "function": "RUN", + "type": "text.select", + "default_value":"disabled", + "options": ["disabled", "once", "always_after_scan"], + "localized": ["name", "description"], + "name" :[{ + "language_code":"en_us", + "string" : "When to run" + }], + "description": [{ + "language_code":"en_us", + "string" : "When enabled, ONCE is the preferred option. It runs at startup and after every save of the config here.
Changes will only show in the devices after the next scan!" + }] + }, + { + "function": "CMD", + "type": "text", + "default_value": "python3 /home/pi/pialert/front/plugins/undiscoverables/script.py devices={devices}", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Command" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Command to run. This can not be changed" + } + ] + }, + + { + "function": "RUN_TIMEOUT", + "type": "integer", + "default_value": 10, + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Run timeout" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted." + } + ] + }, + { + "function": "WATCH", + "type": "lable", + "default_value": [], + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Watched" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Undiscoverable Devices can not change their status, no watch is enabled." + } + ] + }, + { + "function": "REPORT_ON", + "type": "lable", + "default_value": [], + "options": ["new", "watched-changed", "watched-not-changed"], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Report on" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "No notifications will be sent." + } + ] + }, + { + "function": "devices_to_import", + "type": "list", + "default_value":["dummy_router"], + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code":"en_us", + "string" : "UnDiscoverable Devices" + }], + "description": [{ + "language_code":"en_us", + "string" : "Devices to be added to the devices list." + }] + } + ], + + "database_column_definitions": + [ + { + "column": "Watched_Value1", + "mapped_to_column": "DHCP_Name", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Device Name" + }] + }, + { + "column": "Object_PrimaryID", + "mapped_to_column": "DHCP_MAC", + "css_classes": "col-sm-2", + "show": true, + "type": "devicemac", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "MAC address" + }] + }, + { + "column": "Object_SecondaryID", + "mapped_to_column": "DHCP_IP", + "css_classes": "col-sm-2", + "show": true, + "type": "deviceip", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "IP" + }] + } , + { + "column": "DateTimeCreated", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Created" + }] + }, + { + "column": "DateTimeChanged", + "mapped_to_column": "DHCP_DateTime", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Changed" + }] + } + ] +} \ No newline at end of file diff --git a/front/plugins/arp_scan/script.py b/front/plugins/arp_scan/script.py new file mode 100755 index 00000000..ecfece0c --- /dev/null +++ b/front/plugins/arp_scan/script.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# test script by running python script.py devices=test,dummy + +import os +import pathlib +import argparse +import sys + +sys.path.append("/home/pi/pialert/front/plugins") + +from plugin_helper import Plugin_Objects + +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') + + + +def main(): + + # the script expects a parameter in the format of devices=device1,device2,... + parser = argparse.ArgumentParser(description='Import devices from settings') + parser.add_argument('devices', action="store", help="list of device names separated by ','") + values = parser.parse_args() + + UNDIS_devices = Plugin_Objects( RESULT_FILE ) + + if values.devices: + for fake_dev in values.devices.split('=')[1].split(','): + UNDIS_devices.add_object( + primaryId=fake_dev, # MAC (Device Name) + secondaryId="0.0.0.0", # IP Address (always 0.0.0.0) + watched1=fake_dev, # Device Name + watched2="", + watched3="", + watched4="", + extra="", + foreignKey="") + + UNDIS_devices.write_result_file() + + return 0 + +#=============================================================================== +# BEGIN +#=============================================================================== +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/front/plugins/known_template/config.json b/front/plugins/known_template/config.json index ce750874..c7e3b9ae 100755 --- a/front/plugins/known_template/config.json +++ b/front/plugins/known_template/config.json @@ -39,9 +39,9 @@ "settings":[ { "function": "target_macs", - "type": "readonly", + "type": "list.readonly", "maxLength": 50, - "default_value": "", + "default_value": [], "options": [], "localized": ["name", "description"], "name": [ diff --git a/pialert/flows.py b/pialert/flows.py new file mode 100644 index 00000000..87b59ba4 --- /dev/null +++ b/pialert/flows.py @@ -0,0 +1,31 @@ +import json + +def update_value(json_data, object_path, key, value, target_property, desired_value): + # Helper function to traverse the JSON structure and get the target object + def traverse(obj, path): + keys = path.split(".") + for key in keys: + if isinstance(obj, list): + key = int(key) + obj = obj[key] + return obj + + # Helper function to update the target property with the desired value + def update(obj, path, key, value, target_property, desired_value): + keys = path.split(".") + for i, key in enumerate(keys): + if isinstance(obj, list): + key = int(key) + # Check if we have reached the desired object + if i == len(keys) - 1 and obj[key][key] == value: + # Update the target property with the desired value + obj[key][target_property] = desired_value + else: + obj = obj[key] + return obj + + # Get the target object based on the object path + target_obj = traverse(json_data, object_path) + # Update the value in the target object + updated_obj = update(json_data, object_path, key, value, target_property, desired_value) + return updated_obj \ No newline at end of file diff --git a/pialert/flows/apply_template.json b/pialert/flows/apply_template.json index 0df0952d..e6fd3f17 100755 --- a/pialert/flows/apply_template.json +++ b/pialert/flows/apply_template.json @@ -1,13 +1,54 @@ { - "name":"apply_template", - "triggers": [ + "name":"apply_template", + "params" : [ { - "type": "new", - "object": - { - "type": "db.row", - "target": "Devices" - } + "name" : "target_macs", + "type" : "setting", + "value" : "KNWN_target_macs" + }, + { + "name" : "dev_AlertDeviceDown", + "type" : "setting", + "value" : "KNWN_dev_AlertDeviceDown" + }, + { + "name" : "dev_AlertEvents", + "type" : "setting", + "value" : "KNWN_dev_AlertEvents" + }, + { + "name" : "", + "type":"array", + "value": "trigger.Object_PrimaryID" + }, + { + "type":"array", + "value": "trigger" + } + ], + "trigger": [ + { + "object_type": "dbtable", + "object_key": "Devices", + "object_event": "new", + "object_filter": "", + "object_mappings": + [ + { + "column": "Object_PrimaryID", + "mapped_to_column": "Dev_MAC", + "css_classes": "col-sm-2", + "show": true, + "type": "devicemac", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "MAC address" + }] + } + ] } ], "steps": [ @@ -51,9 +92,15 @@ "params": { "unique_prefix": "KNWN", - "override":{ - - } + "overrides":[ + { + "object_path": "settings.0", + "key":"function", + "value":"target_macs", + "target_property":"default_value", + "desired_value": "triggers.keys" + } + ] } } diff --git a/pialert/scanners/pholusscan.py b/pialert/scanners/pholusscan.py index 8a31946d..9dce94aa 100755 --- a/pialert/scanners/pholusscan.py +++ b/pialert/scanners/pholusscan.py @@ -81,6 +81,7 @@ def cleanResult(str): str = str.replace(".lan", "") str = str.replace(".home", "") str = re.sub(r'-[a-fA-F0-9]{32}', '', str) # removing last part of e.g. Nest-Audio-ff77ff77ff77ff77ff77ff77ff77ff77 + str = re.sub(r'#.*', '', str) # Remove everything after '#' including the '#' # remove trailing dots if str.endswith('.'): str = str[:-1]