Benutzer-Werkzeuge

Webseiten-Werkzeuge


omnivista-scripting

OmniVista 2500 - CLI-Scripting mit JavaScript

Der folgende Tech-Tipp soll die Möglichkeiten des Scripting Moduls des OmniVista2500 aufzeigen. Neben der Nutzung der bekannten AOS CLI Syntax, besteht die Möglichkeit Kommandos in JavaScript einzubinden, um so beispielsweise bedingte Konfigurationen (z.B. Learned Port Security nur auf mobilen Ports) oder komplexe Prüfungen der Konfiguration durchzuführen.

Das Modul kann zur Ausführung der Scripte neben den eingebauten System-Variablen (z.B. GeräteTyp, IP-Adresse, MAC-Adresse) auch Benutzer-Variablen zur Ausführung der Scripte heranziehen. Details zu den Möglichkeiten werden im OmniVista direkt unter dem Menüpunkt ?Help im CLI-Scripting Modul angeboten.

Folgend werden einige Beispiel Scripte kurz erklärt, die individuell angepasst werden können und den Konfigurationsaufwand in einigen Fällen bereits erheblich reduzieren können.

:!: Hinweis: Die folgende Scripte wurden mit OmniVista 2500 4.2.1R01 Build 95 auf AOS 6.x Geräten (6450 und 6400) genutzt. Andere Geräte sowie AOS Versionen unterscheiden sich ggf. in der Syntax der Kommandos und in deren Ausgabe. Die Scripte müssen daher immer genau geprüft werden, bevor diese für einen flächendeckenden Rollout verwendet werden können.:!:

Überprüfung der installierten FPGA Version

Das folgende Script führt ein Kommando „show ni“ auf den Geräten aus, und sucht in dessen Ausgabe nach dem Vorkommen eines regulären Ausdrucks. In diesem Fall wird die FPGA Version 11 gesucht. Je nach Resultat, wird unter Administrator→Audit→Configuration→clisripting das Ergebnis entweder als INFORMATION oder ERROR angezeigt.

<js>
/*@@Check if correct FPGA is installed. Use on your own risk! Benjamin Domroese, Januar 2018@@ */
cli.sendCmd("show ni");
var response = cli.lastResponse();
var pattern = /FPGA\s-\sPhysical\s\d:\s+0011/g;/*REGEX Pattern you hope to find. In this case FPGA 11*/
if (pattern.test(response)==true)
{
cli.trace("Everything OK here - FPGA 11 installed on " + "$IP_ADDRESS");/*Positiv Message in Audit if Pattern found*/
}/*if*/
else
{
   cli.errorLog("FPGA need to be updated on " + "$IP_ADDRESS");/*Negative Message in Audit if not found*/
}/*else*/
</js>

Bedingte Konfiguration, z.B. Änderungen nur an mobilen Ports

Das nächste Beispiel beinhaltet eine bedingte Konfiguration. Hier wird eine Liste der mobilen Ports angelegt, und diese für ein bestimmtes Kommando herangezogen. In diesem Fall „default vlan restore disable“. Die Liste wird hier anhand eines regulären Ausdrucks und des Kommandos „show vlan port mobile“ erzeugt. Anschließend wird mithilfe einer for-Schleife, für jedes Element in der Liste (jeder mobile Port) ein Kommando ausgeführt.

<js>
/*@@Check if there are mobile Ports with default vlan restore ENABLED. If yes, disable it. Use on your own risk! Benjamin Domroese, Januar 2018@@ */

cli.sendCmd("show vlan port mobile");
var response = cli.lastResponse();
var pattern = /\d+\/\d+(?=\s+on\s+\d{1,4}\s+\S{1,10}\s+\w{2,3}\s+on)/g;/*Create REGEX that only stores the port i.e 1/3 */

if (pattern.test(response)==false)
{
cli.trace("Everything OK here");
}/*if*/
else
{
    var ListOfMobilePorts = response.match(pattern); /*Create the Array with the Ports that need to be changed*/
    for (i=0;i<ListOfMobilePorts.length && ListOfMobilePorts != null;i++)
    {
   cli.sendCmd("vlan port " + ListOfMobilePorts[i] + " default vlan restore disable");/*send the Cmd for every entry in the Array (every port matched by the REGEX)*/
   cli.errorLog(ListOfMobilePorts[i] + " has been changed");
    }/*for*/
}/*else*/

</js>

Das Ergebnis kann sowohl im Audit Log, als auch im CLI Scripting Modul unter Configuration→CLI Scripting→Logs direkt eingesehen werden.

Überprüfung der ausgerollten Konfigurationen

Folgender Code kann genutzt werden, um das Vorhandensein diverser Konfigurationen zu prüfen. Dafür werden 2 Funktionen definiert, die folgende Parameter erhalten:

  • Einen regulären Ausdruck nach dem gesucht wird.
  • Ein Kommando in dessen Ausgabe der Ausdruck erwartet wird.
  • Ein Namen um das Audit Log File einfacher interpretieren zu können.

Je nachdem ob es gewünscht ist den Ausdruck zu finden, oder nicht zu finden - stehen 2 Funktionen zur Verfügung die das Ergebnis je nach positiver oder negativer Sichtweise interpretieren. Nach der Funktionsdeklaration kann nach beliebig vielen Ergebnissen geprüft werden.

<js>
/*@@ Checks if expected configuration is found. The Log Message could be either positiv or negativ. Depending if you want to find the REGEX Pattern or not. Use on your own risk! Benjamin Domroese, Januar 2018@@ */
/*===Function declaration===*/
function ConfigCheckPositiv(repattern,command,name)/*===Return OK if Pattern is matched===*/
{
cli.sendCmd(command);
var	response= cli.lastResponse();
if (repattern.test(response)==true)
{
   cli.trace(name + " " + "$IP_ADDRESS" + " is OK");/*===Set INFO in AuditLog===*/
}/*if*/
else
{
    cli.errorLog(name + " " + "$IP_ADDRESS" + "  is not ok!");/*===Set ERROR in AuditLog===*/
}/*else*/
}/*Function*/

function ConfigCheckNegative(repattern,command,name)/*===Return NOK if Pattern is matched===*/
{
cli.sendCmd(command);
var	response= cli.lastResponse();
if (repattern.test(response)==false)
{
   cli.trace(name + " " + "$IP_ADDRESS" + " is OK");
}/*if*/
else
{
    cli.errorLog(name + " " + "$IP_ADDRESS" + "  is not ok!");
}/*else*/
}/*Function*/

/*Start of Script*/

var pattern_1 = /\d+\/\d+(?=\s+on\s+\d{1,4}\s+\S{1,10}\s+\w{2,3}\s+on)/g;/*RegEx that checks if Default VLAN Restore is enabled*/
ConfigCheckNegative(pattern_1,"show vlan port mobile","Default VLAN Restore");

var pattern_2 = /\d+\/\d+(?=\s+\w{2,3}\s+(?!999)\d{1,4}\s+on-8021x)/g;/*RegEx that checks if there are mobile ports NOT with default VLAN 999*/
ConfigCheckNegative(pattern_2,"show vlan port mobile","VLAN 999 port default on MobilePorts");

var pattern_3 = /ip\shelper\sdhcp\-snooping\senable/g;/*RegEx that checks if DHCP Snooping is enabled*/
ConfigCheckPositiv(pattern_3,"show configuration snapshot ip-helper","DHCP-Snooping");

var pattern_4 = /Administrative\sState:\s+disabled/g;/*RegEx that checks if VLAN 999 for Trash is disabled*/
ConfigCheckPositiv(pattern_4,"show vlan 999","VLAN 999 disabled");

var pattern_5 = /policy\sport\sgroup\sUserPorts\s+\d+\/\d+/g;/*RegEx that checks if there is at least one port configured for UserPortSecurity*/
ConfigCheckPositiv(pattern_5,"show configuration snapshot qos","UserPortsSecurity");

var pattern_6 = /unp\-secu/g;/*RegEx that checks if a particular UNP exists*/
ConfigCheckPositiv(pattern_6,"show aaa user-network-profile","UNP-Secu");

var pattern_7 = /supp\-polling\sretry\s(?!8)\d+/g;/*RegEx that checks if the desired supp-poll retry is correct*/
ConfigCheckNegative(pattern_7,"show configuration snapshot aaa","8021x Supp-Poll retry");

var pattern_8 = /\d+\/\d+\s+ENABLED\s+1000/g;/*RegEx that checks if LPS is active */
ConfigCheckPositiv(pattern_8,"show port-security brief","LearnedPortSecurity");

var pattern_9 = /\d+\/\d+\s+enabled/g;/*RegEx that checks if LoopBackDetection is enabled at least on one port*/
ConfigCheckPositiv(pattern_9,"show loopback-detection port","LoopBackDetection");
</js>

Das Ergebnis sieht dann im Idealfall wie folgt aus:

Überprüfung von gleichartiger 802.1x Konfiguration

Das folgende Script überprüft, ob die AAA Konfiguration auf allen Ports gleich ist oder sich die Konfiguration auf einzelnen Ports unterscheidet.

Anhand eines Regulären Ausdrucks wird hier mithilfe des Kommandos „show vlan port mobile“ eine Liste (Array) mit allen 802.1x Ports erstellt. Anschließend wird mit „show configuration snapshot aaa“ die komplette AAA Konfiguration eingelesen und mit einem regulären Ausdruck so modifiziert, dass diese zwischen den Ports vergleichbar ist.

Aus:

 
802.1x 1/20 supp-polling retry 10 

wird

 
802.1x      supp-polling retry 10

Diese Konfiguration wird nun mit dem jeweilig nächsten Port verglichen und auf Differenzen untersucht (z.B. Port 1/2 mit Port 1/3). Dieser Vorgang wird für alle 802.1x Ports ausgeführt, die in der Liste „ListOf8021xPorts“ aufgeführt sind. Sollten Unterschiede auftreten, so sind diese anschließend im Audit Log (siehe Screenshot) zu finden.

Anbei der JavaScript Code für diese Funktion.

<js>
/*@@Check if all 8021x Config is identically. Created by Benjamin Domroese, Januar 2018@@*/
cli.sendCmd("show vlan port mobile");
cli.cliSleep("2000"); /*Give the command 2 seconds time, before the next is executed*/
var response = cli.lastResponse();
var pattern = new RegExp("\\d+\\/\\d+(?=\\s+on\\s+\\d{1,4}\\s+on\\-8021x)","gm");/*Create REGEX that only stores the port enabled for 8021x */
var noerrorfound = true;
var okmsg = false;

if (pattern.test(response)==false)
{
cli.trace("No 8021x Ports found on: " + "$IP_ADDRESS");
okmsg = true;
}/*if*/
else
{
    var ListOf8021xPorts = response.match(pattern);/*Create an Array out of all 8021x Ports seen with "show vlan port mobile"*/
	cli.sendCmd("show configuration snapshot aaa");
	var aaa_config = cli.lastResponse();
	
        for (i=0;i<ListOf8021xPorts.length-1 && ListOf8021xPorts != null;i++)
        {
	    var pattern_2 = new RegExp("(?:802.1x\\s+" + ListOf8021xPorts[i] + ").*(\\r\\n|\\r|\\n)","g");/*REGEX Object that capture everything between the Port Number and a new line (just the pure config)*/
	    var first_port = aaa_config.match(pattern_2);
	    var pattern_3 = new RegExp("(?:802.1x\\s+" + ListOf8021xPorts[i+1] + ").*(\\r\\n|\\r|\\n)","g");
	    var second_port = aaa_config.match(pattern_3);

		    for (j=0;j<first_port.length && second_port[j]!= null;j++)
		    {
		    	var first_port_clean = first_port[j].replace(/\d{1,2}\/\d{1,2}/,""); /* Replace Port Number, so that config should be similar*/
				var second_port_clean = second_port[j].replace(/\d{1,2}\/\d{1,2}/,""); 
				
				    if (second_port_clean != first_port_clean)
				    {
				    	cli.errorLog("Warning on " + "$IP_ADDRESS" + "! Port " + ListOf8021xPorts[i] + " is different from " + ListOf8021xPorts[i+1]);
						cli.errorLog("Port Config on " + ListOf8021xPorts[i] + " is: " + first_port_clean);
						cli.errorLog("Port Config on " + ListOf8021xPorts[i+1] + " is: " + second_port_clean);
						var noerrorfound = false;						
					}/*if*/
					
		    }/*for*/	
    }/*for*/
}/*else*/
if (noerrorfound==true && okmsg==false)
{
	cli.trace("Everything ok on " + "$IP_ADDRESS" + "! All Ports are configured identically");
}/*if*/

</js>

Anbei ein Screenshot der Ausgabe, die Hinweise auf unterschiedliche Konfigurationen bietet.

UNP´s anhand von Vorlagen erstellen

Der nächste Code erstellt ein UNP anhand einer Vorlage (eines vorhandenen UNP). Sofern das UNP bereits existiert, oder die „Vorlage“ fehlt, wird das Script beendet und eine ERROR Message im Audit kreiert.

<js>
/*@@Script for creating a UNP with usage of an existing "template". Use on your own risk! Benjamin Domroese, Januar 2018@@*/
cli.sendCmd("show aaa user-network-profile ");
var response_1 = cli.lastResponse();
var pattern_unp_embedded = /unp\-embedded/g;/*RegeEx to lookup for the "template"-UNP*/
var pattern_unp_secu = /unp\-secu/g;/*RegEx Pattern to check for the UNP that should be created*/
if (pattern_unp_secu.test(response_1)==true)
{
	cli.trace("UNP Secu already exists");
}/*if*/
else if (pattern_unp_embedded.test(response_1)==true)
{
	var pattern_unp_embedded_vlan = /unp\-embedded\s+(\d{1,4})/g;/*RegEx that only captures the VLAN ID (used for the create command)*/
	var vlan_for_unp_secu = pattern_unp_embedded_vlan.exec(response_1);

	cli.sendCmd("aaa user-network-profile name unp-secu vlan " + vlan_for_unp_secu[1] + " hic disable");
	cli.trace("UNP Secu was created");
}/*else if*/
	
else
{
	cli.errorLog("Profile UNP-Embedded not found for use as template!");
}/*else*/
</js>

Überprüfung ob alle Ports per 802.1x gesichert sind

Das nächste Beispiel benötigt bei der Ausführung die Eingabe von User Variablen. Im „Send Script Wizard“ werden hier unter Punkt 4 „Define User Variables“ abgefragt. Das Script prüft die Anzahl der Verfügbaren Ports des Systems, subtrahiert die erwarteten Non-802.1x Ports (z.B. Uplink Ports) sowie die 802.1x Ports und gibt im Log File an, ob die Anzahl der 802.1x Ports den Erwartungen entspricht.

Die Anzahl der Ports habe ich in diesem Beispiel per „show interfaces status“ berechnet. Dabei werden mithilfe der Funktion „unique“ doppelte Einträge gelöscht (z.B. Hybrid Ports die doppelt angezeigt werden).

Die Anzahl der 802.1x Ports wird erneut mit „show vlan port mobile“ berechnet. Im Audit werden schlussendlich die Ergebnisse angezeigt. Diese beinhalten die Anzahl der Ports des Systems, die erwarteten 802.1x und Uplink Ports sowie (wenn vorhanden) die Anzahl ungeschützter Ports.

<js>
/*@@Script for checking if all Ports are configured as 8021x. Use on your own risk! Benjamin Domroese, Januar 2018@@*/
/*@@Dont forget to enter the number of expected Uplinks as uservariable in the CLI Module. This Script checks for unsecured Ports@@*/

function unique(array)/* In case there are duplicate entries i.e. for hybrid ports */
{
	array.sort();
	for (i=0;i<array.length;i++) 
		if (a[i]==a[i+1])
		{
			a.splice(i,1);
			
		}/*if*/
    return array.length;
}/* function for removing duplicates */

/* Check the number of available Ports on the System */
cli.sendCmd("show interfaces status");
var response_1 = cli.lastResponse();
var pattern_1 = /\d{1,2}\/\d{1,2}/g; /*RegeEx that only stores the Port i.e. 1/7*/
var a = response_1.match(pattern_1);
var nr_of_ports_available = unique(a); /*Create a Array with the Ports. This is created with var "a" passed to the function for cleaning duplicates. It returns the lenght of the array (the number of ports) */  

/* Check the number of 8021x Ports */
cli.sendCmd("show vlan port mobile");
var response_2 = cli.lastResponse();
var pattern_2 = /on-8021x/g;
var b = response_2.match(pattern_2);
if (b != null)/* Check if there is no 8021x */
{
    var nr_of_ports_8021x = b.length;
}/* if */
else
{
    var nr_of_ports_8021x = 0;
}/*else*

/* Check if there are more unsecured Ports than expected and return unsecured Ports to logfile */
if (nr_of_ports_8021x + parseInt("$ExpectedUplinks") == nr_of_ports_available)
{
	cli.trace("Everything Secure on " + "$IP_ADDRESS" + ". Number of available Ports is: " + nr_of_ports_available + " and number of 8021x and Uplink Ports is: " + (nr_of_ports_8021x + parseInt("$ExpectedUplinks")));
}/* if */
else if (nr_of_ports_8021x + parseInt("$ExpectedUplinks") > nr_of_ports_available)
{
	cli.errorLog("Please check UserVariables for expected Uplink! More Ports detected than possible");
}/*else*/
else
{
	var nr_of_ports_without_8021x = nr_of_ports_available - (nr_of_ports_8021x + parseInt("$ExpectedUplinks"));
	cli.errorLog("Warning for " + "$IP_ADDRESS" + "! There are " + nr_of_ports_without_8021x + " Ports without 8021x! Number of available Ports is: " + nr_of_ports_available + " and number of 8021x and Uplink Ports is: " + (nr_of_ports_8021x + parseInt("$ExpectedUplinks")));
}/*else*/
</js>
omnivista-scripting.txt · Zuletzt geändert: 2018/02/01 13:34 von benny-domroese