Quantcast
Channel: LINICKX.com
Viewing all 88 articles
Browse latest View live

RPM SPECS for Python CiscoConfParse

$
0
0

Recently I have been using ciscoconfparse to loop through Cisco configs, installing on my local laptop is straightforward with pip however getting it onto a customers linux jump server can be a bit more tricky (proxies, build deps and the like).

For Redhat/Centos (6) boxes I found an out of date .src.rpm therefore I have updated the SPEC file:

I have made two changes, I updated to the ciscoconfparse 1.2.16 and added the python-ipaddr dependency.

To build your own yo will also need:

The only change I have made there is to add the correct download URL to the Source so that it build without the human having to put the package in the right directory.... other than that all other build deps should be in the standard base repositories.

Building them is straight forward with rebuild -ba, I have an old post here... fedora have a much more comprehensive one here... I haven't uploaded pre-built RPMs to my repo as I haven't found the need to for years, maybe this is a good excuse to resurrect it!


Cisco NTP Authentication to Linux Server

$
0
0

NTP Authentication is a recommended best security practice; there are a lot of documents out there on how to setup NTP authentication between two Cisco IOS devices but anything between Cisco and LINUX is few and far between.

I have setup a LINUX Server (Redhat/CentOS) box, that will act as an upstream proxy to pool.ntp.org. NTP authentication will be enabled on the LINUX box so that the downstream Cisco IOS box (router/switch) can be configured with authentication.

CentOS Server config

Start with installing and starting NTP.

sudo yum install ntpd
sudo systemctl start  ntpd.service

... don't forget to open the firewall...

sudo firewall-cmd --permanent --zone=public --add-port=123/udp

Next, add a key to /etc/ntp/keys...

# For more information about this file, see the man page ntp_auth(5).
#
# id    type    key
1 M Cisco123

What I've done here is, add a key with id 1 that is type MD5 (authentication), the key is Cisco123

Now, setup /etc/ntp.conf, below is an example of a minimal config (with comments removed, backup your original).

# For more information about this file, see the man pages
# ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5).

driftfile /var/lib/ntp/drift
restrict default nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict ::1

restrict 1.1.1.0 mask 255.255.255.252 nomodify notrap
restrict 2.2.2.0 mask 255.255.255.252 nomodify notrap

server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst

keys /etc/ntp/keys
trustedkey 1

disable monitor

Take note of two things.

  1. trustedkey 1 must match the ID in /etc/ntp/keys
  2. restrict 1.1.1.0 mask 255.255.255.252 nomodify notrap this says that any client (i.e IOS router) in the 1.1.1.0/30 network can query out CentOS time server

Restart NTP to make the changes effective.

sudo systemctl restart  ntpd.service

Use ntpq to check its working...

[nick@CentOS7 ~]$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ntp1.as34288.ne 85.158.25.72     2 u   31   64  377   56.363  -52.207  15.576
+ntp.coreless.ne 77.40.226.114    2 u   30   64  377   64.117  -45.444  10.966
-fra94-1-78-193- 212.83.158.83    3 u   23   64  377   42.197  -44.928  10.275
+dn3t.de         129.69.1.153     2 u   98   64  376   44.418  -42.061   7.436
[nick@CentOS7 ~]$

Don't move onto the IOS box until ntpq shows a * next to one of the upstream servers. You need clocks sync'd on the linux box before the IOS one will work. It should take at least 5 minutes to sync up; if you are having issues, manually set the linux clock to within a minute and restart the NTP service.

Cisco IOS Config

My Cisco router is 1.1.1.1, my linux server is 1.1.1.2, make sure both boxes can ping each other ;-)

The router config is...

ntp authentication-key 1 md5 Cisco123
ntp trusted-key 1
ntp server 1.1.1.2 key 1
ntp authenticate

Take note of the order! I wasted loads of time troubleshooting the debug error NTP Core(INFO): 1.1.1.2 C01C 8C bad_auth no key because the command order is fussy

You can check it's working with the show ntp association commands... notice on the detailed version is says authenticated

R1#show ntp as

  address         ref clock       st   when   poll reach  delay  offset   disp
*~1.1.1.2         81.94.123.17     3     41     64     7 16.017  -4.263  1.893
 * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured
R1#show ntp as detail
1.1.1.2 configured, ipv4, authenticated, our_master, sane, valid, stratum 3
ref ID 81.94.123.17   , time D9104931.F7121393 (13:46:25.965 UTC Wed May 27 2015)
our mode client, peer mode server, our poll intvl 64, peer poll intvl 64
root delay 56.70 msec, root disp 63.87, reach 7, sync dist 6302.70
delay 16.01 msec, offset -4.2633 msec, dispersion 1.89, jitter 6199.94 msec
precision 2**24, version 4
assoc id 42451, assoc name 1.1.1.2
assoc in packets 40, assoc out packets 42, assoc error packets 0
org time 00000000.00000000 (00:00:00.000 UTC Mon Jan 1 1900)
rec time D91049C8.3C62C714 (13:48:56.235 UTC Wed May 27 2015)
xmt time D91049C8.3C62C714 (13:48:56.235 UTC Wed May 27 2015)
filtdelay =   107.76   51.78   16.01   19.97   23.99   19.84   32.00   43.89
filtoffset = 16398.9   76.43   -4.26   -1.38   22.31   27.85   22.48    8.67
filterror =     0.00    0.99    1.87    1.90    1.93    1.96    1.99    2.02
minpoll = 6, maxpoll = 10

R1#

Footnote

NTP authentication is one way, the client authenticates the response from the server, so authentication is optional.

I also have another router (2.2.2.2) talking to the CentOS linux server (1.1.1.2) with a default config....

ntp server 1.1.1.2

And it works just fine...

R2#show ntp as

  address         ref clock       st   when   poll reach  delay  offset   disp
*~1.1.1.2         81.94.123.17     3     18     64     1 39.632  -1.911 187.61
 * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured
R2#
R2#
R2#show ntp as det
1.1.1.2 configured, ipv4, our_master, sane, valid, stratum 3
ref ID 81.94.123.17   , time D9104B06.F4F12334 (13:54:14.956 UTC Wed May 27 2015)
our mode client, peer mode server, our poll intvl 64, peer poll intvl 64
root delay 47.43 msec, root disp 55.89, reach 1, sync dist 322.40
delay 39.63 msec, offset -1.9110 msec, dispersion 187.61, jitter 34.98 msec
precision 2**24, version 4
assoc id 48023, assoc name 1.1.1.2
assoc in packets 8, assoc out packets 8, assoc error packets 0
org time 00000000.00000000 (00:00:00.000 UTC Mon Jan 1 1900)
rec time D9104B96.A0AFE3F2 (13:56:38.627 UTC Wed May 27 2015)
xmt time D9104B96.A0AFE3F2 (13:56:38.627 UTC Wed May 27 2015)
filtdelay =    76.05   48.05   39.83   56.03   39.85   39.63    0.00    0.00
filtoffset =   64.31   33.05    5.55   17.13  -11.56   -1.91    0.00    0.00
filterror =     0.00    0.03    0.06    0.09    0.12    0.15 16000.0 16000.0
minpoll = 6, maxpoll = 10

R2#

So make sure your clients have authentication enabled.

That old Cisco IPSEC VPN Client hangs on Windows 7 64bit

$
0
0

Most people have migrated to AnyConnect or abandoned Cisco altogether in disgust that Remote Access VPN is chargeable but there are a few installations out there who hang onto their beloved old yellow client before they send it to the farm in the sky.

I recently came across one of these, normally I'd just use the native OSX client or VPNc (for linux) but that doesn't help me if I need to run vSphere ;-)

After installing vpnclient-winx64-msi-5.0.07.0440-k9.exe (from cisco here) blindly clicking next-next-next-reboot on my Windows 7 64bit machine I found the client to hang and run horribly slowly.

After a quick google I found this Cisco forum post ... uninstall, start again. This time during the install, change Program Files (x86) to Program Files ... click next-next-next, but do not reboot. Check to see if you are running either Microsoft Security Essentials or System Centre Endpoint Protection ... if so, exclude C:\Program Files\Cisco Systems from scanning.

screenshot

Then Reboot.

With a little bit of luck, old yellow should run like a youthful puppy.

Cisco ISE - Registration Authority Response Invalid

$
0
0

This is a good one where Android devices will provision but Apple iOS will not.... and it only happens with Publicly Signed Certificates (installed on the ISE PSN).

As per the screenshot, the iPhone profile installation fails with the error Profile Installation Failed and The Registration Authority's response is invalid.

Check to see if your certificate has a Digicert chain. See Cisco Bug CSCul69023. Take a look at the work around:

OpentheISEadminGUIwithFirefox,Viewthecertificate,thechain,clickon"DigiCert High Assurance EV Root CA"ExportitandthenimportitonISECertificateStore

Nice, init? If you imported your certificate using the Root Chain from Internet Explorer then the iPhone complains, it needs a specific root CA.

Running Cisco ISE (1.4) in VirtualBox

$
0
0

I've been meaning to do this for a while, but I've finally hackedCisco ISE into VirtualBox for home lab learning and experimentation.

For those familiar with my ACS in VirtualBox post you should notice a very similar theme.

  1. Copy the .iso to a Web server directory that allows page indexing
  2. Hack the KickStart file (ks.cfg) to remove Cisco's hardware checks
  3. Boot the install CD using the custom ks.cfg

As before, I use the web installation method because it's the easiest way to hack/test/boot multiple times when you're trying to work out why the installer doesn't run... Also I will not be providing you an ISO file to download.

Web Server Configuration (nginx)

First, I mounted ise-1.4.0.253.x86_64.iso and copied the whole CD to ~/public_html/ise

Next, I need to expose this directory to the web server. I'm using nginx on CentOS... it's nice and easy, I added this to my config.

location /ise {
    root /home/nick/public_html/;
    autoindex on;
}

Replace ks.cfg

When you copy the contents of the CD to the local file system you'll notice all files have the RO flag set. Fix with chmod +w ~/public_html/ise/ks.cfg

There are a few things in the file you need to change:

  1. Replace cdrom on line 10 with url --url http://192.168.10.122/ise/ (replace 192.168.10.122 with the IP of your web server)
  2. Optional, replace the encrypted root password with a new one rootpw CISCO_ise_p455w0rd on line 12
  3. Comment out with a # any /sbin/halt -f statements to stop error messages from halting the installation
  4. Replace any cars_udi_util statements with your own versions, so...
UDI_PID=`/sbin/cars_udi_util -p`
UDI_VID=`/sbin/cars_udi_util -v`
UDI_SN=`/sbin/cars_udi_util -s`

becomes...

UDI_PID="Cisco-VM-SPID"
UDI_VID="1.0"
UDI_SN="123456789"

... and just for good measure, after validate_hwinfo(){ insert (on a new line) UDI_PID="Cisco-VM-SPID" to force hardware selection.

If you want, you can ignore all of that and just use my ks.cfg

VirtualBox Configuration

  • CPU - 4
  • RAM - 8Gb
  • Hard Disk - SCSI - 100Gb (thin space allocation)
  • CDRom - ise-1.4.0.253.x86_64.iso
  • NIC 1 - Bridged
  • NIC 2 - Host Only (disconnected)

All other defaults left alone.

Boot the custom install

Boot the virtual machine from the Cisco ISO, but DO NOT select 1,2,3 or 4. Instead type:

vmlinuz text ks=http://192.168.10.122/ise/ks.cfg initrd=initrd.img

...replacing 192.168.10.122 with your web server IP.

custom ise boot

Wait, See, Enjoy!

With a little luck, the VM will load your custom KickStart file and begin the install.

If you tail your web server access logs, you should see stuff like:

192.168.10.116 - - [30/Jun/2015:18:50:49 +0100] "GET /ise/Packages/CARSCmdSched-2.0cars-1.x86_64.rpm HTTP/1.1" 200 28353 "-" "Cisco Identity Services Engine (anaconda)/1.3" "-"
192.168.10.116 - - [30/Jun/2015:18:50:49 +0100] "GET /ise/Packages/CARSICMPUtil-2.0cars-1.x86_64.rpm HTTP/1.1" 200 11425 "-" "Cisco Identity Services Engine (anaconda)/1.3" "-"
192.168.10.116 - - [30/Jun/2015:18:50:49 +0100] "GET /ise/Packages/CARSSysMon-2.0cars-1.x86_64.rpm HTTP/1.1" 200 34919 "-" "Cisco Identity Services Engine (anaconda)/1.3" "-"
192.168.10.116 - - [30/Jun/2015:18:50:49 +0100] "GET /ise/Packages/libdrm-2.4.39-1.el6.x86_64.rpm HTTP/1.1" 200 119408 "-" "Cisco Identity Services Engine (anaconda)/1.3" "-"
192.168.10.116 - - [30/Jun/2015:18:50:49 +0100] "GET /ise/Packages/plymouth-0.8.3-27.el6.centos.x86_64.rpm HTTP/1.1" 200 91056 "-" "Cisco Identity Services Engine (anaconda)/1.3" "-"
192.168.10.116 - - [30/Jun/2015:18:50:50 +0100] "GET /ise/Packages/rsyslog-5.8.10-6.el6.x86_64.rpm HTTP/1.1" 200 663780 "-" "Cisco Identity Services Engine (anaconda)/1.3" "-"
192.168.10.116 - - [30/Jun/2015:18:50:50 +0100] "GET /ise/Packages/cronie-anacron-1.4.4-7.el6.x86_64.rpm HTTP/1.1" 200 29768 "-" "Cisco Identity Services Engine (anaconda)/1.3" "-"

installing

At the end of the install the VM should reboot into the normal setup login screen allowing you to complete the setup parameters

The setup will take ages, well over the 15/20mins that Cisco suggest but once it completes and reboots you should find you have a working ISE to play with.

... well, for 90days until the eval lic runs out!

ISE 1.4 running in VirtualBox

Multi-Context HTTPS backups of Cisco ASA Script

$
0
0

If look in the Cisco forums for scripts to backup ASAs you'll find various SSH / Expect , complicated examples... not sure why since in 2006 I showed it can be done with a single wget command ;-)

Recently I needed something that would support Multi-Context firewalls, so I pimped my one line command into the below shell script.

Copy/paste into a new file as backup_cisco_asa.sh then chmod 700 the file as necessary.

Run the file with no options ./backup_cisco_asa.sh and it'll ask you for IP address, username and password to make the connection.

For this to work the ASA needs appropriate HTTP statements (i.e. allow ASDM access from where you are running the script)

The file supports in-line backup of a single device such as ./backup_cisco_asa.sh 10.10.10.10

Multi-context support is via an environment variable or a config file ~/.asa_config. You must set an array containing entries for each context you want to backup. e.g.

ASA_CONTEXTS=( 
 "172.31.9.10:system"
 "172.31.9.10:admin"
 "172.31.9.10:Edge"
 "172.31.2.254:system"
 "172.31.2.254:admin"
 "172.31.2.254:Core" )

If you're feeling insecure you can also save your username/password variables into the ~/.asa_config as ASA_UID and ASA_PW respectively (or as environment variables)

Given that the script is a bash shell script I assume that SCP isn't required (because you are probably already on your linux SSH/SCP server running the script) but to keep the router team happy you might need to copy the files up via TFTP, this can be set with the ASA_TFTP_IP variable in ~/.asa_config.

By default the backup files will be saved to ./ (i.e. where ever you run the script from) and you can change that with the ASA_FILEPATH variable.

backup_cisco_asa.sh

  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
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/bin/bash# Nick Bettison - LINICKX.com - 2015 - v1# Bash Shell Scipt for backing up Cisco ASA's via HTTPS (i.e. ASDM)# # Read the file comments, you can setup a config file ~/.asa_config to store variables.# ASA_UID & ASA_PW for credentials (if you're feeling insecure)# ASA_CONTEXTS for multi-context support# and ASA_TFTP_IP for copying the files via TFTP (for insecure router boys)## Tested on.# Cisco Adaptive Security Appliance Software Version 9.2(3)4 <context># Device Manager Version 7.4(2)# Timestamp for file namesTIMESTAMP=`date "+%Y%m%d-%H%M%S"`# Allow single ASA IP address to be passed from CLI# e.g ./backup_cisco_asa.sh 10.10.10.10if[ -n "$1"]thenASA_IP="$1"fi# Check for Curltype curl >/dev/null 2>&1||{echo>&2"I require curl but it's not installed.  Aborting.";exit 1;}# Read Variables from a config file (if it exits)# The config file can be used for storing multi-context configurations... and for the insecure username/password ;-)if[ -e ~/.asa_config ]then
  . ~/.asa_config
fi# Default File Pathif[ -z "$ASA_FILEPATH"]thenASA_FILEPATH="./"fi# Check for UID/PW Variables - Ask if not foundif[ -z "$ASA_UID"]thenread -p "ASA Username:" ASA_UID
fiif[ -z "$ASA_PW"]thenread -s -p "ASA Password:" ASA_PW
        echofi# Check to see if single or multi-context mode.if[ -z "$ASA_CONTEXTS"]thenif[ -z "$ASA_IP"]thenread -p "ASA IP Address:" ASA_IP
        fiASA_tFILE="$ASA_FILEPATH.$TIMESTAMP.asaconfig.txt"# Download the "show run" via the unofficial CLI.
        curl -s -k -o $ASA_tFILE -u $ASA_UID:$ASA_PW"https://$ASA_IP/admin/exec/show%20running-config%20asdm/show%20running-config"if[ -e $ASA_tFILE]then# Look for hostname in config fileASA_HOSTNAME=`grep ^hostname $ASA_tFILE| awk '{print $2}'`# rename the temp file to something sensible.
            mv $ASA_tFILE"$ASA_FILEPATH$TIMESTAMP.$ASA_HOSTNAME.txt"# Setup an array for TFTP later.ASA_FILES=("${ASA_FILES[@]}""$ASA_FILEPATH$TIMESTAMP.$ASA_HOSTNAME.txt")# Done.echo"DONE: $ASA_FILEPATH$TIMESTAMP.$ASA_HOSTNAME.txt"elseecho"FAILED: $ASA_IP"exit 1
        fielse# Example ASA_CONTEXTS array:# 172.31.9.10 is the admin context IP, admin & Edge are the names of the two contexts to backup.# 172.31.2.254 is the admin context IP, admin & Core are the names of the two contexts to backup.# "system is obviously the system context"# ASA_CONTEXTS=( #     "172.31.9.10:system"#     "172.31.9.10:admin"#     "172.31.9.10:Edge"#     "172.31.2.254:system"#     "172.31.2.254:admin"#     "172.31.2.254:Core" )# Loop through the arrayfor firewall in ${ASA_CONTEXTS[@]};doASA_IP=${firewall%%:*}ASA_CONTEXT=${firewall##*:}# Feedback on progressprintf"Connecting to %s for %s \n"$ASA_IP$ASA_CONTEXT# FilenameASA_FILE="$ASA_FILEPATH$TIMESTAMP.$ASA_IP.$ASA_CONTEXT.txt"# Download the CONTEXT "show run" via the unofficial API.
         curl -s -k -o $ASA_FILE -u $ASA_UID:$ASA_PW"https://$ASA_IP/admin/exec/changeto%20context%20$ASA_CONTEXT/show%20running-config/show%20running-config%20asdm"if[ -e $ASA_FILE]then# Setup an array for TFTP later.ASA_FILES=("${ASA_FILES[@]}""$ASA_FILE")# Done!echo"DONE: $ASA_FILE"elseecho"FAILED: $ASA_IP"fidonefi# Optional Backup to insecure tftp - you know, to keep the router boys happy!if[ -n "$ASA_TFTP_IP"]then# Check for TFTP binarytype tftp >/dev/null 2>&1||{echo>&2"tftp client not installed.  Aborting.";exit 1;}type wc >/dev/null 2>&1||{echo>&2"wc not installed (needed for counting stuff).  Aborting.";exit 1;}type awk >/dev/null 2>&1||{echo>&2"awk not installed.... seriously?!?!  Aborting.";exit 1;}# Loop through arrayfor file in ${ASA_FILES[@]};doLOCAL_FILE=$file# backup separatorOIFS=$IFS# Change separator to /IFS='/'# Split the filename from the pathAWK_POSITION=`echo$file| wc -w`REMOTE_FILE=`echo$file| awk -v w=$AWK_POSITION'{print $w}'`# restore separatorIFS=$OIFS# TFTP the file.
        tftp -v $ASA_TFTP_IP -c put $LOCAL_FILE$REMOTE_FILEdonefi

checking if python is running via ssh

$
0
0

Sometimes it's nice when something is much easier than you expected. I have a few cobbled together python scripts for speeding things up, one in particular I have on my home pc which I wanted to work out if am I running it locally or if I have SSH'd in... below is the surprising simple example!

1
2
3
4
5
6
7
8
9
#!/usr/bin/env pythonimportostry:os.environ["SSH_TTY"]print("SSH Connection Detected")except:print("Running Locally")

You could also test the SSH_CLIENT variable as well, but this was good enough for me.

Enjoy!

Cisco CCNP Security


CentOS7 - syslog-ng: Error setting capabilities, capability management disabled; error=Operation not permitted

$
0
0

I've just installed syslog-ng from epel onto a test CentOS7 box and found that the service wouldn't start, a quick verify of my syslog-ng.conf, with syslog-ng -s came back like so...

syslog-ng:Errorsettingcapabilities,capabilitymanagementdisabled;error='Operation not permitted'

The debain fix suggests something like: syslog-ng -no-caps -s, which seems to work. What is odd is that /usr/lib/systemd/system/syslog-ng.service doesn't have it, but the service still seems to work once you've fixed and syntax errors!

Cisco CMNA

Travis-CI and Dynamips a cloud router for testing scripts against Cisco IOS

$
0
0

Crassh build status

I think I have started to get my head around unit tests for CRASSH; recently my initial implementation of paramiko's “ssh_session.recv_ready" was ballsed up, python3 was forgiving python2 would bork, creating an issue for many. My first unit test was a basic "print" which I ran on Travis-CI against both python2 and python3 if the build passed then syntax checking for both versions would pass, nice!

Unit tests that check the internal functions of CRASSH are all well and good, but the purpose of the script is to log into routers and do stuff, so I really wanted to spin up a router and check the script against that.

Travis-CI's infrastructure comes in two flavors, Standard and Container Based, which essential boils down to one that allows sudo and one that doesn't*; using the standard environment I have managed to spin up a dynamips router for testing CRASSH against.

If you take a look at my .travis.yml, I'll step you through how this works:

sudo:required

By default all builds are Container Based, this forces the Standard build.

 python:
- '2.6'
- '3.5'

Currently tests all run on linux, I plan to add OSX tests in the future but here we instruct Travis-CI to perform the tests twice, once against each version.

before_install:
- ifconfig -a
- sudo /sbin/modprobe tun
- sudo apt-get update -qq
- sudo apt-get install -qq dynamips

The first thing I do is prepare the OS, the ifconfig -a is for troublehooting so I can see the network stack before I start; then I install the Tun/Tap kernel driver, update the OS and install dynamips.

 install:
- pip install .
- pip install paramiko

Next I install CRASSH onto Travis-CI and it's dependency paramiko. The pip install . basically reads setup.py

Now all the dependencies are installed, the router needs to be loaded...

before_script:- wget -q $IOS_URL- ls -l- sudo dynamips -s 0:0:tap:tap0 -P 3725 -T 2001 --idle-pc=0x607081e0 -C tests/r1.txt c3725-advsecurityk9-mz.124-25c.bin &- sleep 90- sudo ifconfig tap0 inet 1.1.1.1 netmask 255.255.255.252- ifconfig -a- ping -c 4 1.1.1.2

$IOS_URL is a secure variable so that charlatan's cannot download the Cisco IOS; so wget downloads the IOS from my secret location and dynamips starts up (and backrounds, note: &).

Once dynamips is running we wait 90secs to give time for the router to boot, we configure an interface to connect to the router with sudo ifconfig tap0 and I ping it to make sure it works.

Now that the router is running, standard python unit tests start with script: py.test --cisco

Inside the test config you'll see that --cisco is an optional switch that runs test_cisco_shver inside test_crassh.py.

The magic of test_cisco_shver is that dynamips was booted with the config in r1.txt the test logs into the r1 router and compares a show ver to an expected output if they match (line for line) then the test passes and Travis-CI shuts everything down; if the test fails I get notified.

Status of builds can be reviewed on the CRASSH Travis Page: https://travis-ci.org/linickx/crassh or is shown in the readme.

[*] I have an issue logged to see if this could be done on a Container Based server

Alpine Linux Raspberry Pi and Wireless (WiFi) firmware

$
0
0

Pidora doesn't appear to be being maintained anymore and CentOS/Fedora support for the Pi appears to be focused on the version 2 hardware, so I've been looking for an alternative distro. I'm very early on in my experimentation with docker, and docker is not in anyway related to my Pi, but since the unofficial announcement that they were moving away from Ubuntu to to Alpine Linux, I thought that's was as good a distro to try as any... funny how we're influenced by the media.

The Alpine Linux Raspberry Pi install guide is insanely easy, unpack the files onto a single disk partition, no fricking around with partitions, no dd just unpack and boot! The Alpine WiFi guide isn't bad either but IMHO isn't complete as I couldn't start the wpa_supplicant service:

pi # /etc/init.d/wpa_supplicant start
 * Starting WPA Supplicant Daemon ...
Successfully initialized wpa_supplicant
Could not set interface wlan0 flags (UP): Resource temporarily unavailable
nl80211: Could not set interface 'wlan0' UP
nl80211: deinit ifname=wlan0 disabled_11b_rates=0
wlan0: Failed to initialize driver interface
 * start-stop-daemon: failed to start `/sbin/wpa_supplicant'
 * Failed to start wpa_supplicant
 * ERROR: wpa_supplicant failed to start
pi #

A quick poke at /var/log/messages reveals that the service is missing firmware:

kern.info kernel: [33264.393174] ieee80211 phy0: rt2x00lib_request_firmware: Info - Loading firmware file 'rt2870.bin'
kern.warn kernel: [33264.393356] rt2800usb 1-1.4:1.0: Direct firmware load for rt2870.bin failed with error -2
kern.warn kernel: [33264.393377] rt2800usb 1-1.4:1.0: Falling back to user helper
daemon.err /etc/init.d/wpa_supplicant[2101]: start-stop-daemon: failed to start `/sbin/wpa_supplicant'
kern.err kernel: [33264.423493] ieee80211 phy0: rt2x00lib_request_firmware: Error - Failed to request Firmware
daemon.err /etc/init.d/wpa_supplicant[2083]: ERROR: wpa_supplicant failed to start

The USB WiFi Adapter I purchased has a lot of reviews saying "it just works" on various Pi distro's and it worked fine in pidora, so I figured that this driver was probably something generic. A few googles later and I find the Linux Kernel Firmware page and I find a copy of rt2870.bin which I place in /lib/firmware/.

After a little /etc/init.d/wpa_supplicant restart I have working WiFi!

The alpine documentation is clear, on a Pi the install is in disk-less mode and forces everything into memory, therefore I'm going to loose the firmware after a reboot. To make the change persistent, run lbu include /lib/firmware/rt2870.bin;lbu commit... give it a reboot, and cross your fingers!

pip install crassh

$
0
0
atom screenshot

Recently myself (and a maybe colleague or two) has been copy/pasting parts of C.R.A.SSH (crassh) my python script for automating commands on Cisco IOS devices into personal scripts to get something done; knowing there must be a better a way I decided to turn crassh into a module which can/should be easy to install on linux or OSX systems with pip. PIP is a python (cross platform) package manager that now crassh is available in, i.e. pip install crassh

Below is an output from my machine, as you can see pip will install any necessary dependencies:

$ pip install crassh
Collecting crassh
  Downloading CraSSH-2.02.tar.gz
Collecting paramiko>=1.10 (from crassh)
  Using cached paramiko-1.16.0-py2.py3-none-any.whl
Collecting pycrypto!=2.4,>=2.1 (from paramiko>=1.10->crassh)
Collecting ecdsa>=0.11 (from paramiko>=1.10->crassh)
  Using cached ecdsa-0.13-py2.py3-none-any.whl
Building wheels for collected packages: crassh
  Running setup.py bdist_wheel for crassh
Successfully built crassh
Installing collected packages: pycrypto, ecdsa, paramiko, crassh
Successfully installed crassh-2.2 ecdsa-0.13 paramiko-1.16.0 pycrypto-2.6.1$

I'm about to start work on some proper documentation , but to get you started there are four functions that most people will want/use:

  • crassh.connect()
  • crassh.send_command()
  • crassh.disconnect()
  • crassh.readtxtfile()

The first three are self explanatory, the last one is very useful as it'll read in a plain text file (one line at at time) and use it as an array, typically the plain text file would be a list of IP address to connect to or a list of commands to execute.

To show how crassh can be used, below is a simple example to audit to switches for the SNMP community string public - A security no-no!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python# coding=utf-8importcrassh# Variablesrouters=["10.159.83.135","10.159.83.136"]username="nick"password="nick"# Loopfordeviceinrouters:hostname=crassh.connect(device,username,password)output=crassh.send_command("show run | inc snmp-server community",hostname)crassh.disconnect()# Split the output by spaces so we can search the responsewords=output.split()# Look for "public" in the outputforxinwords:ifx=="public":print("DANGER: Public SNMP Community set on %s [%s]"%(hostname,device))

I've saved the file as no_public.py and this is the response...

$ python no_public.py
Connecting to 10.159.83.135 ...
Connecting to 10.159.83.136 ...
DANGER: Public SNMP Community set on r2 [10.159.83.136]$

Obviously you could do a lot more than just output but hopefully this'll give you an idea.

NOTE: Instead of routers being an array, I could have done routers = crassh.readtxtfile("./routers.txt") where routers.txt was a plain text file with one IP address per line.

Automated Let's Encrypt Certificates

$
0
0

Last month I was very pleased that I had managed an automated Let's Encrypt certificate renewal; the other night the renewal broke as the certificate was issued from a different intermediate CA, so help others out I thought I'd share with you my cron script.

Before copy/pasting this script, you need to get started with tiny acme. I also recommend you read this post by Scott Heleme as it walks through the end-to-end process.

Once you're all setup, you can use something like the below script on a monthly basis (update paths for your environment and the email address):

 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
42
43
44
45
46
47
#!/bin/bashecho"----------------------"echo"Start:"`date`# Backup
cp -v /home/letsencrypt/priv/signed.crt /home/letsencrypt/priv/old/signed_$(date +%F).crt
cp -v /home/letsencrypt/priv/chained.pem /home/letsencrypt/priv/old/chained_$(date +%F).crt# Renewal
python /home/letsencrypt/bin/letsencrypt_tiny.py --account-key /home/letsencrypt/priv/my.key --csr /home/letsencrypt/priv/my.csr --letsencrypt-dir /home/letsencrypt/challenges/ > /home/letsencrypt/priv/signed.crt# Find IssuerISSUER=`openssl x509 -noout -issuer -in /home/letsencrypt/priv/signed.crt | awk 'NF>1{print $NF}'`echo"Certificate issued by $ISSUER"case$ISSUER in
    X1)ISSUER_CERT="https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem";;
    X2)ISSUER_CERT="https://letsencrypt.org/certs/lets-encrypt-x2-cross-signed.pem";;
    X3)ISSUER_CERT="https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem";;
    X4)ISSUER_CERT="https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem";;
    *)echo -e "Undefined Intermediate CA - Please fix /home/letsencrypt/bin/letsencrypt.sh - Failed to match Intermediate CA $ISSUER not found"| mail -s "LE Renewal Error""changeme_at_gmail_dot_com"echo"** Error: Failed to match Intermediate CA $ISSUER not found **"
        cp -v /home/letsencrypt/priv/old/chained_$(date +%F).crt /home/letsencrypt/priv/chained.pemexit;;esac# Download Intermetdiate CA Certecho"Cert URL: $ISSUER_CERT"
wget -O - $ISSUER_CERT> /home/letsencrypt/priv/intermediate.pem# Build Chain
cat /home/letsencrypt/priv/signed.crt /home/letsencrypt/priv/intermediate.pem > /home/letsencrypt/priv/chained.pem# Restart nginx to install the cert
sudo service nginx reloadecho"End:"`date`

Things to note if the renewal breaks:

  1. It doesn't retry. Look at adding this smart renewal script to your daily cron: https://github.com/ScottHelme/Lets-Encrypt-Smart-Renew/
  2. It emails you and puts the old certificate chain back (then quits)

SSH Server on Windows, the Microsoft Way

$
0
0

An SSH server for windows, it's the kind of thing only a Linux/OSX user would ask for. The current defacto standard is Cygwin but if you fancy something a bit more native, something a bit backed by Microsoft then take a look at PowerShell/Win32-OpenSSH on github.

Installation is quite straight forward:

  1. Download the latest release make sure you correctly select 32bit or 64bit
  2. Create a folder, C:\Program Files\OpenSSH-Win32 and extract the contents there.
  3. Start Powershell as Administrator - cd 'C:\Program Files\OpenSSH-Win32'
  4. Setup SSH host keys (this will generate all the 'host' keys that sshd expects when its starts) - .\ssh-keygen.exe -A
  5. Enable key-based auth - .\install-sshlsa.ps1
  6. Reboot (well it is windows!)
  7. Start Powershell as Administrator again - cd 'C:\Program Files\OpenSSH-Win32'
  8. Install and run daemon as NT Service running as Local System - .\install-sshd.ps1
  9. Start the service - Start-Service sshd
  10. Make the service start on boot - Set-Service sshd -StartupType Automatic

If you have a problem running step 5 you might need to run Set-ExecutionPolicy Unrestricted; if you do disable this security, switch it back on when you're finished Set-ExecutionPolicy RemoteSigned (or whatever).

Also, don't forget to allow tcp/22 through any firewalls, either network or host based.

You'll probably want to enable SFTP, the server that is.

Edit C:\Program Files\OpenSSH-Win32\sshd_config in your favorite text editor and replace this:

# override default of no subsystems
#Subsystem  sftp    /usr/libexec/sftp-server
Subsystem   sftp    /win32openssh/bin/sftp-server.exe
Subsystem   scp /win32openssh/bin/scp.exe

with

# override default of no subsystems
#Subsystem  sftp    /usr/libexec/sftp-server
#Subsystem  sftp    /win32openssh/bin/sftp-server.exe
Subsystem   sftp    c:\PROGRA~1\OPENSS~1\sftp-server.exe
#Subsystem  scp /win32openssh/bin/scp.exe

Notice for program files and openssh-win32 I'm using the short path, you can find those using cmd.exe and using dir /x.

Your first login, from a Linux/OSX/nix machine

Ok, so this is where it gets a little odd. For your username you need SamAccountName@fqdndomain, as there is an @ in there you need to use the -l switch on ssh. Which means you have to do something like ssh -l nick.bettison@company.local mypc.company.local with a little luck that'll give you this...

linickx:~ $ ssh -l nick.bettison@company.local mypc.company.local
ssh -l nick.bettison@company.local@mypc.company.local's password:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

nick.bettison@company.local@MYPC C:\Users\nick.bettison\Documents>

If your PC is standalone (workgroup) you can use normal ssh syntax, either ssh user@pc.local or ssh -l user pc.local.

Connecting with SFTP

On a domain PC, SFTP probably won't work because there is no -l, as a workaround on my nix machine I added the following to my ~/.ssh/config file:

Host mypc
        Hostname mypc.company.local
        User nick.bettison@company.local

Which should work like this...

linickx:~ $ sftp mypc
nick.bettison@company.local@mypc.company.local's password:
Connected to mypc.
sftp> pwd
Remote working directory: /C:/Users/nick.bettison/Documents
sftp>

To enable public key authentication

Edit C:\Program Files\OpenSSH-Win32\sshd_config in your favorite text editor (again) and replace this...

#RSAAuthentication yes
#PubkeyAuthentication yes

with

RSAAuthentication yes
PubkeyAuthentication yes

NOTE: Public key auth doesn't seem to work with domain PCs.

I tested on a standalone (non-domain) windows7 PC and it worked fine, but on a domain PC at work it fails with the following server side error message.

Cannot logon using LSA package (err = 1300, ntStat = c0000041).

Github Issue 87 seems to imply that this is group policy related, if it is, as yet I haven't figured out which one. The other reason this might not work is username interpretation, local users are "username" where as domains are "username@domain" so I wonder if the LSA .DLL is looking in the wrong place; I will update here if I find a solution.


Monitor for Fake Certificates with Certificate Transparency

$
0
0

Certificate Transparency (CT), is an open, public, Certificate Authority monitoring system. More info available over at certificate-transparency.org.

iOS CT Notification

The CT web site sights a couple of examples where CAs have failed, either through compromise or mistake, but recently Facebook caught fake certificates where there was no fault of the CA, which lead me to think... How can I take advantage of this? How would I know if someone issued a certificate for linickx.com?

Google have open-sourced a whole bunch of CT stuff, but it looks over kill for my needs. I found a CT Monitor on github but it's just a database that not only needs hundreds of GB of storage, but a front end to make it useful. ct_advisor, also on github, looks a more complete but still way to much investment for my liking... however the author is providing a hosted version which is a possibility if you like email alerts.

To take advantage of CT, I have opted for Crt.sh mixed with IFTTT.

The Comodo Crt.sh service supports an query-able RSS feed, for example https://crt.sh/atom?q=linickx.%25.

IFTTT supports a Feed Channel that can consume the feed from Crt.sh and then do something. In my case, I opted for a mobile notification... I've published the recipe for others to use:

Just change the feed URL (or change the action) and you're set!

OSX: How to install the Microsoft Fonts

$
0
0

I've recently had to rebuild my laptop and needed to setup M$ fonts for work. The top hit for installing fonts is a stack exchange thread pointing to a 3rd Party download, given that I knew that office came with the fonts, I just needed to figure where they were.

Assuming you don't have MS office installed, here's a quick 4 step install....

-- If you do have office, start at 3

  1. Install Cask
  2. Install Microsoft Office brew cask install microsoft-office
  3. Make a directory: mkdir ~/Library/Fonts/Microsoft
  4. Copy the fonts: cp -av /Applications/Microsoft\ Word.app/Contents/Resources/Fonts/* ~/Library/Fonts/Microsoft/

Enjoy!

Introducing snsync, an rsync client for Simplenote

$
0
0
snsync

I'm a big fan of Simplenote, the iOS app is great but the OSX app, not so much. I had been using nvAlt as a client as it supports all the features that the official client does plus it allows you to take a plain text copy locally which can be opened with an external editor (like atom). The issue I had with this approach was that if you made a change on your phone, you had to open and sync with nvAlt prior to editing the local text file which sometimes can catch you out and create conflicts.

I wanted to create my own solution where I could manually (and schedule with cron) a sync of my local text files and Simplenote. I've been running this for a few weeks now, most of the bugs are squashed, so here we have it snsync !

Installation

At the moment there is no packaging, so either download the latest release or use git:

$git clone https://github.com/linickx/snsync.git

Once unpacked, you'll need a configuration file. By default, you need ~/.snsync but the command line options do allow to select another file, the minimal info needed is a username and password:

    [snsync]
    cfg_sn_username = me@here.com
    cfg_sn_password = secret

IMPORTANT! Protect your .snsync file with the correct permissions and disk encryption.

Usage

Usage is simple... The following options are available:

    $./snsync -h

    Usage: snsync [OPTIONS]

    OPTIONS:
     -h, --help         Help!
     -d, --dry-run      Dry Run Mode (no changes made/saved)
     -s, --silent       Silent Mode (no std output)
     -c, --config=      Config file to read (default: ~/.snsync)
    $

For example: just snsync on it's own should work, but something like this can be used for cron: snsync -s --config=something.txt

I'm using this against my Simplenote store of about 1,000 notes, the first full sync will take a long time (mine -> approx 15mins) you will also find a high number of HTTP ERRORS reported, just wait and re-run the script, missed notes will be downloaded.

NOTE The --silent switch will run quicker, that's due to a delay needing to be added for proper console output.

No warranty is offered, use this at your own risk; I use this for my "production" notes but I always keep backups. The recommended approach is to manually download all your notes for a backup, then use the --dry-run option to observe changes until you are happy.

Enjoy!

If you have any issues or questions, please raise them on github, pull requests are welcome, I've already opened a few issues to show the next features/things I'd like to do.

Apple Magic Mouse - Fixing Windows 10 scrolling

$
0
0

If you're a fan of Apple's Magic Mouse you can use it on Windows, however after pairing via Blue Tooth (the code is0 0 0 0) you'll find that the touch scrolling doesn't work.

It's easily fixed however,

  1. Download Boot Camp Support Software and unzip, in my case that was unzipping BootCamp5.1.5621.zip.
  2. Open the folder \BootCamp5.1.5621\BootCamp\Drivers\Apple\ and install AppleWirelessMouse64.exe.
  3. Switch the mouse off & on and you're done.
iAppleWirelessMouse64

Happy Scrolling!

Ansible Cisco - Primer 1 - Hello World!

$
0
0

Anisble documentation or examples for Cisco devices appear to be a bit hit-n-miss, so I'm documenting my "Hello World Primer" with hope it'll be helpful to others; as this is quite long it will be two posts, one for getting started with a simple "show clock" and a 2nd for making changes. Part two making changes is available here.

TLDR; Some example files are on github: https://github.com/linickx/ansible-cisco

To get started, you need ansible installed on your Laptop/PC, I'm running OSX with homebrew so installation is a simple brew install ansible.

Getting Started - A sane ansible.cfg

Once anisble is installed, the first thing you need an inventory/hosts's file... a lot of the linux examples will get you to start fiddling about with /etc/ansible, firstly this folder doesn't exist on OSX and secondly this is a bad idea on linux as this is a system wide change.

IMHO a better start is to create an ansible directory in your home: mkdir ~/ansible;cd ~/ansible
In your personal ansible directory, create ansible.cfg; in this file you can set a local inventory file and some sane defaults, mine looks like this:

linickx:ansible$catansible.cfg[defaults]hostfile=./inventory.txtretry_files_enabled=Falsetimeout=5host_key_checking=False#log_path=./log.txtlinickx:ansible$

As you can see I have a few other thing set, firstly my local hosts file (inventory.txt) and secondly ansible fails it creates a local retry file, I don't want these. Timeout is ssh timeout, use whatever you like, something between 1 and 10 works for me.

host_key_checking has security implications. The above is set to False because this is my personal test machine, in Production I would set this to True as I want to know if an SSH MitM is happening.

Finally, notice the #, this is a comment; I have commented out the log_path directive, if you enable it, ansible will log all screen output to a file, useful for searching for something instead of scrolling through your terminal.

The Inventory File - Your personal list of devices

The inventory defines the devices you want to manage, anisble expects all devices to have resolvable FQDNs, which is unlikely in most enterprises for Cisco devices, if you're a fan of remembering IP addresses you can have a simple list of IP's but if you're like me an like to know the names of devices you can do something like this...

linickx:ansible$catinventory.txt[all:vars]#OSX/Homebrewhack,asIhavepython3installed.ansible_python_interpreter=/usr/local/Cellar/python/2.7.13/bin/python2.7[ios_devices]r1ansible_host=10.10.10.135r2ansible_host=10.10.10.136[ios_devices_enable]r3ansible_host=10.10.10.137linickx:ansible$

In my inventory file, the [] are group names, I have two custom groups [ios_devices] and [ios_devices_enable], you can call these anything you want, my naming structure will make more sense as this post continues.
All devices belong to a default [all] group that doesn't need to be defeined in the file, but in my config file I have [all:vars] this means: set the following variables for the all group; I have python3 installed for my other python projects, so ansible_python_interpreter is a hack to point ansible to the correct version of python (Python 3 is not supported - yet - for ansible)
For each device listed in my file (r1,r2,r3, etc) I have ansible_host set to an IP address, that's because my test devices do not have resolvable FQDNs.

Hello World! ... or Show Clock play

Ansible is primarily about Play Books, a Play Book is a list of tasks (instructions) that you want to perform on one or many devices; the idea is that you create repeatable plays to standardise configuration and such in your environment.

For my Hello World! example, I'm not going to make a change but show you how to run show clock on many devices (using the ios_command module), in ansible world this is a play.
Start by creating a file called show_clock.yml with the following contents ( including the first --- ):

---- hosts: ios_devices*  gather_facts: no  connection: local  tasks:  - name: Include Login Credentials    include_vars: secrets.yml  - name: Define Provider    set_fact:      provider:        host: "{{ansible_host}}"        username: "{{creds['username']}}"        password: "{{creds['password']}}"  - name: RUN 'Show Clock'    ios_command:      provider: "{{provider}}"      commands:        - show clock    register: clock  - debug: var=clock.stdout_lines

This playbook has three tasks: 1. Include Login Credentials, i.e. Read login credentials from a file 2. Define Provider, i.e. Use the credentials in something called a "fact" that is named "provider" 3. Run show clock

Read login credentials from a file

You'll need a credential file, so create secrets.yml with contents like this (update as appropriate):

---
creds:
  username: nick
  password: my_password
  auth_pass: my_enable

Something called a "fact" that is named "provider"

The provider is what tells ansible how to connect to a device, all networking equipment needs one, so the provider includes the ip address and credentials, a fact is a device specific variable, so this task is assigning connectivity details to the device. Anything inside {{ }} is a variable.

Run show clock ...

To execute the Play Book or play, you use the ansible-playbook command, like this...

linickx:ansible$ansible-playbookshow_clock.ymlPLAY[ios_devices*]************************************************************TASK[IncludeLoginCredentials]***********************************************ok:[r1]ok:[r2]ok:[r3]TASK[DefineProvider]*********************************************************ok:[r2]ok:[r1]ok:[r3]TASK[RUN'ShowClock']********************************************************ok:[r1]ok:[r3]ok:[r2]TASK[debug]*******************************************************************ok:[r1]=>{"clock.stdout_lines":[["18:58:24.812 UTC Mon Mar 27 2017"]]}ok:[r2]=>{"clock.stdout_lines":[["18:58:23.490 UTC Mon Mar 27 2017"]]}ok:[r3]=>{"clock.stdout_lines":[[".18:58:25.064 UTC Mon Mar 27 2017"]]}PLAYRECAP*********************************************************************r1:ok=4changed=0unreachable=0failed=0r2:ok=4changed=0unreachable=0failed=0r3:ok=4changed=0unreachable=0failed=0linickx:ansible$

What happened there then?!

In my ansible-playbook show_clock.yml you'll see the three tasks ran against three routers; in my show_clock.yml the first line hosts: ios_devices* says run against any wildcard group, starting with ios_devices, which in my inventory.txt is both ios_devices and ios_devices_enable.

Notice how there where four tasks not three, the -debug entry was an unnamed task which simply outputs the results of the previous task :)

But storing credentials in a file is INSECURE!!

Anyone that's been on linickx.com before will find that example of storing a username/password in a plain text file highly out of character, so lets look at how to prompt for the credentials instead; create show_clock_prompt.yml with the following:

---- hosts: ios_devices  gather_facts: no  connection: local  vars_prompt:  - name: "mgmt_username"    prompt: "Username"    private: no  - name: "mgmt_password"    prompt: "Password"  vars:    provider:      host: "{{ansible_host}}"      username: "{{mgmt_username}}"      password: "{{mgmt_password}}"  tasks:  - name: RUN 'Show Clock'    ios_command:      provider: "{{provider}}"      commands:        - show clock    register: clock  - debug: var=clock.stdout_lines

Notice a few changes, firstly no *, this play will be run just against one inventory group [ios_devices], secondly one-ish task: RUN 'Show Clock'. In this example, before running any tasks we prompt for some input and save the provider variables, once we have those we can then run the tasks. Run the play.. ansible-playbook show_clock_prompt.yml:

linickx:ansible$ansible-playbookshow_clock_prompt.ymlUsername:nickPassword:PLAY[ios_devices]*************************************************************TASK[RUN'Show Clock']********************************************************ok:[r2]ok:[r1]TASK[debug]*******************************************************************ok:[r1]=>{"clock.stdout_lines":[["19:12:37.863 UTC Mon Mar 27 2017"]]}ok:[r2]=>{"clock.stdout_lines":[["19:12:39.742 UTC Mon Mar 27 2017"]]}PLAYRECAP*********************************************************************r1:ok=2changed=0unreachable=0failed=0r2:ok=2changed=0unreachable=0failed=0linickx:ansible$

This time, we're prompted for credentials and less tasks take place.

Download the files from github!

My ansible files are on github, feel free to download them: https://github.com/linickx/ansible-cisco

Once you're happy with this, check out Primer 2 making changes .

Viewing all 88 articles
Browse latest View live


Latest Images