UNIFI, undiscoverables, docs work

This commit is contained in:
Jokob-sk
2023-09-02 13:30:19 +10:00
parent 854ef20826
commit 25b54d1f62
5 changed files with 128 additions and 152 deletions

View File

@@ -17,9 +17,9 @@
- [set_password (SETPWD)](/front/plugins/set_password/) - [set_password (SETPWD)](/front/plugins/set_password/)
- [nmap_scan (NMAP)](/front/plugins/nmap_scan/) - [nmap_scan (NMAP)](/front/plugins/nmap_scan/)
### SQL query based plugins ### SQL query-based plugins
- N/A, but the External SQLite based plugins work very similar - No example available, but the External SQLite based plugins work very similar
### template based plugins ### template based plugins
@@ -610,7 +610,7 @@ The UI will adjust how columns are displayed in the UI based on the resolvers de
| `device_name_mac` | The value is considered to be a MAC address, and a link pointing to the device with the given IP is generated. The link label is resolved as the target device name. | | `device_name_mac` | The value is considered to be a MAC address, and a link pointing to the device with the given IP is generated. The link label is resolved as the target device name. |
| `url` | The value is considered to be a URL, so a link is generated. | | `url` | The value is considered to be a URL, so a link is generated. |
| `textbox_save` | Generates an editable and saveable text box that saves values in the database. Primarily intended for the `UserData` database column in the `Plugins_Objects` table. | | `textbox_save` | Generates an editable and saveable text box that saves values in the database. Primarily intended for the `UserData` database column in the `Plugins_Objects` table. |
| `url_http_https` | Generates towo links with the `https` and `http` prefix as lock icons. | | `url_http_https` | Generates two links with the `https` and `http` prefix as lock icons. |
> [!NOTE] > [!NOTE]

View File

@@ -226,7 +226,7 @@
"mapped_to_column": "cur_MAC", "mapped_to_column": "cur_MAC",
"css_classes": "col-sm-2", "css_classes": "col-sm-2",
"show": true, "show": true,
"type": "device_mac", "type": "label",
"default_value":"", "default_value":"",
"options": [], "options": [],
"localized": ["name"], "localized": ["name"],
@@ -291,6 +291,23 @@
"language_code":"es_es", "language_code":"es_es",
"string" : "Cambiado" "string" : "Cambiado"
}] }]
},
{
"column": "ForeignKey",
"css_classes": "col-sm-2",
"show": false,
"type": "device_mac",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "MAC"
},
{
"language_code":"es_es",
"string" : "MAC"
}]
} }
] ]
} }

View File

@@ -5,6 +5,7 @@ import os
import pathlib import pathlib
import argparse import argparse
import sys import sys
import hashlib
sys.path.append("/home/pi/pialert/front/plugins") sys.path.append("/home/pi/pialert/front/plugins")
sys.path.append('/home/pi/pialert/pialert') sys.path.append('/home/pi/pialert/pialert')
@@ -31,6 +32,9 @@ def main():
if values.devices: if values.devices:
for fake_dev in values.devices.split('=')[1].split(','): for fake_dev in values.devices.split('=')[1].split(','):
fake_mac = string_to_mac_hash(fake_dev)
plugin_objects.add_object( plugin_objects.add_object(
primaryId=fake_dev, # MAC (Device Name) primaryId=fake_dev, # MAC (Device Name)
secondaryId="0.0.0.0", # IP Address (always 0.0.0.0) secondaryId="0.0.0.0", # IP Address (always 0.0.0.0)
@@ -39,12 +43,21 @@ def main():
watched3="", watched3="",
watched4="", watched4="",
extra="", extra="",
foreignKey="") foreignKey=fake_mac)
plugin_objects.write_result_file() plugin_objects.write_result_file()
return 0 return 0
def string_to_mac_hash(input_string):
# Calculate a hash using SHA-256
sha256_hash = hashlib.sha256(input_string.encode()).hexdigest()
# Take the first 12 characters of the hash and format as a MAC address
mac_hash = ':'.join(sha256_hash[i:i+2] for i in range(0, 12, 2))
return mac_hash
#=============================================================================== #===============================================================================
# BEGIN # BEGIN
#=============================================================================== #===============================================================================

View File

@@ -2,59 +2,47 @@
# Inspired by https://github.com/stevehoek/Pi.Alert # Inspired by https://github.com/stevehoek/Pi.Alert
# Example call # Example call
# python3 /home/pi/pialert/front/plugins/unifi_import/script.py username=pialert password=passw0rd host=192.168.1.1 site=default protocol=https port=8443 version='UDMP-unifiOS'
# python3 /home/pi/pialert/front/plugins/unifi_import/script.py username=pialert password=passw0rd host=192.168.1.1 site=default protocol=https:// port=8443 version='UDMP-unifiOS'
# python3 /home/pi/pialert/front/plugins/unifi_import/script.py username=pialert password=passw0rd host=192.168.1.1 sites=sdefault port=8443 verifyssl=false version=v5 # python3 /home/pi/pialert/front/plugins/unifi_import/script.py username=pialert password=passw0rd host=192.168.1.1 sites=sdefault port=8443 verifyssl=false version=v5
from __future__ import unicode_literals from __future__ import unicode_literals
from time import sleep, time, strftime from time import strftime
import requests
from requests import Request, Session, packages
import pathlib
import threading
import subprocess
import socket
import json
import argparse import argparse
import logging import logging
import pathlib
import os
import json
import sys
import requests
from requests import Request, Session, packages
from requests.packages.urllib3.exceptions import InsecureRequestWarning from requests.packages.urllib3.exceptions import InsecureRequestWarning
from pyunifi.controller import Controller from pyunifi.controller import Controller
# Add your paths here
sys.path.append("/home/pi/pialert/front/plugins")
sys.path.append('/home/pi/pialert/pialert')
curPath = str(pathlib.Path(__file__).parent.resolve()) from plugin_helper import Plugin_Object, Plugin_Objects
log_file = curPath + '/script.log' from logger import mylog
last_run = curPath + '/last_result.log'
logging.basicConfig(
filename=log_file,
level=logging.INFO,
format='%(asctime)s:%(levelname)s:%(name)s:%(message)s'
)
unifi_logger = logging.getLogger('[UNIFI]')
unifi_logger.setLevel(logging.INFO)
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')
requests.packages.urllib3.disable_warnings(InsecureRequestWarning) requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# Workflow # Workflow
def main(): def main():
unifi_logger.info('Start scan') mylog('verbose', ['[UNFIMP] In script'])
# init global variables # init global variables
global UNIFI_USERNAME, UNIFI_PASSWORD, UNIFI_HOST, UNIFI_SITES, PORT, VERIFYSSL, VERSION global UNIFI_USERNAME, UNIFI_PASSWORD, UNIFI_HOST, UNIFI_SITES, PORT, VERIFYSSL, VERSION
# empty file parser = argparse.ArgumentParser(description='Import devices from a UNIFI controller')
unifi_logger.debug('Purging old values')
with open(last_run, 'w') as last_run_logfile:
last_run_logfile.write("")
parser = argparse.ArgumentParser(description='Import devices from an UNIFI controller')
parser.add_argument('username', action="store", help="Username used to login into the UNIFI controller") parser.add_argument('username', action="store", help="Username used to login into the UNIFI controller")
parser.add_argument('password', action="store", help="Password used to login into the UNIFI controller") parser.add_argument('password', action="store", help="Password used to login into the UNIFI controller")
@@ -67,9 +55,11 @@ def main():
values = parser.parse_args() values = parser.parse_args()
# parse output # parse output
newEntries = [] plugin_objects = Plugin_Objects(RESULT_FILE)
mylog('verbose', [f'[UNFIMP] Check if all login information is available: {values}'])
unifi_logger.debug(f'Check if all login information is available: {values}')
if values.username and values.password and values.host and values.sites: if values.username and values.password and values.host and values.sites:
UNIFI_USERNAME = values.username.split('=')[1] UNIFI_USERNAME = values.username.split('=')[1]
@@ -80,17 +70,16 @@ def main():
VERIFYSSL = values.verifyssl.split('=')[1] VERIFYSSL = values.verifyssl.split('=')[1]
VERSION = values.version.split('=')[1] VERSION = values.version.split('=')[1]
newEntries = get_entries(newEntries) plugin_objects = get_entries(plugin_objects)
unifi_logger.debug(f'Print {len(newEntries)} to monitoring log') plugin_objects.write_result_file()
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 )
unifi_logger.info(f'Scan finished, found {len(newEntries)} devices')
# ----------------------------------------------------------------------------- mylog('verbose', [f'[UNFIMP] Scan finished, found {len(plugin_objects)} devices'])
def get_entries(newEntries):
# .............................................
def get_entries(plugin_objects):
global VERIFYSSL global VERIFYSSL
sites = [] sites = []
@@ -108,13 +97,13 @@ def get_entries(newEntries):
for site in sites: for site in sites:
c = Controller(UNIFI_HOST, UNIFI_USERNAME, UNIFI_PASSWORD, port=PORT, version=VERSION, ssl_verify=VERIFYSSL, site_id=site ) c = Controller(UNIFI_HOST, UNIFI_USERNAME, UNIFI_PASSWORD, port=PORT, version=VERSION, ssl_verify=VERIFYSSL, site_id=site)
unifi_logger.debug('identify Unifi Devices') mylog('verbose', [f'[UNFIMP] Identify Unifi Devices'])
# get all Unifi devices # get all Unifi devices
for ap in c.get_aps(): for ap in c.get_aps():
# print(f'{json.dumps(ap)}') # mylog('verbose', [f'{json.dumps(ap)}'])
deviceType = '' deviceType = ''
if (ap['type'] == 'udm'): if (ap['type'] == 'udm'):
@@ -131,37 +120,35 @@ def get_entries(newEntries):
name = set_name(name, hostName) name = set_name(name, hostName)
tmpPlugObj = plugin_object_class( plugin_objects.add_object(
ap['mac'], primaryId=ap['mac'],
get_unifi_val(ap, 'ip'), secondaryId=get_unifi_val(ap, 'ip'),
name, watched1=name,
'Ubiquiti Networks Inc.', watched2='Ubiquiti Networks Inc.',
deviceType, watched3=deviceType,
ap['state'], watched4=ap['state'],
get_unifi_val(ap, 'connection_network_name') extra=get_unifi_val(ap, 'connection_network_name')
) )
newEntries.append(tmpPlugObj)
unifi_logger.debug(f'Found {len(newEntries)} Unifi Devices') mylog('verbose', [f'[UNFIMP] Found {len(plugin_objects)} Unifi Devices'])
# print(f'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
online_macs = set() online_macs = set()
# get_clients() returns all clients which are currently online. # get_clients() returns all clients which are currently online.
for cl in c.get_clients(): for cl in c.get_clients():
# print(f'{json.dumps(cl)}') # mylog('verbose', [f'{json.dumps(cl)}'])
online_macs.add(cl['mac']) online_macs.add(cl['mac'])
unifi_logger.debug(f'Found {len(online_macs)} Online Clients')
# print(f'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') mylog('verbose', [f'[UNFIMP] Found {len(plugin_objects)} Online Devices'])
# get_users() returns all clients known by the controller # get_users() returns all clients known by the controller
for user in c.get_users(): for user in c.get_users():
# print(f'{json.dumps(user)}') mylog('verbose', [f'{json.dumps(user)}'])
name = get_unifi_val(user, 'name') name = get_unifi_val(user, 'name')
hostName = get_unifi_val(user, 'hostname') hostName = get_unifi_val(user, 'hostname')
@@ -172,21 +159,25 @@ def get_entries(newEntries):
if status == 1: if status == 1:
tmpPlugObj = plugin_object_class( ipTmp = get_unifi_val(user, 'last_ip')
user['mac'],
get_unifi_val(user, 'last_ip'), if ipTmp == 'null':
name, ipTmp = get_unifi_val(user, 'fixed_ip')
get_unifi_val(user, 'oui'),
'Other', plugin_objects.add_object(
status, primaryId=user['mac'],
get_unifi_val(user, 'last_connection_network_name') secondaryId=ipTmp,
watched1=name,
watched2=get_unifi_val(user, 'oui'),
watched3='Other',
watched4=status,
extra=get_unifi_val(user, 'last_connection_network_name')
) )
newEntries.append(tmpPlugObj)
unifi_logger.debug(f'Found {len(newEntries)} Clients overall') mylog('verbose', [f'[UNFIMP] Found {len(plugin_objects)} Clients overall'])
return newEntries
return plugin_objects
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
def get_unifi_val(obj, key): def get_unifi_val(obj, key):
@@ -214,60 +205,8 @@ def set_name(name: str, hostName: str) -> str:
else: else:
return 'null' return 'null'
# -------------------------------------------------------------------
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
# -----------------------------------------------------------------------------
def service_monitoring_log(primaryId, secondaryId, created, watched1, watched2 = 'null', watched3 = 'null', watched4 = 'null', extra ='null', foreignKey ='null'):
if watched1 == '':
watched1 = 'null'
if watched2 == '':
watched2 = 'null'
if watched3 == '':
watched3 = 'null'
if watched4 == '':
watched4 = 'null'
if extra == '':
extra = 'null'
if foreignKey == '':
foreignKey = 'null'
unifi_logger.debug(f'Adding entry to monitoring log:\n{primaryId}, {secondaryId}, {created}, {watched1}, {watched2}, {watched3}, {watched4}, {extra}')
with open(last_run, 'a') as last_run_logfile:
last_run_logfile.write("{}|{}|{}|{}|{}|{}|{}|{}|{}\n".format(
primaryId,
secondaryId,
created,
watched1,
watched2,
watched3,
watched4,
extra,
foreignKey
)
)
#=============================================================================== #===============================================================================
# BEGIN # BEGIN
#=============================================================================== #===============================================================================
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -98,7 +98,7 @@ function processColumnValue(dbColumnDef, value, index, type) {
value = `<span class="form-group"> value = `<span class="form-group">
<div class="input-group"> <div class="input-group">
<input class="form-control" type="text" value="${value}" id="${id}" data-my-column="${dbColumnDef.column}" data-my-index="${index}" name="${dbColumnDef.column}"> <input class="form-control" type="text" value="${value}" id="${id}" data-my-column="${dbColumnDef.column}" data-my-index="${index}" name="${dbColumnDef.column}">
<span class="input-group-addon"><i class="fa fa-save pointer" onclick="saveData('${id}');"></i></span> <span class="input-group-addon"><i class="fa fa-save pointer" onclick="genericSaveData('${id}');"></i></span>
</div> </div>
<span>`; <span>`;
break; break;
@@ -106,6 +106,7 @@ function processColumnValue(dbColumnDef, value, index, type) {
value = `<span><a href="${value}" target="_blank">${value}</a><span>`; value = `<span><a href="${value}" target="_blank">${value}</a><span>`;
break; break;
case 'url_http_https': case 'url_http_https':
value = `<span> value = `<span>
<a href="http://${value}" target="_blank"> <a href="http://${value}" target="_blank">
<i class="fa fa-lock-open "></i> <i class="fa fa-lock-open "></i>
@@ -143,14 +144,16 @@ function processColumnValue(dbColumnDef, value, index, type) {
}); });
break; break;
case 'regex': case 'regex':
for (const option of dbColumnDef.options) { for (const option of dbColumnDef.options) {
if (option.type === type) { if (option.type === type) {
console.log(value)
const regexPattern = new RegExp(option.param); const regexPattern = new RegExp(option.param);
const match = value.match(regexPattern); const match = value.match(regexPattern);
if (match) { if (match) {
// Return the first match // Return the first match
value = match[0]; value = match[0];
console.log(value)
} }
} }
} }
@@ -169,11 +172,15 @@ function processColumnValue(dbColumnDef, value, index, type) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Update the corresponding DB column and entry // Update the corresponding DB column and entry
function saveData (id) { function genericSaveData (id) {
columnName = $(`#${id}`).attr('data-my-column') columnName = $(`#${id}`).attr('data-my-column')
index = $(`#${id}`).attr('data-my-index') index = $(`#${id}`).attr('data-my-index')
columnValue = $(`#${id}`).val() columnValue = $(`#${id}`).val()
console.log(columnName)
console.log(index)
console.log(columnValue)
$.get(`php/server/dbHelper.php?action=update&dbtable=Plugins_Objects&columnName=Index&id=${index}&columns=UserData&values=${columnValue}`, function(data) { $.get(`php/server/dbHelper.php?action=update&dbtable=Plugins_Objects&columnName=Index&id=${index}&columns=UserData&values=${columnValue}`, function(data) {
// var result = JSON.parse(data); // var result = JSON.parse(data);