#!/usr/bin/env python3 # Tested with OS6860E-P24 8.10.93.R03 GA. Benjamin Domroese in 2025 ### Known Restrictions: ### # - The script should not be started, if a device is already learned in # "unp auth-srv-down" profile. Otherwise it will be learned with the "unp # auth-srv-down" profile assigned to it. # # - The script wont work properly, if one on the same MAC is authenticating # itself with different VLAN tags. In that case the entry in the "DisasterON" # file will be overwritten with the last entry in # "show unp user authentication-type 802.1x|mac". # # - The script will not overwrite existing entries (same MAC and VLAN assignment). # If there is a change of i.e. UNP names or change of UNP assignent of MAC Addresses, # then the file "dict_unp_user" should be deleted. It will be automatically # recreated with updated information. # ######################################################################################## import subprocess import re import json import os #Get only users which are using authentication #(classification users already have their needed unp rules) cmd1 = ["show","unp","user","authentication-type","mac"] cmd2 = ["show","unp","user","authentication-type","802.1x"] ps1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE) ps2 = subprocess.Popen(cmd2, stdout=subprocess.PIPE) output1 = ps1.communicate()[0] output2 = ps2.communicate()[0] #RegEx to filter port entries in command "show unp user" r1 = re.compile(r"\d+/\d+") #Convert bytewise object to string in order to be readably for RegEx converted_output1 = output1.decode("utf-8") converted_output2 = output2.decode("utf-8") file_path = "/flash/dict_unp_user" #Check if dictionary already exists, if not create it new if os.path.exists(file_path): with open(file_path, 'r') as file: UNPUSERTable = json.load(file) else: UNPUSERTable = [] # Add entries from "show unp user authentication-type mac|802.1x" to the dict def process_output(output, pattern, table): duplicate = False #Bool to break outer for loop to prevent duplicate entries for line in output.splitlines(): if re.match(pattern, line): parts = line.split() # Check if MAC and VLAN already exists in UNPUSERTable for i in range(len(UNPUSERTable)): if parts[2] in UNPUSERTable[i]["MacAddress"] and \ parts[4] in UNPUSERTable[i]["Vlan"]: duplicate = True if duplicate == False: table.append({ 'Port': parts[0], 'Username': parts[1], 'MacAddress': parts[2], 'IP': parts[3], 'Vlan': parts[4], 'Profile': parts[5], 'Type': parts[6], 'Status': parts[7] }) duplicate = False # Process both outputs process_output(converted_output1, r1, UNPUSERTable) process_output(converted_output2, r1, UNPUSERTable) # Write the list to the file with open(file_path, 'w') as file: json.dump(UNPUSERTable, file, indent=4) # Write the DisasterON config to file file_path_disasterON = "/flash/disasterON" with open(file_path_disasterON, 'w') as file: file.write("unp port-template AuthDisaster\n") for i in range(len(UNPUSERTable)): file.write("unp classification mac-address {mac} profile1 {unp}\n".format \ (mac = UNPUSERTable[i]['MacAddress'], unp = UNPUSERTable[i]['Profile'])) for i in range(len(UNPUSERTable)): file.write("unp port {port} port-template AuthDisaster\n".format \ (port = UNPUSERTable[i]['Port'])) for i in range(len(UNPUSERTable)): file.write("unp user flush port {port}\n". \ format(port = UNPUSERTable[i]['Port'])) # Write the DisasterOFF config to file file_path_disasterOFF = "/flash/disasterOFF" with open(file_path_disasterOFF, 'w') as file: file.write("TBD. The content of the vcboot.cfg (the UNP part) from the \ running-directory could simply be re-applied.")