CiscoConfParse Legacy Syntax

Warning

The methods covered in this section are only for documentation purposes. As of version 1.9.43, they are offically removed from CiscoConfParse. Refer to the CiscoConfParse Tutorial for the latest API information.

This section will cover the legacy CiscoConfParse() 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, they have been removed as of CiscoConfParse version 1.9.43.

Baseline configuration

This tutorial will run all the queries against a sample configuration, which is shown below.

 1! Filename: /tftpboot/bucksnort.conf
 2!
 3policy-map QOS_1
 4 class GOLD
 5  priority percent 10
 6 class SILVER
 7  bandwidth 30
 8  random-detect
 9 class default
10!
11interface Ethernet0/0
12 ip address 1.1.2.1 255.255.255.0
13 no cdp enable
14!
15interface Serial1/0
16 encapsulation ppp
17 ip address 1.1.1.1 255.255.255.252
18!
19interface Serial1/1
20 encapsulation ppp
21 ip address 1.1.1.5 255.255.255.252
22 service-policy output QOS_1
23!
24interface Serial1/2
25 encapsulation hdlc
26 ip address 1.1.1.9 255.255.255.252
27!
28class-map GOLD
29 match access-group 102
30class-map SILVER
31 match protocol tcp
32!
33access-list 101 deny tcp any any eq 25 log
34access-list 101 permit ip any any
35!
36access-list 102 permit tcp any host 1.5.2.12 eq 443
37access-list 102 deny ip any any
38!
39logging 1.2.1.10
40logging 1.2.1.11
41logging 1.2.1.12

Finding interface names that match a substring

The following script will load a configuration file from /tftpboot/bucksnort.conf and use find_lines() to find the Serial interfaces.

Note that the ^ symbol at the beginning of the search string is a regular expression; ^interface Serial tells python to limit the search to lines that begin with interface Serial.

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.

Finding parents with a specific child

The last example was a nice start, but if this was all CiscoConfParse could do, then it’s easier to use grep.

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 config.

find_parents_w_child() requires at least two different arguments:

  • The first argument is a regular expression to match the parents

  • The second argument is a regular expression to match the child

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 the configuration.

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" )

Results:

>>> qos_intfs
['interface Serial1/1']

Finding parents without a specific child

Let’s suppose you wanted a list of all interfaces that have CDP enabled; this implies a couple of things:

  1. CDP has not been disabled globally with no cdp run

  2. The interfaces in question are not configured with no cdp enable

find_parents_wo_child() is a function to find parents without a specific child; it requires arguments similar to find_parents_w_child():

  • The first argument is a regular expression to match the parents

  • The second argument is a regular expression to match the child’s exclusion

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 use 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')

Results:

>>> cdp_intfs
['interface Serial1/0', 'interface Serial1/1', 'interface Serial1/2']

Finding children

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')

Results:

>>> children
['policy-map QOS_1', ' class GOLD', ' class SILVER', ' class default']

If you do want the children (recursively), then use find_all_children().

>>> 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']

Checking Passwords

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.

Note

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 another Cisco IOS Type password; these are much more secure and cannot be easily decrypted.

Warning

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 CiscoPassword class

>>> from ciscoconfparse import CiscoPassword
>>> dp = CiscoPassword()
>>> decrypted_passwd = dp.decrypt('107D3D232342041E3A')

Result:

>>> decrypted_passwd
'STZF5vuV'