From 6d5eeb88d31e9b02495ae8c07a498003752ec326 Mon Sep 17 00:00:00 2001 From: Jokob-sk Date: Sun, 19 Mar 2023 15:48:20 +1100 Subject: [PATCH] dhcp.leases v0.1 --- Dockerfile | 2 +- back/pialert.py | 1 - docker-compose.yml | 6 +- front/plugins/dhcp_leases/README.md | 32 +++ front/plugins/dhcp_leases/config.json | 322 ++++++++++++++++++++++++++ front/plugins/dhcp_leases/script.py | 116 ++++++++++ 6 files changed, 475 insertions(+), 4 deletions(-) create mode 100755 front/plugins/dhcp_leases/README.md create mode 100755 front/plugins/dhcp_leases/config.json create mode 100755 front/plugins/dhcp_leases/script.py diff --git a/Dockerfile b/Dockerfile index cd800b59..1580bc27 100755 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ ENV USER=pi USER_ID=1000 USER_GID=1000 TZ=Europe/London PORT=20211 RUN apt-get update \ && apt-get install --no-install-recommends tini ca-certificates curl libwww-perl arp-scan perl apt-utils cron sudo nginx-light php php-cgi php-fpm php-sqlite3 php-curl sqlite3 dnsutils net-tools python3 iproute2 nmap python3-pip zip -y \ - && pip3 install requests paho-mqtt scapy cron-converter pytz json2table \ + && pip3 install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases \ && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 \ && apt-get clean autoclean \ && apt-get autoremove \ diff --git a/back/pialert.py b/back/pialert.py index f9e2f6b7..a38c8ef6 100755 --- a/back/pialert.py +++ b/back/pialert.py @@ -3356,7 +3356,6 @@ class api_endpoint_class: apiEndpoints[changedIndex].hash = self.hash else: mylog('info', [f' [API] ERROR Updating {self.fileName}']) - #------------------------------------------------------------------------------- diff --git a/docker-compose.yml b/docker-compose.yml index 30e093c3..fd148df4 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,12 +7,14 @@ services: network_mode: "host" restart: unless-stopped volumes: - - ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config + - ${APP_DATA_LOCATION}/pialert2/config:/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}/pialert2/db:/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 + - ${APP_DATA_LOCATION}/pialert/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases + - ${APP_DATA_LOCATION}/pialert/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases - ${DEV_LOCATION}/back/pialert.py:/home/pi/pialert/back/pialert.py - ${DEV_LOCATION}/back/report_template.html:/home/pi/pialert/back/report_template.html - ${DEV_LOCATION}/back/report_template_new_version.html:/home/pi/pialert/back/report_template_new_version.html diff --git a/front/plugins/dhcp_leases/README.md b/front/plugins/dhcp_leases/README.md new file mode 100755 index 00000000..e96bc5d8 --- /dev/null +++ b/front/plugins/dhcp_leases/README.md @@ -0,0 +1,32 @@ +## Overview + +A plugin allowing for importing devices from DHCP.leases files. + +### Usage + +- Specify full paths of all `dhcp.leases` files you want to import and watch in the `DHCPLSS_paths_to_check`setting. +- Map the paths specified in the `DHCPLSS_paths_to_check`setting in your `docker-compose.yml` file. + +#### Example: + + +`docker-compose.yml` excerpt: + +```yaml + volumes: + ... + # mapping different dhcp.leases files + - /first/location/dhcp.leases:/mnt/dhcp1.leases + - /second/location/dhcp.leases:/mnt/dhcp2.leases + ... +``` + +`DHCPLSS_paths_to_check` Setting: + +```python +DHCPLSS_paths_to_check = ['/mnt/dhcp1.leases','/mnt/dhcp2.leases'] +``` + +### Notes + +- No specific configuration needed. \ No newline at end of file diff --git a/front/plugins/dhcp_leases/config.json b/front/plugins/dhcp_leases/config.json new file mode 100755 index 00000000..4616911f --- /dev/null +++ b/front/plugins/dhcp_leases/config.json @@ -0,0 +1,322 @@ +{ + "code_name": "dhcp_leases", + "unique_prefix": "DHCPLSS", + "enabled": true, + "data_source": "python-script", + "localized": ["display_name", "description", "icon"], + "display_name" : [{ + "language_code":"en_us", + "string" : "DHCP Leases" + }], + "icon":[{ + "language_code":"en_us", + "string" : "" + }], + "description": [{ + "language_code":"en_us", + "string" : "This plugin is to import devices from dhcp.leases files." + }], + "params" : [ + { + "name" : "paths", + "type" : "setting", + "value" : "DHCPLSS_paths_to_check" + }], + "database_column_definitions": + [ + { + "column": "Index", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "N/A" + }] + } , + { + "column": "Plugin", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "N/A" + }] + }, + { + "column": "Object_PrimaryID", + "css_classes": "col-sm-2", + "show": true, + "type": "devicemac", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "IP" + }] + }, + { + "column": "Object_SecondaryID", + "css_classes": "col-sm-2", + "show": true, + "type": "deviceip", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "MAC address" + }] + } , + { + "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", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Changed" + }] + }, + { + "column": "Watched_Value1", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Is active" + }] + }, + { + "column": "Watched_Value2", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Hostname" + }] + }, + { + "column": "Watched_Value3", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Hardware" + }] + } , + { + "column": "Watched_Value4", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "State" + }] + } , + { + "column": "UserData", + "css_classes": "col-sm-2", + "show": false, + "type": "textboxsave", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Comments" + }] + }, + { + "column": "Extra", + "css_classes": "col-sm-3", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "DHCP leases file" + }] + }, + { + "column": "Status", + "css_classes": "col-sm-1", + "show": true, + "type": "replace", + "default_value":"", + "options": [ + { + "equals": "watched-not-changed", + "replacement": "
" + }, + { + "equals": "watched-changed", + "replacement": "
" + }, + { + "equals": "new", + "replacement": "
" + } + ], + "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" : "Enable import of devices from dhcp.leases files. If you select schedule the scheduling settings from below are applied. If you select once the scan is run only once on start of the application (container) or after you update your settings." + }] + }, + { + "function": "CMD", + "type": "text", + "default_value":"python3 /home/pi/pialert/front/plugins/dhcp_leases/script.py paths={paths}", + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code":"en_us", + "string" : "Command" + }], + "description": [{ + "language_code":"en_us", + "string" : "Command to run" + }] + }, + { + "function": "paths_to_check", + "type": "list", + "default_value":["/mnt/dhcp1.leases", "/mnt/dhcp2.leases"], + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code":"en_us", + "string" : "Files" + }], + "description": [{ + "language_code":"en_us", + "string" : "Add all dhcp.leases mapped paths to watch. Enter full path within the container, e.g. /mnt/dhcp2.leases. You must map these files accordingly in your docker-compose.yml file." + }] + }, + { + "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 schedule in the DHCPLSS_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. 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 script to finish. If this time is exceeded the script is aborted." + }] + }, + { + "function": "WATCH", + "type": "multiselect", + "default_value":["Watched_Value1", "Watched_Value4"], + "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 CTRL + Click to select/deselect. " + }] + }, + { + "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. new means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered. watched-changed means that selected Watched_ValueN columns changed." + }] + } + ] +} + diff --git a/front/plugins/dhcp_leases/script.py b/front/plugins/dhcp_leases/script.py new file mode 100755 index 00000000..c9b361b8 --- /dev/null +++ b/front/plugins/dhcp_leases/script.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# Based on the work of https://github.com/leiweibau/Pi.Alert + +from __future__ import unicode_literals +from time import sleep, time, strftime +import requests +import pathlib +import threading +import subprocess +import socket +import argparse +import io +import sys +from requests.packages.urllib3.exceptions import InsecureRequestWarning +import pwd +import os +from dhcp_leases import DhcpLeases + +curPath = str(pathlib.Path(__file__).parent.resolve()) +log_file = curPath + '/script.log' +last_run = curPath + '/last_result.log' + +print(last_run) + +# Workflow + +def main(): + + last_run_logfile = open(last_run, 'a') + + # empty file + last_run_logfile.write("") + + parser = argparse.ArgumentParser(description='Import devices from dhcp.leases files') + parser.add_argument('paths', action="store", help="absolute dhcp.leases file paths to check separated by ','") + values = parser.parse_args() + + # parse output + newEntries = [] + + if values.paths: + for path in values.paths.split('=')[1].split(','): + + + newEntries = get_entries(newEntries, path) + + + for e in newEntries: + # Insert list into the log + service_monitoring_log(e.primaryId, e.secondaryId, e.created, e.watched1, e.watched2, e.watched3, e.watched4, e.extra, e.foreignKey ) + + +# ----------------------------------------------------------------------------- +def service_monitoring_log(primaryId, secondaryId, created, watched1, watched2 = '', watched3 = '', watched4 = '', extra ='', foreignKey ='' ): + + if watched1 == '': + watched1 = 'null' + if watched2 == '': + watched2 = 'null' + if watched3 == '': + watched3 = 'null' + if watched4 == '': + watched4 = 'null' + + with open(last_run, 'a') as last_run_logfile: + # https://www.duckduckgo.com|192.168.0.1|2023-01-02 15:56:30|200|0.9898|null|null|Best search engine|null + last_run_logfile.write("{}|{}|{}|{}|{}|{}|{}|{}|{}\n".format( + primaryId, + secondaryId, + created, + watched1, + watched2, + watched3, + watched4, + extra, + foreignKey + ) + ) +# ----------------------------------------------------------------------------- +def get_entries(newEntries, path): + + + leases = DhcpLeases(path) + leasesList = leases.get() + + for lease in leasesList: + + tmpPlugObj = plugin_object_class(lease.ethernet, lease.ip, lease.active, lease.hostname, lease.hardware, lease.binding_state, path) + + newEntries.append(tmpPlugObj) + + return newEntries + +# ------------------------------------------------------------------- +class plugin_object_class: + def __init__(self, primaryId = '',secondaryId = '', watched1 = '',watched2 = '',watched3 = '',watched4 = '',extra = '',foreignKey = ''): + self.pluginPref = '' + self.primaryId = primaryId + self.secondaryId = secondaryId + self.created = strftime("%Y-%m-%d %H:%M:%S") + self.changed = '' + self.watched1 = watched1 + self.watched2 = watched2 + self.watched3 = watched3 + self.watched4 = watched4 + self.status = '' + self.extra = extra + self.userData = '' + self.foreignKey = foreignKey + +#=============================================================================== +# BEGIN +#=============================================================================== +if __name__ == '__main__': + main() +