5

I'm trying to write a script that will pull configuration files over SSH from Cisco routers and parse them, so I can ensure that they meet predefined standards (e.g. password shouldn't be "cisco").

Connecting to the routers and running commands programmatically is simple. The barrier I run into is that running show running config returns global configuration settings as well as settings for particular interfaces.

My goal was to handle settings for interfaces differently from global settings; for example, I can ignore bad settings on interfaces that are disabled.

Are there separate commands for getting global settings and getting interface definitions (e.g. show global settings and a show interface settings type of commands)? Alternatively, is there a better way I can retrieve this information that would make it easier to parse?

2 Answers 2

4

Automated Cisco IOS config parsing

Alternatively, is there a better way I can retrieve this information that would make it easier to parse?

Parsing router / switch configurations is quite complicated due to the layers of hierarchy in IOS configs; whenever possible, use a tool which specializes in parsing for you. One such tool is ciscoconfparse (docs are here) Note 1. ciscoconfparse has a whole battery of unit tests, which ensure that parsing remains consistent between versions of the tool.

Assuming the configuration comes in the exact format used by Cisco IOS show running-config or show startup-config, ciscoconfparse automatically finds the interface-level configurations for you. This means you can automate standardization of interface and global configurations... This is an example switch interface configuration audit in the documentation. ciscoconfparse has a lot of functionality in it; you should spend some time reading the documentation.

There are also some specialized methods which do a lot of specific value parsing for you; these methods are currently in beta - and only visible in the source code... for instance suppose you have a switch configuration saved as c6509.conf

!
interface GigabitEthernet2/8
 ip address 192.0.2.1 255.255.255.252
 mtu 9000
 carrier-delay msec 50
!

You can use a script or the python interpreter to retrieve the IP address and carrier-delay in native python representations...

[mpenning@tsunami ~]$ python
Python 2.7.3 (default, Jan  2 2013, 13:56:14)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from ciscoconfparse import CiscoConfParse
>>> config = CiscoConfParse('c6509.conf', factory=True)
>>>
>>> intfs = config.find_objects('interface GigabitEthernet2/8', exactmatch=True)
>>> intfs
[<IOSIntfLine # 1 'GigabitEthernet2/8' info: '192.0.2.1/30'>]
>>>
>>> intfs[0].ip_addr
'192.0.2.1'
>>>
>>> intfs[0].has_manual_carrierdelay
True
>>>
>>> intfs[0].manual_carrierdelay
0.05
>>>
>>> intfs[0].manual_mtu
9000
>>>

If you want the beta functionality, you need to parse the config with factory=True, as shown above...


Native Cisco IOS parsing capabilities

My goal was to handle settings for interfaces differently from global settings; for example, I can ignore bad settings on interfaces that are disabled.

Are there separate commands for getting global settings and getting interface definitions (e.g. show global settings and a show interface settings type of commands)?

IOS lets you see individual interface-level configs, but it's very painful when you have potentially hundreds of interfaces... imagine running this command for every interface...

CORE01.PUB.DAL02#sh runn int gi1/2
Building configuration...

Current configuration : 242 bytes
!
interface GigabitEthernet1/2
 description Link to edge01.pub.dal02
 ip address 192.0.2.46 255.255.255.252
 ip ospf network point-to-point
 media-type rj45
end

CORE01.PUB.DAL02#

Depending on the image you're running, Cisco IOS allows a few other global configuration sections... this is from a router running 12.4...

EDGE01.PUB.DEN#sh running-config ?
  brief       configuration without certificate data
  class-map   Show class-map information
  full        full configuration
  interface   Show interface configuration
  linenum     Display line numbers in output
  map-class   Show map class information
  policy-map  Show policy-map information
  view        View options
  |           Output modifiers
  <cr>

EDGE01.PUB.DEN#

It's also possible to get portions of the global configuration using IOS regular expressions from the CLI... for instance...

EDGE01.PUB.DEN#show runn | include ^enable
enable secret 5 $1$mOmQ$sORLRqZQZ/cr7KSyrXUPZ.
EDGE01.PUB.DEN#

FYI, that's an MD5 hash for an enable password of "cisco", which you'd want to flag, if found in production...


Responding to this comment:

Is there a good way to define when an interface definition ends? It appears that all interface lines are indented by one space but I'm not sure if that's standard across configs

Yes, Cisco IOS always indents child configuration elements by an extra space... regardless of whether the child is an interface configuration statement, IP extended ACL line, etc...


End Notes

Note 1 Stack Exchange Disclaimer: I am the author.

3
  • Thank you! I don't think I'll be able to use the python code (it's a Java project), but I'm definitely going to use it as a launching point! Jul 24, 2014 at 12:19
  • Using ciscoconfparse in java should be possible if you use jython. Please file an issue on github if you run into a jython integration problem Jul 24, 2014 at 12:24
  • Can ciscoconfparse emit a marked-up version like json, yaml or xml? Oct 31, 2022 at 13:15
1

Since there is context in the format, you should consider parsing it contextually. You might need to write more code to do that. Consider using a model for your code that constructs an object model for the global state, interfaces, and such.

Operationally, removing non-compliant settings from disabled interfaces might be a good idea in case someone enables them.

4
  • Thats what i was considering doing. Is there a good way to define when an interface definition ends? It appears that all interface lines are indented by one space but I'm not sure if that's standard across configs Jul 23, 2014 at 20:27
  • Syntactically, it ends when the next one starts (I seem to recall some kind of keyword, exit or end or something, that brings you up one level but it's been a very long time). Jul 23, 2014 at 20:28
  • It also brings you back to global scope if you enter a directive with global scope I think. Parsing them requires a detailed understanding of what directives there are. Jul 23, 2014 at 20:30
  • That's how I planned on parsing it, what worried me was the chance that someone could put a global setting between interfaces. Is that a possibility? Essentially what I'm worried about is edge cases; I'm worried I might overgeneralize and miss an edge case. Jul 23, 2014 at 20:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .