Friday 5 February 2016

Using Expect to automate SSH public key installation

Using SSH password-less configuration is a corner stone in any automation for Unix based systems in IT.
even when using tools like puppet and the like, you still need SSH and password-less authentication.

Lately i was faced with a scenario where i have access to login with a single none privileged user to a set of 45 nodes and only is able to sudo su - to a tomcat user which have access to the Tomcat installation.

Those nodes uses puppet so it was working for me and taking over the headache of playing around with automation. the issue happened when i needed to deploy some 40+ java war files manually on those nodes.
I do have an automated puppet based deployment mechanism but for this setup, there is a lot of road blocks to using it, firewalls, code sharing and other stuff.

so i needed a way to setup SSH keys for the tomcat user, so i can jump to it with SSH directly.
given i don't have its password, and i only use sudo from another user, traditional shell scripting will not help much since i will hop from user to user, and sudo syntax is limiting me to only sudo su -  tomcat.

Entering the domain of Unix expect once more, it has been a long while since i last used it.
expect is the perfect tool to automate scenarios like this, since it will be able to handle as if you are doing things interactively.

Below is my simple expect script:

admin@cntrl01> cat script.exp
set timeout 20
set host [lindex $argv 0]
spawn ssh -q sherif@${host}
expect "password:"
send "sherif@01\r"
expect "sherif@"
send "sudo su - tomcat\r"
expect "tomcat@"
send "mkdir -p .ssh\r"
expect "tomcat@"
send "chmod 700 .ssh\r"
expect "tomcat@"
send "echo 'ssh-rsa AAAAB3NjskjsksjskuuuuuuuuoiqoioabSSLKKSlksoiSSs9lp00wwwU4VzXVLFMGdFoVK3NmGEyTlYzPHhzJNldsSNqJnZaXw== admin@cntrl01' >>.ssh/authorized_keys\r"
expect "tomcat@"
send "chmod 400 .ssh/authorized_keys\r"
expect "tomcat@"
send "exit\r"
expect "sherif@"
send "exit\r"
admin@cntrl01>


this script take the host name as a parameter, to run it do the following:

$ expect script.exp node1.example.com

expect is really powerful, specially if you know ur way with TCL, but still its a major security flaw that many companies don't like to have on their nodes, still, its very useful for admins only on a control node.