PyForms dependencies

While I was looking for a GUI programming in python I came across PyForms, the scripting with PyForms seemed easy so I install it using pip.

When I was testing a simple code from PyForms, my Python interpreter told me that no module pysettings was found… So I attempted to install from my pycharm repository, pysettings could not install…

Ok.. So I downloaded Git for Windows, and make a PATH in the environment variable, then do this pip install git+https://github.com/UmSenhorQualquer/pyforms.git and pip install git+https://github.com/UmSenhorQualquer/pysettings.git

So i thought all was settled and attempt to run the script again, python said no module loggingbootstrap...i could not find this module, so i commented the line. Here's the import in pyforms __init__.py:

import logging
#import loggingbootstrap
from pysettings import conf

I commented the second line. So i tried running the script again, it says no module for PyQT5... WTF!... Ok so here are the dependencies to use pyforms:

1. pysettings (because pyforms is using conf from this module)
2. pyqt5
3. numpy
4. matplotlib
5. visvis
6. cv2

Ok installing cv2 needs dependencies... read this blog: Install OpenCV 3 with Python 3 on Windows

Advertisements
Posted in Python, Scripting | Tagged , | Leave a comment

[Powershell] Finding discrepancy between two files

thanks to Stackoverlfow: https://stackoverflow.com/questions/8799847/compare-two-csv-files-and-find-discrepancies

The code snippet is about comparing two CSV files containing firewall object groups and list down the discrepancy. the code snippet can be used to out-file to a text.

[System.Collections.ArrayList]$base = Get-Content "C:\Temp\reference_ip.csv"
[System.Collections.ArrayList]$diff = Get-Content "C:\Temp\difference_ip.csv"
$notmatching = @()

foreach ($ip in $base) {
    if (!$diff.Contains($ip)) {
        $notmatching += $ip
        }
    }

Write-Host "Not Matches : "
foreach ($value in $notmatching) {
    $message += $value + [Environment]::NewLine
    }
Write-Host $message
Posted in Powershell, Scripting | Tagged , | Leave a comment

Powershell script to invoke Tufin Path analysis API

There is an undocumented Tufin API, see the code below:

#Parameters must be declared at the start of the script.
Param(
    [Parameter(Mandatory=$true)][string]$usr,
    #[Parameter(Mandatory=$true)][string]$pwd,
    [Parameter(Mandatory=$true)][ipaddress]$src,
    [Parameter(Mandatory=$true)][ipaddress]$dst,
    [Parameter(Mandatory=$false)][string]$svc = 'any'
    )

#Purpose is to obfuscate the password when user type his/her password.
$securepwd = Read-Host("Password") -AsSecureString
$bstrpwd = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepwd)
#Need to convert the password from secure to plaintext otherwise the encrypted cipher text will locked your account.
$pwd = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstrpwd)

add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

$cred = "${usr}:${pwd}"
$bytes = [System.Text.Encoding]::ASCII.GetBytes($cred)
$base64 = [System.Convert]::ToBase64String($bytes)
$basicAuthValue = "Basic $base64"
$headers = @{ Authorization = $basicAuthValue }
$date = Get-Date

try {
    #Invoke-RestMethod -Uri "https://tufin_Secure_track_ipaddress/securetrack/api/topology/path_image?src=$($src)&dst=$($dst)&service=$($svc)" -Method Get -ContentType 'application/xml' -Headers $headers -OutFile "$env:USERPROFILE\path_image_$($date.ToString('ddMMyy-HHmm')).png"
    Invoke-RestMethod -Uri "https://tufin_Secure_track_ipaddress/securetrack/api/path/calcImage/src/$($src)/dst/$($dst)/svc/ANY?arrow=true&WithPa=false" -Method Get -ContentType 'application/xml' -Headers $headers -OutFile "$env:USERPROFILE\path_image_$($date.ToString('ddMMyy-HHmm')).png"
} catch {
    $Error[0].ErrorDetails.Message
    
    }
Posted in Powershell, Scripting | Tagged , , , | Leave a comment

Update Cisco ASA object group with netmiko

This is a demo of configuring ASA with netmiko, there is a use case when a server is provisioned, the server’s hostname and ip addresses are assigned automatically by Vrealize, and run a python script to update the object-group of the server.

Here’s the code:

from netmiko import ConnectHandler
from getpass import getpass
import logging

usr = input("Username: ")
pwd = getpass()
asav = {  'device_type': 'cisco_asa',
    'ip': '192.168.1.15',
    'username': usr,
    'password': pwd,
    'secret': pwd,
    'port': '22', }

config_set = ['object network member1', 'host 1.1.1.1 ', 'exit', 'object network member2', 'host 2.2.2.2', 'exit', 'object-group network Group1',
           'network-object object member1', 'network-object object member2' ]

logging.basicConfig(level=logging.DEBUG)
with ConnectHandler(**asav) as m:
    m.enable()
    m.config_mode()
    m.send_config_set(config_set, True)
    m.send_command_expect('write memory')
Posted in Python, Scripting | Tagged , , , | Leave a comment

Extending the python script to configure OSPF with ncclient

Previously I have successfully download the configuration from the netconf enabled router, now i have extended support to configure ospf.
This is a simple lab to further extend and get myself familiarize and comfortable with netconf.

During the lab I was careless, I inadvertently left a space on my netconf snippet that breaks my script and it generate an error, I turned on the debug on the router and found that a “<" was missing.

*Sep  2 04:38:08.709: NETCONF: netconf_xml_interpret.86.failure<?xml version="1.0" encoding="UTF-8"?><nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"message-id="urn:uuid:36abc85e-d850-45b5-95d0-fdf5d0a3226f"><nc:edit-config><nc:target><nc:running/></nc:target><config>
             cli-config-data>
                <cmd<cmd>interface Ethernet0/0</cmd>
                <cmd>ip address 10.0.0.2 255.255.255.252</cmd>
                <cmd>no shutdown</cmd>
            </config></nc:edit-config></nc:rpc>
*Sep  2 04:38:08.709: NETCONF: _nssd.87.snd.now<?xml version="1.0" encoding="UTF-8"?><rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><rpc-error><error-type>rpc</error-type><error-tag>unknown-element</error-tag><error-severity>error</error-severity><error-info><bad-element>cmd</bad-element></error-info></rpc-error></rpc-reply>

So on this lab I have put together a simple menu, the feature to download configuration file and added ospf.
Here's the entire code

import sys, time, os.path
from ncclient import manager
from getpass import getpass
from datetime import datetime
import logging


CREATE_INTERFACE_IP = """
        <config>
            <cli-config-data>
                <cmd>interface %s</cmd>
                <cmd>description Configured by ncclient</cmd>
                <cmd>ip address %s %s</cmd>
                <cmd>no shutdown</cmd>
            </cli-config-data>
        </config>
        """

CREATE_OSPF = """
        <config>
            <cli-config-data>
                <cmd>router ospf %i</cmd>
                <cmd>router-id %s</cmd>
                <cmd>passive-interface default</cmd>
                <cmd>no passive-interface %s</cmd>
                <cmd>network %s 0.0.0.0 area 0</cmd>
                <cmd>network %s 0.0.0.0 area 0</cmd>
            </cli-config-data>
        </config>
     """


def create_interface_ip(conn, interface, ip, mask):
    try:
        config_str = CREATE_INTERFACE_IP % (interface, ip, mask)
        conn.edit_config(target='running', config=config_str)
    except Exception:
        print('Exception occurs while creating interface %s' % interface)


def create_ospf(conn, ospf_id, rid, interface, network1, network2):
    try:
        config_str = CREATE_OSPF % (ospf_id, rid, interface, network1, network2)
        conn.edit_config(target='running', config=config_str)
    except  Exception:
        print('Exception occurs while creating ospf %i' % ospf_id)


def r_connect(host,port,usr,passwd):
    try:
            return manager.connect(host=host,
                    port=port,
                    username=usr,
                    password=passwd,
                    hostkey_verify=False)
    except EnvironmentError:
        print('Exception occurred while connecting %s' % host)


def main_menu():
    print(30 * "*", "Simple Conf Wizard", 30 * "*")
    print("1. Configure OSPF for router.")
    print("2. Download router configuration.")
    print("3. Quit")
    print(60 * "*")


def conn():
    user = input('Username: ')
    password = getpass()
    #loop = True
    with r_connect('192.168.1.46','22',user,password) as m:
        print("Connection is established" )
        time.sleep(3)
        #while loop:
        main_menu()
        try:
                choice = int(input("What you want to do? [1-3] "))
        except ValueError:
                print("Oops you have entered an invalid choice")
                #continue
        if choice == 1:
            ip = input("Enter IP address for Ethernet0/0: ")
            mask = input("Enter subnet mask: ")
            print("Interface has been configured")
            ospf_id = int(input("Enter OSPF id: "))
            router_id = input("Enter router id: ")
            network1 = input("Enter 1st network to be advertised: ")
            network2 = input("Enter 2nd network to be advertised: ")
            create_interface_ip(m, "Ethernet0/0", ip, mask)
            create_ospf(m,ospf_id,router_id,'Ethernet0/0',network1,network2)
            print("OSPF has been configured")
            #time.sleep(3)
        elif choice == 2:
            path = 'd:/temp/'
            today = datetime.now().strftime("%d%m%y-%H%M")
            filename = "config" + today + ".cfg"
            fullpath = os.path.join(path, filename)
            output = m.get_config(source='running').data_xml
            with open(fullpath, "w") as f:
                f.write(output)
                print("Backup saved in {}".format(fullpath))
        elif choice == 3:
            print("bye")
        else:
            print("You may have entered an invalid choice")


if __name__ == '__main__':
    #logging.basicConfig(level=logging.DEBUG)
    conn()

Before configuration

R3#sh ip int brief | include Ethernet0/0
Ethernet0/0 unassigned YES TFTP administratively down down


R3#sh run | s r o
R3#

No OSPF and interface e0/0 is down and no ip address assigned.

Test option 1
pycharm2.png

Here’s the outcome after option 1 was chosen:

R3#
*Sep 2 05:13:58.873: %LINK-3-UPDOWN: Interface Ethernet0/0, changed state to up
R3#
*Sep 2 05:13:59.878: %LINEPROTO-5-UPDOWN: Line protocol on Interface Ethernet0/0, changed state to up
R3#

The interface is up after the option 1 was selected.

Here is the router’s configuration:

R3#sh run int e0/0
Building configuration...

Current configuration : 102 bytes
!
interface Ethernet0/0
description Configured by ncclient
ip address 10.0.0.2 255.255.255.252
end

R3#sh run | s r o
router ospf 1
router-id 3.3.3.3
passive-interface default
no passive-interface Ethernet0/0
network 10.0.0.2 0.0.0.0 area 0
network 192.168.1.46 0.0.0.0 area 0
R3#

Test option 2
pycharm3

Here’s the file in my folder:
pycharm4.png

This is the configuration which was downloaded:
pycharm5

Visible password
The password was visible in debug, however it is not visible when it was executed outside the Python IDE environment:
pycharm6

Posted in OSPF, Python, Scripting | Tagged , , , , , , , | Leave a comment

Testing configuration with ncclient (netconf)

I wanted to extend the previous post regarding using netmiko to get the configuration, well since my router supports netconf, I turned on netconf and did a test on getting configuration using get-config.

Now i am testing edit-config to try assigning ip address to an interface and turn the interface on.

Let’s see my R3, which I have default the ethernet0/0 and shut it down.

R3#sh run int e0/0
Building configuration...

Current configuration : 54 bytes
!
interface Ethernet0/0
no ip address
shutdown
end

On ncclient I only need to prepare field for the edit_config() to send to the router.
I can set the target to candidate, running or startup, i have not tried candidate yet since Cisco never has candidate before lol…
I tried the running instead.

So here’s my IOS command config which i want to pass to router using netconf with ncclient.

CREATE_INTERFACE_IP = """
    <config>
        <cli-config-data>
            <cmd>interface %s</cmd>
            <cmd>ip address %s %s</cmd>
            <cmd>no shutdown</cmd>
        </cli-config-data>
    </config>
"""

So here’s the code which i am testing..

from ncclient import manager
import logging

CREATE_INTERFACE_IP = """
    <config>
        <cli-config-data>
            <cmd>interface %s</cmd>
            <cmd>ip address %s %s</cmd>
            <cmd>no shutdown</cmd>
        </cli-config-data>
    </config>
"""


def create_interface_ip(conn, interface, ip, mask):
    try:
        config_str = CREATE_INTERFACE_IP % (interface, ip, mask)
        rpc_sent = conn.edit_config(target='running', config=config_str)
    except Exception:
        print('Exception occurs while creating interface %s' % interface) 


#netconf connection to router
def r_connect(host,port,user,password,):
        return manager.connect(host=host,
                               port=port,
                               username=user,
                               password=password,
                               hostkey_verify=False)

# Test the code here
with r_connect('192.168.1.46','22','cisco','cisco') as m:
        logging.basicConfig(level=logging.DEBUG)
        create_interface_ip(m, "Ethernet0/0", '10.0.0.2', '255.255.255.252')

My exception handling is too general hence i could not get any useful information, at first my code hit exception.. in the end because i put in a broadcast address into the command inadvertently -_-”

the logging is the python debugging in fact not much useful information as it only returns python related logs…

So from Cisco it receives my xml configuration as below, seems like ncclient helped me send the hello response:

*Sep  1 21:51:46.468: GSI: netconf app _s_ssh.[0xC4DD7840]: <?xml version="1.0" encoding="UTF-8"?><nc:hello xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><nc:capabilities><nc:capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:capability:confirmed-commit:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:capability:xpath:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:capability:validate:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:base:1.1</nc:capability><nc:capability>urn:ietf:params:netconf:capability:interleave:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:capability:writable-running:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:base:1.0</nc:capability><nc:capability>urn:liberouter:params:netconf:capability:power-control:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:capability:startup:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:capability:notification:1.0</nc:capability><nc:capability>urn:ietf:params:netconf:capability:url:1.0?scheme=http,ftp,file,https,sftp</nc:capability><nc:capability>urn:ietf:params:netconf:capability:candidate:1.0</nc:capability></nc:capabilities></nc:hello>
*Sep  1 21:51:46.468: NETCONF: _namn.54.mlc.don=C5CCF4B8
*Sep  1 21:51:46.468: NETCONF: _narc.54.rcv.ok=C5D134DC
*Sep  1 21:51:46.468: NETCONF: netconf_xml_interpret.54.msg_len=1195 bytes
*Sep  1 21:51:46.468: NETCONF: netconf_xml_interpret.54.ok
*Sep  1 21:51:46.468: NETCONF: _nem.54.msg_type=1
*Sep  1 21:51:46.468: NETCONF: netconf hello#23.count=0
*Sep  1 21:51:46.468: NETCONF: _nem.54.nre_type=3
*Sep  1 21:51:46.468: NETCONF: _nmfr.54.now=C5E727D0
*Sep  1 21:51:46.468: NETCONF: _nefhm.now=C5E727D0
*Sep  1 21:51:46.468: NETCONF: _nefrp.now=C5E727D0
*Sep  1 21:51:46.568: GSI: netconf app _s_ssh.[0xC4DD7840]: <?xml version="1.0" encoding="UTF-8"?><nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:6403fff2-1d0b-434c-b1c7-b09f0edc8aa6"><nc:edit-config><nc:target><nc:running/></nc:target><config>
        <cli-config-data>
            <cmd>interface Ethernet0/0</cmd>
            <cmd>ip address 10.0.0.2 255.255.255.252</cmd>
            <cmd>no shutdown</cmd>
        </cli-config-data>
    </config></nc:edit-config></nc:rpc>
*Sep  1 21:51:46.568: NETCONF: _namn.55.mlc.don=C5CD2140
*Sep  1 21:51:46.568: NETCONF: _narc.55.rcv.ok=C5D134DC
*Sep  1 21:51:46.568: NETCONF: netconf_xml_interpret.55.msg_len=448 bytes
*Sep  1 21:51:46.568: NETCONF: netconf_xml_interpret.55.ok
*Sep  1 21:51:46.568: NETCONF: _nem.55.msg_type=2
*Sep  1 21:51:46.568: NETCONF: _nsv.31.vty=C5794710 usr=cisco priv=15 cvw=0
*Sep  1 21:51:46.568: NETCONF:cli.12.1=[interface Ethernet0/0] prv=PARSE_ERROR_NOERR prc=(SUCCESS) oLen=0 cLen=0.
*Sep  1 21:51:46.579: NETCONF:cli.12.2=[ip address 10.0.0.2 255.255.255.252] prv=PARSE_ERROR_NOERR prc=(SUCCESS) oLen=0 cLen=0.
*Sep  1 21:51:46.579: NETCONF:cli.12.3=[no shutdown] prv=PARSE_ERROR_NOERR prc=(SUCCESS) oLen=0 cLen=0.
*Sep  1 21:51:46.579: NETCONF: _nssd.56.snd.now<?xml version="1.0" encoding="UTF-8"?><rpc-reply message-id="urn:uuid:6403fff2-1d0b-434c-b1c7-b09f0edc8aa6" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><ok /></rpc-reply>
*Sep  1 21:51:46.579: NETCONF: _nssd.56.snd.don=C5D134DC msg=C5D133D4
*Sep  1 21:51:46.579: NETCONF: ne_send.sess=0xC5D134DC
*Sep  1 21:51:46.579: NETCONF: _nem.55.nre_type=3
*Sep  1 21:51:46.579: NETCONF: _nmfr.55.now=C4851C90
*Sep  1 21:51:46.579: NETCONF: _nefom.now=C4851C90
*Sep  1 21:51:46.579: NETCONF: _nefrp.now=C4851C90
*Sep  1 21:51:46.682: GSI: netconf app _s_ssh.[0xC4DD7840]: <?xml version="1.0" encoding="UTF-8"?><nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:617e6a2a-9c54-4b2e-a868-3bc9e1218f31"><nc:close-session/></nc:rpc>

Now to test the code:
My router’s logging console:

--More--
*Sep 1 22:09:03.324: %LINK-3-UPDOWN: Interface Ethernet0/0, changed state to up
*Sep 1 22:09:04.333: %LINEPROTO-5-UPDOWN: Line protocol on Interface Ethernet0/0, changed state to up

See the interface ip address now:

R3#sh ip int brief | in Ethernet0/0
Ethernet0/0 10.0.0.2 YES TFTP up up
R3#

Posted in Python, Scripting | Tagged , , | Leave a comment

Testing on netconf with Python ncclient module

Cisco router
On the cisco router I need to enable ssh version 2, netconf will only run on sshv2.

Also I need to create an ACL to allow Netconf over ssh.


ip ssh version 2
cypto key generate rsa modulus 2048 general-keys
access-list 1 permit 192.168.1.0 0.0.0.255
netconf ssh acl 1
netconf ssh

Originally I tried with plink to connect from windows using this command plink -s cisco@192.168.1.46 netconf
I got connected and saw the netconf hello xml, but I need to give a response back, but unfortunately I could not seem to be able to paste the hello xml response back to the command prompt.. So I tried an alternative and found ncclient on python.

from ncclient import manager
import os.path

path = "d:/temp/"
filename = os.path.join(path, "config.xml")
m = manager.connect(host='192.168.1.46', port='22', username='cisco', password='cisco', hostkey_verify=False)
tmp = m.get_config(source='running').data_xml
f = open(filename, "w")
f.write(tmp)
f.close()

It seems the manager.connect() does not work well with dictionary… hence I put in the arguments directly into connect()

The response from the netconf router
There is nothing special to the response… it includes a xml header and the rest are old school cisco command lines.

<?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><cli-config-data-block>!
! Last configuration change at 19:33:47 UTC Fri Sep 1 2017
!
version 15.5
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname R3
!
boot-start-marker
boot-end-marker
!
!
enable secret 5 $1$vXrW$AjAyyXZ806fS/LlnFwAX/.
!
no aaa new-model
!
!
!
bsd-client server url https://cloudsso.cisco.com/as/token.oauth2
mmi polling-interval 60
no mmi auto-configure
no mmi pvc
mmi snmp-timeout 180
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
ip domain name cyruslab.local
ip cef
no ipv6 cef
!
multilink bundle-name authenticated
!
!
!
!
!
!
!
cts logging verbose
!
!
username cisco privilege 15 secret 5 $1$ch6j$YKylcY7mY0dnvV9gDxQTe0
!
redundancy
!
!
ip ssh version 2
ip scp server enable
! 
!
!
!
!
!
!
!
!
!
!
!
!
interface Loopback3
 ip address 3.3.3.3 255.255.255.255
!
interface Ethernet0/0
 ip address 10.0.0.2 255.255.255.252
!
interface Ethernet0/1
 ip address dhcp
!
interface Ethernet0/2
 no ip address
 shutdown
!
interface Ethernet0/3
 no ip address
 shutdown
!
router ospf 1
 passive-interface default
 no passive-interface Ethernet0/0
 network 3.3.3.3 0.0.0.0 area 0
 network 10.0.0.2 0.0.0.0 area 0
 network 192.168.1.0 0.0.0.255 area 0
!
ip forward-protocol nd
!
!
no ip http server
no ip http secure-server
!
!
!
access-list 1 permit 192.168.1.0 0.0.0.255
!
control-plane
!
!
!
!
!
!
!
!
line con 0
 logging synchronous
line aux 0
line vty 0 4
 privilege level 15
 logging synchronous
 login local
 transport input ssh
!
netconf ssh acl 1
!
end
</cli-config-data-block></data>
Posted in General stuffs | Leave a comment