Cisco IOS-XE Guest Shell

Cisco IOS-XE now comes with a neat feature called Guest Shellit give us the power of spinning up a Linux Container on the router, giving us many new Network Programmability options, the main one being the option of running custom Python Scripts. With that we can write things like custom Metrics, Integrations, Features and tools not natively available.

Enabling the Guest Shell

I will be using a Cisco CSR1000v on AWS as an example (its easier to spin up and lab), but the feature is also available on ASR and ISR, and the way to enable is is fairly similar.
When you bring the CSR up, you should notice that it has a VirtualPortGroup Interface enabled, this Interface will be responsible for the Interface between the GuestShell Container and the router IOS-XE/External World. On platforms with managements ports, the mgmt interface/vrf would be used for the Interface with the GuestShell.

app-hosting appid guestshell
 vnic gateway1 virtualportgroup 0 guest-interface 0 guest-ipaddress netmask gateway
 resource profile custom cpu 1500 memory 512

guestshell enable VirtualPortGroup 0 guest-ip

That’s it, we can run show app-hosting list to confirm that GuestShell is enabled:

#show app-hosting list
App id                           State
guestshell                       RUNNING

To gain shell access, run  guestshell run bash:

#guestshell run bash
[guestshell@guestshell ~]$ uname -a
Linux guestshell 4.4.51 #1 SMP Sun Apr 23 01:42:33 PDT 2017 x86_64 x86_64 x86_64 GNU/Linux
[guestshell@guestshell ~]$

We are now able to start playing with Python. Your main Python package will be the cli package, this let you run IOS commands from the shell:

[guestshell@guestshell ~]$ python
Python 2.7.5 (default, Jun 17 2014, 18:11:42)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from cli import cli
>>> from cli import configure
>>> configure('hostname IT-WORKS')
[ConfigResult(success=True, command='hostname IT-WORKS', line=1, output='', notes=None)]
>>> cli('show running-config | in hostname')
'\nhostname IT-WORKS\n'

It also comes with pip installed, so you are able to install pretty much any package that you need to write your code.

I’ve been implementing a bunch of Cisco routers with ZBF lately, its a simple and nice Firewall solution for those that don’t need all that fancy features that vendors as CheckPoint or Palo Alto offer you, and one thing that happened a couple of times is ACL out o Sync between the devices, before we wrote a NAPALM script to update both devices at same time (more of this on a future post), I would sometimes update the ACL in one Router and forget to update the pair device, I would then test a failover and notice that traffic was dropped on the secondary router. (Oops!)

Verify ACL Sync with IOS-XE GuestShell and Python

This gave the Idea to write this example using GuestShell and Python for this blog post, the following Script runs after X specified seconds, compare the Local ACLs with the Remote ACLs, and generate a Syslog Message in case they are out of sync. Simple and helpful. Here’s the code, which is also available on my github:

#!/usr/bin/env python
from cli import cli
from cli import configure
from netmiko import ConnectHandler
This script should run on the GustShell, it requires netmiko to be installed. This will check the local acls, the peer
router ACls, compare the difference and generate a SysLog message in case they are out-of-sync.
#Users hardcoded in code as this is just an example script. In production you may want to use
#Some sort of Vault.
username = "superuser"
password = "superpass"
def get_remote_acls():
remote_acls = ""
#Specify the ip for the pair Router
device = { 'device_type': 'cisco_ios', 'ip':'', 'username': username,
'password': password}
net_connect = ConnectHandler(**device)
remote_acls = net_connect.send_command("show run | sec access-list")
return remote_acls
def acl_diff(local_acls,remote_acls):
lines = local_acls.splitlines()
lines = [line for line in lines if line.strip()]
local_acls = lines
lines = remote_acls.splitlines()
lines = [line for line in lines if line.strip()]
remote_acls = lines
if len(local_acls) > len(remote_acls):
diff = "ATTENTION. ACLs are not in Sync, local ACL has more entries than Peer."
elif len(remote_acls) > len(local_acls):
diff = "ATTENTION. ACLs are not in Sync, remote ACL has more entries than Peer."
diff = False
return diff
def log(message, severity):
cli('send log {} {}'.format(severity, message))
def reschedule(seconds, diff):
event manager applet ACL-SYNC-CHECK
event timer watchdog time %s
action 1.0 cli command "enable"
action 1.1 cli command "guestshell run /home/guestshell/
configure(UPDATE_SCRIPT_FIRING_COMMANDS % (seconds))
if diff:
def main():
local_acls = cli("show run | sec access-list")
remote_acls = get_remote_acls()
diff = acl_diff(local_acls, remote_acls)
#specify in seconds how long to wait between checks.
reschedule(1800, diff)
if __name__ == "__main__":

Copy this to a .py on the GuestShell, make it an executable with chmod +x, and execute it! If the ACLs on both devices are not the same, you will see this log msg on the Router:

*Feb  8 11:57:16.924: %SYS-4-USERLOG_WARNING: Message from tty3(user id: ): ATTENTION. ACLs are not in Sync, local ACL has more entries than Peer.

If you have a syslog Collector that Integrates with Slack or some other Chat Platform that your team uses, it should be easy to see when the ACLs are not in-sync, and now anyone can go to their favourite Version Control system where they manage their ACLs and re-apply the ACL to the device with missing entries. I am sure you store you ACLs in a repo, right? 🙂

With imagination and some available time this Script could be much improved, and many other cool tools/features could be written to level-up your Cisco IO-XE Routers!

I hope this helps someone, thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s