diff --git a/front/plugins/omada_sdn_imp/config.json b/front/plugins/omada_sdn_imp/config.json index 8bc11949..76b1a95e 100755 --- a/front/plugins/omada_sdn_imp/config.json +++ b/front/plugins/omada_sdn_imp/config.json @@ -2,7 +2,7 @@ "code_name": "omada_sdn_imp", "unique_prefix": "OMDSDN", "plugin_type": "device_scanner", - "execution_order" : "Layer_1", + "execution_order" : "Layer_0", "enabled": true, "data_source": "script", "mapped_to_table": "CurrentScan", diff --git a/front/plugins/omada_sdn_imp/omada_sdn.py b/front/plugins/omada_sdn_imp/omada_sdn.py index 2e521966..365f5633 100755 --- a/front/plugins/omada_sdn_imp/omada_sdn.py +++ b/front/plugins/omada_sdn_imp/omada_sdn.py @@ -1,13 +1,11 @@ #!/usr/bin/env python __author__ = "ffsb" -__version__ = "0.1" +__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... # 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 -# how to rebuild and re-run... -# sudo docker-compose --env-file ../.env.omada.ffsb42 -f ../docker-compose.yml.ffsb42 up - # # sample code to update unbound on opnsense - for reference... @@ -48,15 +46,14 @@ pluginName = 'OMDSDN' # sample target output: # 0)MAC, 1)IP, 2)Name, 3)switch/AP, 4)port/SSID, 5)TYPE # "['9C-04-A0-82-67-45', '192.168.0.217', 'foo', '40-AE-30-A5-A7-50, '17', 'Switch']" - - +# constants: MAC = 0 IP = 1 NAME = 2 SWITCH_AP = 3 PORT_SSID = 4 TYPE = 5 - +OMDLOGLEVEL='debug' # # translate MAC address from standard ieee model to ietf draft # AA-BB-CC-DD-EE-FF to aa:bb:cc:dd:ee:ff @@ -79,7 +76,7 @@ def get_mac_from_IP(target_IP): else: return None except Exception as e: - mylog('verbose', [f'[{pluginName}] get_mac_from_IP ERROR:{e}']) + mylog('minimal', [f'[{pluginName}] get_mac_from_IP ERROR:{e}']) return None @@ -93,14 +90,18 @@ def callomada(myargs): mylog('verbose', [f'[{pluginName}] callomada:{arguments}']) from tplink_omada_client.cli import main as omada from contextlib import redirect_stdout - try: - mf = io.StringIO() - with redirect_stdout(mf): - bar = omada(myargs) - omada_output = mf.getvalue() - except Exception as e: - mylog('verbose', [f'[{pluginName}] ERROR WHILE CALLING callomada:{arguments}\n {mf}']) - omada_output= '' + 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) # @@ -125,13 +126,13 @@ def find_default_gateway_ip (): """ def find_port_of_uplink_switch(switch_mac, uplink_mac): - mylog('verbose', [f'[{pluginName}] find_port uplink="{uplink_mac}" on switch="{switch_mac}"']) + mylog(OMDLOGLEVEL, [f'[{pluginName}] find_port uplink="{uplink_mac}" on switch="{switch_mac}"']) myport = [] switchdump = callomada(['-t','myomada','switch','-d',switch_mac]) port_pattern = r"(?:{[^}]*\"port\"\: )([0-9]+)(?=[^}]*"+re.escape(uplink_mac)+r")" myport = re.findall(port_pattern, switchdump,re.DOTALL) # print("myswitch=",mymac, "- link_switch=", mylink, "myport=", myport) - mylog('verbose', [f'[{pluginName}] finding port="{myport}" of uplink switch="{uplink_mac}" on switch="{switch_mac}"']) + mylog(OMDLOGLEVEL, [f'[{pluginName}] finding port="{myport}" of uplink switch="{uplink_mac}" on switch="{switch_mac}"']) try: myport2=myport[0] except IndexError: @@ -142,8 +143,8 @@ def find_port_of_uplink_switch(switch_mac, uplink_mac): def add_uplink (uplink_mac, switch_mac, device_data_bymac, sadevices_linksbymac,port_byswitchmac_byclientmac): - mylog('verbose', [f'[{pluginName}] trying to add uplink="{uplink_mac}" to switch="{switch_mac}"']) - mylog('verbose', [f'[{pluginName}] before adding:"{device_data_bymac[switch_mac]}"']) + 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': @@ -152,7 +153,7 @@ def add_uplink (uplink_mac, switch_mac, device_data_bymac, sadevices_linksbymac, else: port_to_uplink=device_data_bymac[uplink_mac][PORT_SSID] device_data_bymac[switch_mac][PORT_SSID] = port_to_uplink - mylog('verbose', [f'[{pluginName}] after adding:"{device_data_bymac[switch_mac]}"']) + 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) @@ -192,8 +193,8 @@ def main(): #some_setting = get_setting_value('OMDSDN_url') - #mylog('verbose', [f'[{pluginName}] some_setting value {some_setting}']) - mylog('verbose', [f'[{pluginName}] ffsb']) + #mylog(OMDLOGLEVEL, [f'[{pluginName}] some_setting value {some_setting}']) + mylog(OMDLOGLEVEL, [f'[{pluginName}] ffsb']) @@ -215,13 +216,13 @@ def main(): # figure a way to run my udpate script delayed for device in device_data: - mylog('verbose', [f'[{pluginName}] main parsing device: "{device}"']) + mylog(OMDLOGLEVEL, [f'[{pluginName}] main parsing device: "{device}"']) if device[PORT_SSID].isdigit(): myport = device[PORT_SSID] - myssid = '' + myssid = 'null' else: myssid = device[PORT_SSID] - myport = '' + myport = 'null' if device[SWITCH_AP] != 'Internet': ParentNetworkNode = ieee2ietf_mac_formater(device[SWITCH_AP]) else: @@ -236,13 +237,13 @@ def main(): 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: "{len(device_data)}"']) + mylog(OMDLOGLEVEL, [f'[{pluginName}] New entries: "{len(device_data)}"']) # log result plugin_objects.write_result_file() - #mylog('verbose', [f'[{pluginName}] TEST name from MAC: {device_handler.getValueWithMac('dev_Name','00:e2:59:00:a0:8e')}']) - #mylog('verbose', [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'))}']) + #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'))}']) return 0 @@ -263,7 +264,13 @@ def get_device_data(omada_clients_output,switches_and_aps,device_handler): # sample target output: # 0 MAC, 1 IP, 2 Name, 3 switch/AP, 4 port/SSID, 5 TYPE #17:27:10 [] token: "['9C-04-A0-82-67-45', '192.168.0.217', '9C-04-A0-82-67-45', '17', '40-AE-30-A5-A7-50, 'Switch']" - + #constants + dMAC = 0 + dIP = 1 + dTYPE = 2 + dSTATUS = 3 + dNAME = 4 + dMODEL = 5 sadevices_macbyname = {} sadevices_macbymac = {} sadevices_linksbymac = {} @@ -273,23 +280,29 @@ def get_device_data(omada_clients_output,switches_and_aps,device_handler): omada_force_overwrite = get_setting_value('OMDSDN_force_overwrite') sadevices = switches_and_aps.splitlines() - mylog('verbose', [f'[{pluginName}] switches_and_aps rows: "{len(sadevices)}"']) + mylog(OMDLOGLEVEL, [f'[{pluginName}] switches_and_aps rows: "{len(sadevices)}"']) for sadevice in sadevices: sadevice_data = sadevice.split() - thisswitch = sadevice_data[0] + thisswitch = sadevice_data[dMAC] sadevices_macbyname[sadevice_data[4]] = thisswitch - if sadevice_data[2] == 'ap': + if sadevice_data[dTYPE] == 'ap': sadevice_type = 'AP' sadevice_details = callomada(['access-point', thisswitch]) - sadevice_links = extract_mac_addresses(sadevice_details) + if sadevice_details == '': + sadevice_links = [thisswitch] + else: + sadevice_links = extract_mac_addresses(sadevice_details) sadevices_linksbymac[thisswitch] = sadevice_links[1:] - mylog('verbose', [f'[{pluginName}]adding switch details: "{sadevice_details}"']) - mylog('verbose', [f'[{pluginName}]links are: "{sadevice_links}"']) - mylog('verbose', [f'[{pluginName}]linksbymac are: "{sadevices_linksbymac[thisswitch]}"']) - elif sadevice_data[2] == 'switch': + 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_links=extract_mac_addresses(sadevice_details) + 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]) @@ -298,26 +311,25 @@ def get_device_data(omada_clients_output,switches_and_aps,device_handler): port_pattern = r"(?:{[^}]*\"port\"\: )([0-9]+)(?=[^}]*"+re.escape(link)+r")" myport = re.findall(port_pattern, switchdump,re.DOTALL) port_byswitchmac_byclientmac[thisswitch][link] = myport[0] - mylog('verbose', [f'[{pluginName}]links are: "{sadevice_links}"']) - mylog('verbose', [f'[{pluginName}]linksbymac are: "{sadevices_linksbymac[thisswitch]}"']) - mylog('verbose', [f'[{pluginName}]ports of each links are: "{port_byswitchmac_byclientmac[thisswitch]}"']) - mylog('verbose', [f'[{pluginName}]adding switch details: "{sadevice_details}"']) - + 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[1], sadevice_data[4], 'null', 'null',sadevice_type] - device_data_mac_byip[sadevice_data[1]] = thisswitch + 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('verbose', [f'[{pluginName}]adding switch: "{foo}"']) + mylog(OMDLOGLEVEL, [f'[{pluginName}]adding switch: "{foo}"']) # sadevices_macbymac[thisswitch] = thisswitch - mylog('verbose', [f'[{pluginName}] switch_macbyname: "{sadevices_macbyname}"']) - mylog('verbose', [f'[{pluginName}] switches: "{device_data_bymac}"']) + 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 @@ -334,52 +346,65 @@ def get_device_data(omada_clients_output,switches_and_aps,device_handler): #17:27:10 [] token: "['50-02-91-29-E7-53', '192.168.0.153', 'frontyard_ESP_29E753', 'pantry12', '(48)']" #17:27:10 [] token: "['00-E2-59-00-A0-8E', '192.168.0.1', 'bastion', 'office24', '(23)']" #17:27:10 [] token: "['60-DD-8E-CA-A4-B3', '192.168.0.226', 'brick', 'froggies3', '(ompapaoffice)']" + cMAC = 0 + cIP = 1 + cNAME = 2 + cSWITCH_AP = 3 + cPORT_SSID = 4 + # sample target output: # 0 MAC, 1 IP, 2 Name, 3 MAC of switch/AP, 4 port/SSID, 5 TYPE #17:27:10 [] token: "['9C-04-A0-82-67-45', '192.168.0.217', 'brick', 'ompapaoffice','froggies2', , 'Switch']" odevices = omada_clients_output.splitlines() - mylog('verbose', [f'[{pluginName}] omada_clients_outputs rows: "{len(odevices)}"']) + 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[0] - odevice_data_reordered[IP]=odevice_data[1] - naxname = device_handler.getValueWithMac('dev_Name',ieee2ietf_mac_formater(odevice_data[MAC])) - if naxname == None or ietf2ieee_mac_formater(naxname) == odevice_data[MAC] or '('in naxname: + 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. + # + if real_naxname == None or ietf2ieee_mac_formater(real_naxname) == odevice_data[cMAC] or '('in real_naxname or real_naxname == odevice_data[cNAME] or real_naxname == 'null': naxname = None - mylog('verbose', [f'[{pluginName}] TEST name from MAC: {naxname}']) - if odevice_data[MAC] == odevice_data[NAME]: + else: + naxname = real_naxname + mylog('debug', [f'[{pluginName}] TEST name from MAC: {naxname}']) + if odevice_data[cMAC] == odevice_data[cNAME]: if naxname != None: - callomada(['set-client-name', odevice_data[MAC], naxname]) + callomada(['set-client-name', odevice_data[cMAC], naxname]) odevice_data_reordered[NAME] = naxname else: - odevice_data_reordered[NAME] = 'null' + odevice_data_reordered[NAME] = real_naxname else: if omada_force_overwrite and naxname != None: - callomada(['set-client-name', odevice_data[MAC], naxname]) - odevice_data_reordered[NAME] = odevice_data[2] - mightbeport = odevice_data[4].lstrip('(') + callomada(['set-client-name', odevice_data[cMAC], naxname]) + odevice_data_reordered[NAME] = odevice_data[cNAME] + mightbeport = odevice_data[cPORT_SSID].lstrip('(') mightbeport = mightbeport.rstrip(')') if mightbeport.isdigit(): - odevice_data_reordered[SWITCH_AP] = odevice_data[3] + 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[3] + 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('verbose', [f'[{pluginName}] could not find the mac adddress for: "{odevice_data_reordered[SWITCH_AP]}"']) + mylog(OMDLOGLEVEL, [f'[{pluginName}] could not find the mac adddress for: "{odevice_data_reordered[SWITCH_AP]}"']) # adding the type - odevice_data_reordered[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('verbose', [f'[{pluginName}] tokens: "{odevice_data}"']) - mylog('verbose', [f'[{pluginName}] tokens_reordered: "{odevice_data_reordered}"']) + 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... diff --git a/front/plugins/omada_sdn_imp/testre.py b/front/plugins/omada_sdn_imp/testre.py index c04e7655..bf5648cf 100644 --- a/front/plugins/omada_sdn_imp/testre.py +++ b/front/plugins/omada_sdn_imp/testre.py @@ -1,5 +1,38 @@ import re +"""" +how to rebuild and re-run... +savefolder=~/naxdev/NetAlertX.v6 +cd ~/naxdev +mv NetAlertX $savefolder +gh repo clone FlyingToto/NetAlertX +cd NetAlertX +ln -s ../docker-compose.yml.ffsb42 . +ln -s ../.env.omada.ffsb42 . +cd front/plugins/omada_sdn_imp/ +cp -p $savefoder/front/plugins/omada_sdn_imp/omada_sdn.py . +cp -p $savefoder/front/plugins/omada_sdn_imp/README.md . +cp -p $savefoder/front/plugins/omada_sdn_imp/omada_account_sample.png . +cp -p $savefoder/front/plugins/omada_sdn_imp/testre.py . +cp -p $savefoder/front/plugins/omada_sdn_imp/config.json config.json.v6 +cd ~/naxdev/NetAlertX +sudo docker-compose --env-file .env.omada.ffsb42 -f ./docker-compose.yml.ffsb42 up + +to gather data for Boris: +today=$(date +%Y_%m_%d__%H_%M) +mkdir /drives/c/temp/4boris/$today +cd /drives/c/temp/4boris/$today +scp hal:~/naxdev/logs/app.log . +scp hal:~/naxdev/NetAlertX/front/plugins/omada_sdn_imp/* . +gzip -c app.log > app.$today.log.gz + + + +""" + + + + 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_pattern = r'([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})' @@ -77,7 +110,7 @@ def extract_uplinks_mac_and_ports(tplink_device_dump): return(0) - +''' with open('/tmp/switch.bigroom.dump.json', 'r') as file: foo3 = file_content = file.read() print("bigroom", end="") @@ -86,7 +119,7 @@ with open('/tmp/switch.office.dump.json', 'r') as file: foo4 = file_content = file.read() print("office", end="") extract_uplinks_mac_and_ports(foo4) - +''' import netifaces gw = netifaces.gateways() @@ -98,3 +131,12 @@ d = {'a': ['0', 'Arthur'], 'b': ['foo', 'Belling']} print(d.items()) print(d.keys()) print(d.values()) + + +foo = 2 +#while foo > 0: +# foo = 'toto' + +print("foo is ",foo) + +