Leaving ones Comfort Zone (wip).

Written by  on January 9, 2013

The other day another admin was asked to help put together the system uptime reports based on the work done by a long item gone admin who left the organization with a CA-spectrum monitoring legacy. Every now and then uptime reports were created for upper management which consisted of graphs produced from excel spreadsheets which were populated based on spreadsheets produced by the CA suit. The entire process was extremely manual and the problems they were having were with the tools used by any Unix admin to parse data. The questions were about how do I get this text file on to adn off of a non essential unix system so they could run the documented steps to get data from one excel spreadsheet to another. As a long time admin I didnt see much issue with the process since the reports were infrequent and usually “I need this now”. But it seems silly to leave a step by step set of instructions on how to cut, grep, and sed a pile of text to get the requested data for a windows admin. My first thought was just to repeat the process in python but then you have to expect python and its supporting tools to be installed on windows.

So. I started looking at the tools which were already valiable to Windows users and a process that would produce the same

I was surprised to find a fairly rich set in a short time. Now to finish the translation. Then to get the same reports out of the nagios.

Paramiko: python driven ssh.

Written by  on January 4, 2013

As the only unix person available over the holidays the task I was given was to take a list of over a hundred servers and a login (belonging to our manager, a windows sysadmin) that was supposed to have ssh and sudo access and learn as much as I could before the other admin got back from Christmas vacation. Since I have been working primarily in python I started looking at ssh and python and found paramiko which is an ssh implementation built in python. http://www.lag.net/paramiko/docs/paramiko-module.html I was able to use this to determine which servers actually were accessible and which were virtual. Once the other admin was available to fix the accounts that didn’t have access I set about getting a login and password on them. Apparently in the past this took months.

"""
quick script to add my account to the 100+ servers using
my managers login credentials
"""

import paramiko
import getpass
import socket

uname='myboss'
pwd=getpass.getpass()
hosts=["host1",...,"host130"]
for host in hosts:
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host,username=uname,password=pwd,timeout=3.0)
        stdin,stdout,stderr=ssh.exec_command('/usr/local/bin/sudo /usr/sbin/useradd -u 1119 -g 14 -G"ssh-allow" -c"Donald Davis" -m -d /export/home/ddavis -s /bin/bash ddavis')
        stdin.write(pwd+'\n')
        stdin.flush()
        outlines=stdout.readlines()
        if len(outlines):
            lastout=outlines[0].rstrip('\r\n')
            lastuser=lastout.split(' ',1)[0]
        stdin,stdout,stderr=ssh.exec_command("/usr/bin/grep ddavis /etc/passwd")
        outlines=stdout.readlines()
        if len(outlines):
           print "USER_ADDED::"+host+","+outlines[0].rstrip('\r\n')
        else:
            outlines=stderr.readlines()
            for line in outlines:
                print " ERROR::"+host+","+line.rstrip('\r\n')

        stdin,stdout,stderr=ssh.exec_command("/usr/bin/grep ddavis /etc/group")
        if len(outlines):
           print "GRP_CHANGE::"+host+","+outlines[0].rstrip('\r\n')
        else:
            outlines=stderr.readlines()
            for line in outlines:
                print " ERROR::"+host+","+line.rstrip('\r\n')

    except paramiko.AuthenticationException:
        print " AUTHFAIL::"+host+","+uname
    except Exception as e:
        if "Name or service not known" in str(e):
            print " AWOL::"+host
        elif "timed out" in str(e):
            print " TIMEDOUT::"+host
        else:
            print " UNKNOWN::"+host+",", str(e)

Getting the password set was a little more tricky since passwd actually requires a tty/shell context.

import paramiko
import getpass
import socket
import time

authissues=[]
unknown=[]
awol=[]

uname='myboss'
pwd=getpass.getpass()

hosts=[...listofhosts...]

mypwd=getpass.getpass(0)
for host in hosts:
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host,username=uname,password=pwd,timeout=1.5)
        chan=ssh.invoke_shell()
        chan.set_combine_stderr(True)
        time.sleep(.6)
        print chan.recv(9999)

        chan.sendall("/usr/local/bin/sudo /usr/bin/passwd ddavis\n")
        time.sleep(.3)
        buff=''
        while 'assword' not in buff:
            resp = chan.recv(9999)
            buff += resp
            print(resp)
            if 'unknown' in buff:
                raise #hell
            if 'denied' in buff:
                raise #hell
            if 'o such file' in buff:
                raise #hell
            if 'not in the sudoers' in buff:
                raise #hell
        chan.send(pwd+'\n')
        time.sleep(.2)

        buff=''
        while 'assword' not in buff:
            resp = chan.recv(9999)
            buff += resp
            print(resp)
            if 'unknown' in buff:
                raise #hell
            if 'denied' in buff:
                raise #hell
            if 'o such file' in buff:
                raise #hell
            if 'not in the sudoers' in buff:
                raise #hell

        chan.send(mypwd+'\n')
        time.sleep(.2)

        buff=''
        while 'assword' not in buff:
            resp = chan.recv(9999)
            buff += resp
            print(resp)
        chan.send(mypwd+'\n')
        time.sleep(.2)

        print chan.recv(2000)
        chan.close()
    except paramiko.AuthenticationException:
        print " AUTHFAIL::"+host+","+uname
        authissues.append(host)
    except Exception as e:
        if "Name or service not known" in str(e):
            print " AWOL::"+host
            awol.append(host)
        elif "timed out" in str(e):
            print " TIMEDOUT::"+host
            awol.append(host)

        else:
            print "UNKNOWN::"+host+",", str(e)
            unknown.append(host)

print "AUTHFAIL", authissues
print "AWOL", awol
print "UNKNOWN",unknown

Finally I can then get rid of the need for passwords altogether with this snippet stolen from the internets.

#!/usr/bin/python
import os
import getpass

authissues=[]
unknown=[]
awol=[]
hosts=[...list of hostnamed ]
import paramiko

def deploy_key(key, server, username, password):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(server, username=username, password=password)
    client.exec_command('mkdir -p ~/.ssh/')
    client.exec_command('echo "%s" > ~/.ssh/authorized_keys' % key)
    client.exec_command('chmod 644 ~/.ssh/authorized_keys')
    client.exec_command('chmod 700 ~/.ssh/')

key = open(os.path.expanduser('~/.ssh/id_rsa.pub')).read()
username = os.getlogin()
password = getpass.getpass()

for host in hosts:
    try:
        deploy_key(key, host, username, password)
    except paramiko.AuthenticationException:
        print " AUTHFAIL::"+host
        authissues.append(host)
    except Exception as e:
        if "Name or service not known" in str(e):
            print " AWOL::"+host
            awol.append(host)
        elif "timed out" in str(e):
            print " TIMEDOUT::"+host
            awol.append(host)

        else:
            print "UNKNOWN::"+host+",", str(e)
            unknown.append(host)

print "AUTHFAIL", authissues
print "AWOL", awol
print "UNKNOWN",unknown

.