A better library for automating network gear with Cisco-style command line interfaces
Project description
A better library for automating network gear with Cisco-style command line interfaces.
- Author:
Alex Forster (alex@alexforster.com)
- License:
BSD 3-Clause
Features
Provides a fluid API for parsing running-config and startup-config into strongly typed hierarchical objects that can be traversed with regex-based searching
Complete support for VT100-series terminal emulation, guaranteeing that what you see on the command line will also be what you receive from this library
Automatically handles Cisco-style “more” pagination and prompt matching, allowing for seamless read()/write() semantics regardless of the target device’s terminal settings
Provides special API support for enable authorization
Runs on any platform that has the OpenSSH binary installed
Tested against Cisco IOS, Catalyst, Nexus, ASA/PIX, and ASR series devices
Installation
pip install sisqo
PyPI: https://pypi.python.org/pypi/sisqo/2.0.2
Dependencies:
ptyprocess – a library for launching a subprocess in a pseudo terminal (pty)
pyte – an in memory VTXXX-compatible terminal emulator library
wcwidth – a library for wide-character width calculation
Example Code
from sys import exit
import sisqo
router = sisqo.SSH(username='jdoe', host='router.example.com')
with router:
if not router.authenticate('password123'):
exit(1) # could not authenticate with the router
if not router.enable('123456'):
exit(2) # could not enable on the router
router.write('show version')
versionInformation = router.read() #= "Cisco IOS Software, C2900 Software (C2900-UNIVERSALK9-M) ..."
print(versionInformation)
runningConfig = router.showRunningConfig()
# hostname router1
# !
# interface GigabitEthernet0/0
# shutdown
# interface GigabitEthernet0/1
# shutdown
# !
# router bgp 12345
# network 55.66.77.88/24
# neighbor 11.22.33.44
# remote-as 54321
# timers 7 21
# neighbor 22.33.44.55
# remote-as 98765
# timers 7 21
routerBGP = runningConfig.findChild('router bgp \d+') #= "router bgp 12345"
asn = routerBGP.value.split()[-1] #= "12345"
print('BGP neighbors of ASN {}'.format(asn))
bgpNeighbors = routerBGP.findChild('router bgp \d+').findChildren('neighbor .+')
for neighbor in bgpNeighbors: #= [<neighbor 11.22.33.44>, <neighbor 22.33.44.55>]
ipAddress = neighbor.value #= "neighbor 11.22.33.44"
ipAddress = ipAddress.split()[-1] #= "11.22.33.44"
print("Neighbor: {}".format(ipAddress))
API Documentation
class sisqo.SSH
Note: this class can be used as a context manager (using a “with” statement)
Constructor
__init__( username: str, host: str, port: Optional[int], sshConfigFile: Optional[str] )
Creates an object that initiates an SSH connection as username to the provided host and port (default: 22).
The OpenSSH client, by default, will obey the system’s /etc/ssh/ssh_config file as well as the current user’s ~/.ssh/config file. You can provide a path to a custom ssh_config file using the sshConfigFile argument, which will prevent these default configuration files from being considered.
Properties
- host: readonly str
Hostname or IP address to SSH into
- port: readonly int
Port number to connect to
- promptRegex: str
Regular Expression used to match shell prompts
- moreRegex: str
Regular Expression used to match Cisco-style “more” pagination prompts
Methods
authenticate( password: Optional[str], passphrase: Optional[str],
promptCallback: Optional[lambda], promptState: Optional[dict] ): None
Allows the user to reliably respond to an authentication prompt (password and/or private key passphrase) if necessary.
This method also provides a convenient way to handle alternative prompts, for situations where something other than a password or passphrase are required (for example, a TOTP multi-factor challenge code).
The promptCallback parameter should be a function that responds to the alternative prompt. It will be called repeatedly until it either returns a correct response, or it returns None to indicate that it cannot answer the prompt successfully. The signature of the callback is: (prompt: str, state: dict[str, object], logger: logging.Logger): Optional[bool]
The promptState parameter is a way to pass in persistent state information to the prompt callback via a dictionary. The same dictionary will be passed in for successive calls to promptCallback. It is seeded with password and passphrase properties by the authenticate method, corresponding to the provided arguments of the same name.
For example, to try guessing multiple passwords, one could do the following–
from sys import exit
import sisqo
state = { 'passwordsToTry': ['cisco', '123456', 'password123'] }
def onPrompt(prompt, state, logger):
if 'password:' not in prompt.lower(): return None
if len(state['passwordsToTry']) == 0: return None
return state['passwordsToTry'].pop()
with sisqo.SSH(username='cisco', host='router.example.com') as router:
if not router.authenticate(promptCallback=onPrompt, promptState=state):
exit(1) # none of the passwords we tried worked
# successfully authenticated using one of the three passwords we tried
router.write('show version')
read( self, timeout: Optional[int], stripPrompt: Optional[bool], promptRegex: Optional[re] ): str
Reads from the target device up to the next prompt, with special handling for Cisco-style “more” pagination. If a prompt cannot be matched in the output, the read operation returns after timeout seconds (default: 10). The stripPrompt argument can be used to control whether or not the text of the prompt is returned as part of the read operation (default: True). The promptRegex argument (default: None), if specified, overrides the class’s promptRegex property.
write( self, command: str, timeout: Optional[int], consumeEcho: Optional[bool ): None
Writes command to the target device. This function can optionally suppress the terminal’s echoback. If consumeEcho is True (the default), this function will implicitly read up to len(command) bytes or until timeout seconds has passed (default: 10). When manually responding to password prompts, you should set consumeEcho to False if the password is not typically echoed back to you as asterisks or otherwise.
Warning: this function implicitly discards any previously unread data without returning it to the consumer.
enable( password: str ): bool
Helper function to elevate privileges on the target network gear, with special handling for the “Password” prompt.
Warning: enable is not supported on certain Cisco-alike operating systems
showRunningConfig(): Configuration
Helper function to retrieve the target device’s running-config and parse it into a sisqo.Configuration object.
showStartupConfig(): Configuration
Helper function to retrieve the target device’s startup-config and parse it into a sisqo.Configuration object.
Warning: startup-config is not supported on certain Cisco-alike operating systems
disconnect(): None
Closes the SSH connection with the target device, if open. Called automatically when exiting a context manager and/or when the object is garbage collected.
class Configuration
Note: instances of this class are returned from sisqo.SSH.showRunningConfig() and sisqo.SSH.showStartupConfig()
Constructor
__init__( configString: str )
Parses a Cisco configuration file configString into a hierarchical, searchable representation of configuration lines.
Methods
findChild( regex: str ): Line
Searches the root node of the hierarchy for the first line that matches the provided regex.
findChildren( regex: str ): list[Line]
Searches the root node of the hierarchy for lines that match the provided regex.
class Line
Note: instances of this class are returned from sisqo.Configuration.findChild() and sisqo.Configuration.findChildren()
Constructor
__init__( number: int, indent: str, value: str )
Creates an in-memory representation of a single line of a Cisco configuration file.
Properties
- value: str
Text of this configuration line, stripped of indentation
- parent: Line
Hierarchical parent of this configuration line
- children: list[Line]
List of hierarchical children of this configuration line
- lineNumber: int
Line number from the original configuration text
- indentation: readonly int
Indentation level of this configuration line
- depth: readonly int
Depth of this line in the configuration hierarchy
Methods
findChild( regex: str ): Line
Searches the children of this node for the first line that matches the provided regex and returns that line.
findChildren( regex: str ): list[Line]
Searches the children of this node for lines that match the provided regex and returns a list of matching lines.
class sisqo.NotConnectedError : Exception
Thrown when certain operations are tried on a sisqo.SSH instance which is not connected.
class sisqo.NotAuthenticatedError : Exception
Thrown when certain operations are tried on a sisqo.SSH instance which has not yet authenticated.
class sisqo.AlreadyAuthenticatedError : Exception
Thrown when authentication is tried on a sisqo.SSH instance which has already authenticated.
class sisqo.BadAuthenticationError : Exception
Thrown when authentication fails.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file sisqo-2.0.2.tar.gz
.
File metadata
- Download URL: sisqo-2.0.2.tar.gz
- Upload date:
- Size: 10.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | dcab0f349fa9e8cd0808f829a63f714f03b3027313d65a76034a0172b455c3b9 |
|
MD5 | f878ee79b1cf576d9b3c8c8501f9bb83 |
|
BLAKE2b-256 | 6c20f148217e73b572e032cc68972669f3757c86d4733f986eceef161fcc1465 |