This section will cover the legacy
syntax; these were the original methods before version 1.0.0; legacy
methods always returned text strings. This makes them easier to learn, but
harder to write complex scripts with. There is nothing wrong with continuing to use these methods; however, you will probably find that your scripts are more
efficient if you use the newer methods that manipulate
IOSCfgLine() objects, which were introduced in
This tutorial will run all the queries against a sample configuration, which is shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
! Filename: /tftpboot/bucksnort.conf ! policy-map QOS_1 class GOLD priority percent 10 class SILVER bandwidth 30 random-detect class default ! interface Ethernet0/0 ip address 184.108.40.206 255.255.255.0 no cdp enable ! interface Serial1/0 encapsulation ppp ip address 220.127.116.11 255.255.255.252 ! interface Serial1/1 encapsulation ppp ip address 18.104.22.168 255.255.255.252 service-policy output QOS_1 ! interface Serial1/2 encapsulation hdlc ip address 22.214.171.124 255.255.255.252 ! class-map GOLD match access-group 102 class-map SILVER match protocol tcp ! access-list 101 deny tcp any any eq 25 log access-list 101 permit ip any any ! access-list 102 permit tcp any host 126.96.36.199 eq 443 access-list 102 deny ip any any ! logging 188.8.131.52 logging 184.108.40.206 logging 220.127.116.11
The following script will load a configuration file from
/tftpboot/bucksnort.conf and use
find_lines() to find the
Note that the
^ symbol at the beginning of the search string is a regular
^interface Serial tells python to limit the search to lines
that begin with
To find matching interface statements, use this code...
>>> from ciscoconfparse import CiscoConfParse >>> parse = CiscoConfParse("/tftpboot/bucksnort.conf") >>> serial_lines = parse.find_lines("^interface Serial") >>> serial_lines ['interface Serial1/0', 'interface Serial1/1', 'interface Serial1/2']
Going forward, I will assume that you know how to use regular expressions; if you would like to know more about regular expressions, O’Reilly’s Mastering Regular Expressions book is very good.
The last example was a nice start, but if this was all
CiscoConfParse could do, then it’s easier to
Let’s suppose you need to find all interfaces that are configured with
service-policy QOS_1 in the output direction. We will use
find_parents_w_child() to search the
find_parents_w_child() requires at least
two different arguments:
If the arguments above match both the parent and child respectively, then
find_parents_w_child() will add the
parent’s line to a list. This list is returned after
find_parents_w_child() finishes analyzing
In this case, we need to find parents that begin with
^interface and have a child matching
service-policy output QOS_1. One might wonder why we chose to put a caret (
^) in front of the parent’s regex, but not in front of the child’s regex. We did this because of the way IOS indents commands in the configuration. Interface commands always show up at the top of the heirarchy in the configuration; interfaces do not get indented. On the other hand, the commands applied to the interface, such as a service-policy are indented. If we put a caret in front of
service-policy output QOS_1, it would not match anything because we would be forcing a beginning-of-the-line match. The search and result is shown below.
>>> parse = CiscoConfParse("/tftpboot/bucksnort.conf") >>> qos_intfs = parse.find_parents_w_child( "^interf", "service-policy output QOS_1" )
>>> qos_intfs ['interface Serial1/1']
Let’s suppose you wanted a list of all interfaces that have CDP enabled; this implies a couple of things:
no cdp run
no cdp enable
Since we need to find parents that do not have
no cdp enable, we will use
find_parents_wo_child() for this query.
Note that the script below makes use of a special property of python lists...
empty lists test False in Python; thus, we can
if not bool(parse.find_lines('no cdp run')) to ensure that CDP is
running globally on this device.
>>> if not bool(parse.find_lines('no cdp run')): ... cdp_intfs = parse.find_parents_wo_child('^interface', 'no cdp enable')
>>> cdp_intfs ['interface Serial1/0', 'interface Serial1/1', 'interface Serial1/2']
Let’s suppose you needed to look at the children of a particular parent, but
you didn’t want the children’s children.
find_children() was made for this purpose.
>>> children = parse.find_children('policy-map QOS_1')
>>> children ['policy-map QOS_1', ' class GOLD', ' class SILVER', ' class default']
If you do want the children (recursively), then use
>>> all_children = parse.find_all_children('policy-map QOS_1')
>>> all_children ['policy-map QOS_1', ' class GOLD', ' priority percent 10', ' class SILVER', ' bandwidth 30', ' random-detect', ' class default']
CiscoConfParse‘s functions support one of these options:
exactmatch - This can either be
False (the default). When
exactmatch is set
True, CiscoConfParse requires an exact match of the whole string (instead of a sub-string match, which is the default).
ignore_ws - This can either be
False (the default). When
ignore_ws is set
True, CiscoConfParse will ignore differences in whitespace between the query string and the IOS configuration.
Not all functions support the options above; please consult the API documentation for specifics.
Sometimes you find yourself wishing you could decrypt vty or console passwords to ensure that they conform to the corporate standard.
CiscoConfParse comes with a
CiscoPassword class that can decrypt some Cisco IOS type 7 passwords.
Cisco IOS Type 7 passwords were never meant to be secure; these passwords only protect against shoulder-surfing. When you add users and enable passwords to your router, be sure to use Cisco IOS Type 5 passwords; these are much more secure and cannot be decrypted.
CiscoPassword also cannot decrypt all Type 7 passwords. If the passwords exceed a certain length, the algorithm I have ceases to work. An error is printed to the console when this happens. In a future version of the script I will raise a python error when this happens.
Simple example... let’s suppose you have this configuration...
line con 0 login password 107D3D232342041E3A exec-timeout 15 0
We need to ensure that the password on the console is correct. This is easy with the
>>> from ciscoconfparse import CiscoPassword >>> dp = CiscoPassword() >>> decrypted_passwd = dp.decrypt('107D3D232342041E3A')
>>> decrypted_passwd 'STZF5vuV'