Posts

Showing posts from 2017

No more 180 day trial licensing....thanks Cisco :(

Here are the new licensing options.  If you request a license type more than once, you will now only get offered a 30 day license unless you request approval for a longer license.

Limitations of passing SQL across the Unified OS CLI

I have found that if you pass around 500 SQL updates via the CLI, you will get the following memory fault, 10.5.2, I have not yet tested with any other version:

Exception in thread "main" run(): caught exception Stream closed
java.lang.OutOfMemoryError: unable to create new native thread
        at java.lang.Thread.start0(Native Method)
        at java.lang.Thread.start(Thread.java:714)
        at com.cisco.cpi.common.util.cmExecCommand.exec(cmExecCommand.java:937)
        at com.cisco.cpi.common.util.cmExecCommand.exec(cmExecCommand.java:842)
        at com.cisco.iptplatform.cli.cmdBaseDbOSI.setDbLogMessageMethod(cmdBaseDbOSI.java:57)
        at com.cisco.iptplatform.cli.cmdBaseDbOSI.<init>(cmdBaseDbOSI.java:49)
        at com.cisco.iptplatform.cli.cmdRunSql.<init>(cmdRunSql.java:38)
        at sun.reflect.GeneratedConstructorAccessor8.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at java.lang.Class.newInstance(Class.java:383)
        at com.cisco.iptplatform.cli.cmdClassThread.setCmdInstance(cmdClassThread.java:105)
        at com.cisco.iptplatform.cli.CliClassLauncher.execute(CliClassLauncher.java:285)
        at sdMain.main(sdMain.java:1881)


However, I wrote a script that simply splits the loop into 400 command segments and then logs out and back in.  I will look to see if the API has the same issue as well and update this post at a later time.

ISE 2.3 for TACACS

This is just a quick post on how to get TACACS working in 2.3; using AD in this example.  For this, we will follow the guide provided here and supplement it below:

https://www.cisco.com/c/en/us/support/docs/security/identity-services-engine/200208-Configure-ISE-2-0-IOS-TACACS-Authentic.html

But for Configuring TACACS Authorization Policy, I am going to provide some screenshots in order.

Step 1

Step 2
Step 3











Step 4

Restoring from OVA backups, and changing IP, losing communications between nodes and how to restore

On occasion you might want to re-IP your lab environment and while the steps are fairly easy, ensuring you change it on the GUI prior to CLI changes and rebooting the subscriber node first.  You may still find you run into errors when trying to check the dbreplication runtimestate post IP change.  If you get the error, "Runtime state cannot be performed on a cluster with a single active node; aborting operation", you can fix it by ensuring you have the cluster publisher IP set in the subscriber and restarting the cluster manager service on both nodes.

set network cluster publisher ip <IP ADDRESS>
utils service restart Cluster Manager


After this, you should be able to see the proper status when issuing show network cluster:

admin:show network cluster
<IP> hq-sub.collab.life hq-sub Subscriber authenticated
<IP> hq-pub.collab.life hq-pub Publisher authenticated


Enjoy!

ISE 2.x Python API example EndPointGroup creation

Here is just a quick tidbit I tossed together for interfacing with the ISE 2.x API.n  Sadly, Parent Groups are not yet defined in the API.

#!/usr/bin/python3
import json, requests
from requests.auth import HTTPBasicAuth
#modify your values here
username = '<USERNAME>'
password = '<PASSWORD>'
fqdn = '<FQDN>'
name = '<GROUPNAME>'

description = '<DESCRIPTION>'
#actual script
url = 'https://' + fqdn + ':9060/ers/config/endpointgroup'
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
payload = {
        "EndPointGroup" : {
                "id" : "id",
                "name" : name,
                "description" : description,
                "systemDefined" : False
        }
}
resp = requests.post(url=url,
        data=json.dumps(payload),
        headers=headers,
        verify=False,
        auth=HTTPBasicAuth(username, password)
)
data = resp.text
if resp.status_code == 201:
        print('EndPointGroup ' + name + ' added!')
else:
        print('Status Code ' + str(resp.status_code))
        print(data)

Scheduled my CCIE Collab Lab for January 19th 2018

I don't normally post about myself, because really, I don't find my life important or fascinating.  However, on the scale of great accomplishments, I will be taking my CCIE lab soon.  After as much procrastination as possible, I will have to focus solely on studying.  Due to this, expect no updates until later in 2018!  See you then.  Feel free to leave a comment/request.


HP Proliant G7 (Old Server) madness and 10Gig NICs

I am just going to make a quick post after a long bit of sacrifice.  Should one every buy a new 10G NIC for their server in their CCIE lab, a couple of things you will want to know up front.

1)  What is the current firmware version on the card and does ESXi support it?
2)  What method does it require to upgrade the firmware, how will I go about doing this?

Once you have those out of the way, you may need some tools.  What I recommend for older cards is to use WinToUSB Enterprise with a version of Windows Server Evaluation that you can get from Microsoft's website.  You will need a 64GB thumbdrive as a lot of server hardware that is older will not boot from an external USB drive, but a thumbdrive will work.  Lastly, check your hardware's USB support prior to all this to ensure if you must flash it that it will work.  Otherwise you may need to slot the card in different hardware so you can flash it.

While there are methods using Linux to flash the firmware, I found those to be problematic if the drivers used .src.rpms or source based code that had to compile against the kernel due to differences in the original release and the packages now available.

Once you have all this done, you should be able to install the proper vib/driver in ESXi and get the host to recognize the card.  You can easily use a loopback plug to test your optics prior to wiring everything up and as always, make sure you clean your fiber ends prior to plugging them in to ensure you don't get dust into your transceivers!

CCIE Lab Licensing.... 6 month demo licensing FTW

So as many people know or aware, you can install CUCM and most nodes with demo licensing, and redeploy as needed for your labs.  However, Cisco offers 6 month demo licenses through their license management portal (which has steadily improved over the last few years).  Simply go to PLM, generate a license request and paste it into the port under the request demo license drop down.


You get 20 CUWL Pro for both Unity and CUCM.  Perfect for your CCIE Lab!

Using Cisco Jabber on a shared machine

While there are many ways to possibly solve the issue of a shared machine, one is to simply create a bat file that clears the current shared user's folder every time Cisco Jabber launches.  To do this you will need to use a text editor and input the following:

rmdir /s /q C:\Users\%USERNAME%\AppData\Roaming\Cisco\
"C:\Program Files (x86)\Cisco Systems\Cisco Jabber\CiscoJabber.exe"


Save this as a .bat file and then create a shortcut to it.  Once you have done this, you can update the shortcut properties to change both the Icon and Run Minimized so the command prompt window does not open when running it.  This is a quick and dirty work around for using Cisco Jabber on a shared machine.

Using an ASA and a single inside interace as your gateway for your CCIE Collaboration Lab

Before you think it will be a wonderful idea to run everything through your ASA as the default gateway of your lab, keep in mind that hairpins/u-turns off an ASA are not the best design.  For this reason you may have a bit of configuration to do. Please follow the current Cisco guide when you using an ASA your gateway device.

Found here:
https://supportforums.cisco.com/t5/security-documents/hairpin-u-turn-traffic-off-an-interface-on-an-asa-running-8-3-or/ta-p/3129668

CCIE Collaboration Lab NFS tidbits for Windows

Given the cost of storage for servers, you may want to use NFS for your CCIE lab.  If you are using Windows 10 and have a mass amount of storage on say your desktop vs your server, you could use a program called FreeNFS.  First download and install it, then run it and configure it from the directory where you would like to use it.  After this, connect to it using ESXi and validate you can access it.  Once you have done this, you can use NSSM to add FreeNFS as a service to run when your desktop boots.  I use it for all my VMDK backups to work around the 60 day demo licensing for my lab.  As well, if you are lacking resources, ensure you are thin provisioning your VM's and you can even go so far as using OVFtool to tweak the resources of each VM to dwindle them down to the 850Mhz range of processor usage.

Links to both:
http://freenfs.sourceforge.net/
https://nssm.cc/download

Lastly, should you have issues with ESXi inactive NFS shares, the best solution to avoid having to reconfigure any hosts is to use the CLI.

esxcli storage nfs remove -v <DATASTORE>
esxcli storage nfs add -H <HOST> -s <MOUNTPOINT> -v <DATASTORE>

CUCM certificate requests with an IP as the Subject Alternative Name (SAN)

If you have ever created a Certificate Signing Request using CUCM, you may have noticed a lack of setting an IP as a SAN.  A simple solution to this if you are dealing with a Microsoft Certificate Server is to fill out the additional attributes text field. However, by default prior to doing this you will need to open up an Administrator command prompt and issue the following command:

certutil -setreg policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2

Now restart your certificate services under the AD CA management pane.

Finally, you simply need to add the following:

san:dns=<hostname>&dns=<fqdn>&ipaddress=<ip address>

Although this may seem like a trivial thing, you will cause errors in most modern browsers due to not having a correct SAN in the certificate. This allows you to override even improperly generated requests lacking a SAN.  But by default Microsoft Server CA doesn't even generate Certificates with a SAN from the CUCM CSR's.  As always, remember that you need your CA to be in the computer's certificate store for trust to be established.

Lastly, make sure you restart your Tomcat service via the CLI by entering:

utils service restart Cisco Tomcat

LetsEncrypt + ASA 5500, automated certificate renewal script.

So there is no API for the ASA 5500 series, and you probably do not have an X series for Firepower firewall in your lab.  You could use the ASAv and the github script out there, but then you need licensing.  Due to this, I have created a fairly lengthy script that creates and renews your certs from Let's Encrypt.  You will need a Linux box, a web server running on it, root access (you have to run this with sudo at least), Python 3.x and paramiko-expect installed.  Most values are at the top to be changed.  It assumes you will use SSL-Trustpoint as the name, you can modify as you like.  This script is BSD licensing.  You may want to change the prompts and all fields at the top as needed.

So install Python 3.x (64 bit if needed), ensure your Path environment variable is set properly, then you will need to pip install paramiko-expect

This should work on all platforms!

This will also create a log file in /var/log/letsRenewASA.log as it is meant to be set up as a Cron job so that you no longer have to manually grab new certificates.

This script does NOT configure your VPN for you, you still have to do that yourself.

You can download it directly here:
https://drive.google.com/file/d/0Bz9hJ3nepc_7bUwxVUUxRG50OEU/view?usp=sharing

#!/usr/bin/python
#Copyright 2017 Tim Nelson
#
#Redistribution and use in source and binary forms, with or without modification,
#are permitted provided that the following conditions are met:
#
#1. Redistributions of source code must retain the above copyright notice,
#this list of conditions and the following disclaimer.
#
#2. Redistributions in binary form must reproduce the above copyright notice,
#this list of conditions and the following disclaimer in the documentation and/or
#other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
#IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
#INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
#NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#POSSIBILITY OF SUCH DAMAGE.


import paramiko, re, time
from paramiko_expect import SSHClientInteraction

asaHost = '<HOSTNAME OR IP OF ASA>'

hostname = '<ACTUAL HOSTNAME FIELD ON ASA>'
localHost = '127.0.0.1'
asaUser = '<ASAUSERNAME>'
asaPassword = '<ASAPASSWORD>'
enablePassword = '<ENABLEPASSWORD>'
localUser = '<LINUXUSERNAME>'
localPassword = '<LINUXPASSWORD>'
csrFilename = 'asa.csr'
logFile = '/var/log/letsRenewASA.log'
fqdn = '<YOUR FQDN>'
certString = 'CN=' + (fqdn) + ',OU=<YOUROU>,O=<ORGANIZATION>,C=US,St=<ST>,L=<CITY>'
letsEncrypt = '/usr/bin/letsencrypt/letsencrypt-auto'
email = '<YOUR ADMIN EMAIL>'
webRoot = '<ROOT DIRECTORY OF WEBSERVER>'

localPrompt = localUser + '@.*'
prompt0 = (hostname) + '> '
prompt1 = (hostname) + '# '
authPrompt = 'Password: '
confPrompt = '.*\)\# '
keyPrompt = '.*\[yes\/no\]: '
accept = 'Continue \(y\/n\)\?'
logFile = open(logFile ,'a+')
csrFile = open(csrFilename ,'w')
i = 10

logFile.write('\n\nStarting to Renew!\n')

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=asaHost, username=asaUser, password=asaPassword)
interact = SSHClientInteraction(client, timeout=120, display=False)
try:
        interact.expect(prompt0)
except Exception:
        logFile.write('could not read prompt0\n')
interact.send('en')
try:
        interact.expect(authPrompt)
except Exception:
        logFile.write('could not read authPrompt\n')
interact.send(enablePassword)
try:
        interact.expect(prompt1)
except Exception:
        logFile.write('could not read prompt1\n')
interact.send('conf t')
try:
        interact.expect(confPrompt)
except Exception:
        logFile.write('could not read confPrompt\n')
interact.send('crypto key generate rsa label SSL-Keypair modulus 2048')
interact.expect([keyPrompt, confPrompt])
if interact.last_match == keyPrompt:
        interact.send('n')
interact.send('crypto ca authenticate SSL-Trustpoint')
interact.expect(['.*delete.*', '.*unknown.*'])
if interact.last_match == '.*delete.*':
        interact.send('no crypto ca trustpoint SSL-Trustpoint')
        interact.expect([keyPrompt, '.*in use.*'])
        if interact.last_match == '.*in use.*':
                i = 0
                interact.send('no crypto ikev2 remote-access trustpoint SSL-Trustpoint')
                interact.expect(confPrompt)
                interact.send('no crypto ca trustpoint SSL-Trustpoint')
                interact.expect(keyPrompt)
        interact.send('y')
interact.send('crypto ca trustpoint SSL-Trustpoint')
interact.expect(confPrompt)
interact.send('enrollment terminal')
interact.expect(confPrompt)
interact.send('fqdn ' + (fqdn))
interact.expect(confPrompt)
interact.send('subject-name ' + (certString))
interact.expect(confPrompt)
interact.send('keypair SSL-Keypair')
interact.expect(confPrompt)
interact.send('exit')
interact.expect(confPrompt)
interact.send('crypto ca enroll SSL-Trustpoint')
interact.expect(keyPrompt)
interact.send('y')
interact.expect(keyPrompt)
interact.send('n')
interact.expect(keyPrompt)
interact.send('y')
interact.expect(keyPrompt)
cert = interact.current_output_clean
cert = re.sub('Certificate Request follows:\n', '', cert)
cert = re.sub('\x00', '', cert)
interact.send('n')
interact.expect(confPrompt)
interact.send('exit')
interact.expect(prompt1)
interact.send('exit')
csrFile.write(cert)
csrFile.close()
client.connect(hostname=localHost, username=localUser, password=localPassword)
interact = SSHClientInteraction(client, timeout=120, display=False)
try:
        interact.expect(localPrompt)
except Exception:
        logFile.write('could not read localPrompt\n')
        print('could not read localPrompt')
interact.send(
 (letsEncrypt) +
 ' certonly --authenticator manual --server https://acme-v01.api.letsencrypt.org/directory --text --email '+
 (email) + ' --csr ' + (csrFilename)
 )
interact.expect('.*o: ')
interact.send('y')
interact.expect('Press Enter to Continue')
cleanOutput = interact.current_output_clean
challengeFile = cleanOutput.splitlines()[8]
challengeFile = re.sub('http://' + (fqdn) + '/', (webRoot), challengeFile)
challengeContent = cleanOutput.splitlines()[4]
logFile.write('Created challengeFile at ' + (challengeFile) + '\n')
challengeFile = open(challengeFile, 'w')
challengeFile.write(challengeContent)
logFile.write('Put the following content: ' + (challengeContent) + ' in challengeFile\n')
challengeFile.close()
interact.send('\r')
interact.expect(localPrompt)
cleanOutput = interact.current_output_clean
interact.send('exit')
certPath = (cleanOutput.splitlines()[4])
certPath = re.sub('Server issued certificate; certificate written to ', '', certPath)
logFile.write('Grabbed the certificate from: ' + (certPath) + '\n')
chainPath = (cleanOutput.splitlines()[10])
chainPath = re.sub('\s+', '', chainPath)
chainFile = open(chainPath, 'r')
certFile = open(certPath, 'r')
caFile = chainFile.read()
caCert = re.findall(
 r'-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----',
 caFile, re.DOTALL
 )
caCert = '-----BEGIN CERTIFICATE-----' + (caCert[1]) + '-----END CERTIFICATE-----'
chainFile.close()
logFile.write('Grabbed the certificate chain from: ' + (chainPath) + '\n')
client.connect(hostname=asaHost, username=asaUser, password=asaPassword)
interact = SSHClientInteraction(client, timeout=120, display=False)
try:
        interact.expect(prompt0)
except Exception:
        logFile.write('could not read prompt0\n')
interact.send('en')
try:
        interact.expect(authPrompt)
except Exception:
        logFile.write('could not read authPrompt\n')
interact.send(enablePassword)
try:
        interact.expect(prompt1)
except Exception:
        logFile.write('could not read prompt1\n')
interact.send('conf t')
try:
        interact.expect(confPrompt)
except Exception:
        logFile.write('could not read confPrompt\n')
interact.send('crypto ca authenticate SSL-Trustpoint')
interact.expect('.*by itself.*')
for line in caCert.splitlines():
        interact.send(line)
        time.sleep(.1)
interact.send('quit')
interact.expect(keyPrompt)
interact.send('y')
interact.expect(confPrompt)
interact.send('crypto ca import SSL-Trustpoint certificate')
interact.expect(keyPrompt)
interact.send('y')
interact.expect('.*by itself.*')
lines2 = certFile.read().splitlines()
for line2 in lines2:
        interact.send(line2)
        time.sleep(.1)
certFile.close()
interact.send('quit')
interact.expect(confPrompt)
interact.send('ssl trust-point SSL-Trustpoint outside')
interact.expect(confPrompt)
if i == 0:
        interact.send('crypto ikev2 remote-access trustpoint SSL-Trustpoint')
        interact.expect(confPrompt)
interact.send('exit')
interact.expect(prompt1)
interact.send('wr')
interact.expect(prompt1)
logFile.write('SUCCESSFULLY installed the cert and chain to your ASA!\n')
logFile.close()
interact.send('exit')

Adding 2 Factor Authentication to Guacamole through Duo and Yubikey

In order to do this you will need to grab the current duo extension as such:

wget https://gigenet.dl.sourceforge.net/project/guacamole/current/extensions/guacamole-auth-duo-0.9.13-incubating.tar.gz

Once downloaded, decompress and move it to the appropriate folder:

tar xzf guacamole-auth-duo-0.9.13-incubating.tar.gz && mkdir /etc/guacamole/extensions && mv ./guacamole-auth-duo-0.9.13-incubating/guacamole-auth-duo-0.9.13-incubating.jar /etc/guacamole/extensions/

Now add the Guacamole as an application to your Duo management page.  Select, Protect an Application under the Applications menu, then you will select the Web SDK application, rename it something like Guacamole.

Next you will need to edit your /etc/guacamole/guacamole.properties and add the following info to it from the Duo site (minus the last key):

duo-api-hostname: <Your API key found on the Duo site>
duo-integration-key: <Integration key found on the Duo site>
duo-secret-key: <Secret Key found on Duo site>
duo-application-key: <40 random characters, I used pwgen 40 1>


The duo-application-key is just any 40 characters that you save into this file, it is not found on the Duo site.  Once you add these to the bottom, restart the tomcat service.

Next you will need to ensure you have your token registered as per instructions here:
https://duo.com/docs/yubikey

Ensure the assigned user matches your Guacamole username and that if you are using the second token slot, you are holding the button on your Yubikey down for the token input (as well, make sure you are on token).

That's it!  Enjoy 2 factor authentication to your Guacamole server!


Guacamole, Tomcat and LetsEncrypt, for VPN-less CCIE Lab Access

So you just built your CCIE lab but you can't access it from work because VPNs are restricted?  No problem!  Guacamole solves this issue, below is a quick dirty method of implementing it properly.

I highly recommend that you use the most current Guacamole release always (not Git).  Once you have compiled Guacamole from source (binaries generally do not work as well and I run my portal on a 7watt ARM dev board).  You can simply follow the guide off the Guacamole site: https://guacamole.incubator.apache.org/ you may have unmet dependencies prior to doing this. For Ubuntu, the following is done:

add-apt-repository ppa:webupd8team/java
apt -y update
apt -y upgrade
apt -y dist-upgrade
apt -y install libcairo2-dev libjpeg-turbo8-dev libpng12-dev libossp-uuid-dev \

libfreerdp-dev libpango1.0-dev libssh2-1-dev libtelnet-dev libvncserver-dev \
libpulse-dev libssl-dev libvorbis-dev libwebp-dev git build-essential autoconf \
libtool oracle-java8-installer tomcat8 tomcat8-admin tomcat8-common tomcat8-docs \
tomcat8-user maven mysql-server mysql-client mysql-common mysql-utilities \
libpulse-dev libvorbis-dev freerdp ghostscript wget


Once this is complete you should be good.  Next, you will need to get Letsencrypt:

git clone https://github.com/letsencrypt/letsencrypt ~/letsencrypt
cd ~/letsencrypt
./letsencrypt-auto certonly --expand --webroot --webroot-path \

/<CATALINA_HOME>/webapps/ROOT/ -d <YOURDOMAIN> --staging

Ensure you are using staging until successful, once successful, drop the --staging and rerun.  At this point we now have our certificate issued by LetsEncrypt.  For Tomcat, it's easiest to convert it into a .jks  Once you get the success, cd into the proper directory where your certs are stored.
Then do the following:

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out cert_and_key.p12 \
-name tomcat -CAfile chain.pem -caname root


fullchain.pem should be the host and the intermediate certificate in a single file, or else you will only present a single certificate, which is a security risk.

Convert the pkcs12 into a jks now:

keytool -importkeystore -deststorepass <changeit> -destkeypass <changeit> \
-destkeystore myKeyStore.jks -srckeystore cert_and_key.p12 -srcstoretype \
PKCS12 -srcstorepass <PasswordUsedAbove> -alias tomcat


Now edit your /<CATALINA_HOME>/server.xml with the following connector options:

scheme="https" secure="true" SSLEnabled="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="/etc/letsencrypt/live/<YOURDOMAIN>/myKeyStore.jks"

keystorePass="<changeit>" keyAlias="tomcat" keyPass="<changeit>"


Next, lets forward port 443 to 8443 since tomcat doesn't always run on 443 and it's much quicker to do it this way:

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443

Test your connection from an outside source and done!
I recommend using https://www.ssllabs.com/ssltest/

If you want to install Tomcat 8 from source, use this guide:
https://www.digitalocean.com/community/tutorials/how-to-install-apache-tomcat-8-on-ubuntu-14-04

And if you need an init.d script, here's mine:
#!/bin/bash
export CATALINA_HOME=/opt/tomcat
export JAVA_HOME=<WHATEVERYOURJAVAHOMEIS>
export PATH=$JAVA_HOME/bin:$PATH

start() {
 echo "Starting Tomcat 8..."
 sh $CATALINA_HOME/bin/startup.sh
}
stop() {
 echo "Stopping Tomcat 8..."
 sh $CATALINA_HOME/bin/shutdown.sh
}
case $1 in
  start|stop) $1;;
  restart) stop; start;;
  *) echo "Usage : $0 <start|stop|restart>"; exit 1;;
esac

exit 0




PhantomJS, Python, Selenium, Java notifications and popups, how to confirm?

When dealing with Java alerts/notifications that you need to accept and using a headless browser such as PhantomJS, there is no method (currently) for handling the alerts.  Instead what you have to do is send a driver.execute script into the mix.

driver.execute_script("window.confirm = function(msg) { return true; }");

However, this simply cannot be placed after the pop up occurs, it must be pushed before the step you will use in Selenium that causes the pop up notification.

Example, in CUCM you have certain actions that create two consecutive pop-ups that you need to accept or press 'OK' on.  For this you would need to do the following:

try:
driver.execute_script("window.confirm = function(msg) { return true; }");
driver.execute_script("window.confirm = function(msg) { return true; }");
elem = driver.find_element_by_name("button2")

elem.click()

Selenium how to simply grab an html value in Python

While dealing with Selenium, you may run into object that have no ID and no Name, or a duplicate name.  At this point the unique identifier might be the Value field.  While normally Xpath values are a pain to deal with, you can simply wild card them if the Value field is indeed unique to the page.

elem = driver.find_element_by_xpath(".//*[@value='<WhatIamLookingFor>']")
elem.click()

CUCM Selenium, inability to skip steps

When dealing with CUCM, one of the things you need to take notice of is that you are dealing with Tomcat JSP's. This means that even through there are URL shortcuts, you can not take them when automating.

Example:
'https://'+host+'/ccmservice/communitystring.jsp?NodeID='+(host)+'.'+(domain)+'&action=add'

This is the third step, after you have selected the server and then clicked the Add New button.  While you would think you can just negate all the clicking and go directly to the URL and have shorter code, you cannot.  You must click through as if you were doing it manually.

So you really have to use all this:
elem = driver.find_element_by_name("submit1")
elem.click()
elem = driver.find_element_by_name("button1")
elem.click()
elem = driver.find_element_by_name("communityString")
elem.send_keys(communityString)

How to update CUCM DNS through automation in Windows

So I spent a lot of time trying to find something that works in both Windows and other OS's under python that has similar output as expect (Yes, I happen to be a TCL fan....)

My solution is Python + Paramiko-Expect

Here is a snippet:


client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=hostAddress, username=u, password=p, banner_timeout=120)
prompt = 'admin:'
accept = 'Continue \(y\/n\)\?'
interact = SSHClientInteraction(client, timeout=120, display=False)
interact.expect(prompt)
try:
interact.send('set network dns primary ' + str(args.primarydns))
cmd_output_pd = interact.current_output_clean
#split what you expect as output and do tasks for each
interact.expect([accept, prompt])
if interact.last_match == prompt:
print((threadName) + ' -> ' + str(args.primarydns) + ' -> FAIL')
if interact.last_match == accept:
print((threadName) + ' -> ' + str(args.primarydns) + ' -> SUCCESS')
interact.send('y')
interact.expect(accept)
interact.send('y')
interact.expect(prompt)
interact.send('exit')
#throw no exception, you lose connectivity when changing this
except Exception:
interact.send('exit')

Example Python Selenium Script for logging into CUCM


import getpass
u = input("Enter the OS Administration Username: ")
p = getpass.getpass ("Enter the OS Administration Password:")
hostList = ['host1','host2']
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

options = webdriver.ChromeOptions()
options.add_argument('--ignore-certificate-errors')

driver = webdriver.Chrome(chrome_options=options)

for host in hostList:
url = "https://" + host + "/cmplatform"
driver.get(url)
elem = driver.find_element_by_name("j_username")
elem.clear()
elem.send_keys(u)
elem = driver.find_element_by_name("j_password")
elem.clear()
elem.send_keys(p)
elem.send_keys(Keys.RETURN)
url = "https://" + host + "/cmplatform/"
driver.get(url)