#!/bin/sh # # SSHMigrate - v0.1 # # Joe Emenaker (joe@emenaker.com) # 2007-02-16 # # This script lets you specify any remote user/host combination # (ie, sshmigrate someuser@some.host.com) and it will send # your ssh public keys and import them into the authorized_keys # files on the remote host... thereby eliminating the need # for you to supply a password when ssh'ing to that host # from this one. # Some options: # SEND_AUTHKEYS (0|1) # Whether to just send the public keys for *this* host or to also # send all public keys in authorized_keys and authorized_keys2 # This is handy if you have a group of hosts/accounts that # you want to seamlessly login to/from. SEND_AUTHKEYS=1 # SEND_SCRIPT (0|1) # Whether to scp this script to the remote host (for further migration) # after this migration is complete SEND_SCRIPT=1 # REFLECT (0|1) # Whether to attempt to run SSHMigrate on the *remote* host back # to this one. (Implies SEND_SCRIPT=1) REFLECT=0 # REMOTE_HOSTS (space-separated string) # A list of remote hosts to copy our keys to. If this is empty, # then the user must supply the remote host on the command-line # If this is *not* empty, supplying a host(s) on the command-line # over-rides this. REMOTE_HOSTS="" SSH1PUBKEY="$HOME/.ssh/identity.pub" SSH2RSAPUBKEY="$HOME/.ssh/id_rsa.pub" SSH2DSAPUBKEY="$HOME/.ssh/id_dsa.pub" SSH1AUTHKEYS="$HOME/.ssh/authorized_keys" SSH2AUTHKEYS="$HOME/.ssh/authorized_keys2" WHOAMI=`whoami` WHEREAMI=`hostname -f` SCRIPTNAME=`echo $0 | sed 's!.*/!!'` ################################### ################################### ################################### # REMOTE SCRIPT START ################################### ################################### ################################### send_remote_script() { cat << 'ENDOFSCRIPT' #!/bin/sh # # Joe Emenaker (joe@emenaker.com) # 2007-02-16 # Where are our authorized keys stored? TYPE1STORE="$HOME/.ssh/authorized_keys" TYPE2STORE="$HOME/.ssh/authorized_keys2" MYNAME=`whoami` MYGROUP=`groups | cut -d" " -f1` set_perms() { FILE="$1" chmod 600 "$FILE" chown "$MYNAME.$MYGROUP" "$FILE" } add_type_1() { KEY="$1" # Adds an SSL1 public key to $HOME/.ssh/authorized_keys # Is there a file to put it in already? if [ ! -f "$TYPE1STORE" ] then echo " Couldn't find \"$TYPE1STORE\". Creating empty one." touch "$TYPE1STORE" fi # Get the key to add MYID=`echo "$KEY" | cut -d" " -f4` # Make sure the key is somewhat formatted properly if (echo "$KEY" | egrep -q "^[0-9]{3,4} [0-9]{2} [0-9]{100}") then # Is it already in the key store? if ( cat "$TYPE1STORE" | cut -d" " -f4 | grep -q "$MYID" "$TYPE1STORE" ) then echo " \"$MYID\" already exists in \"$TYPE1STORE\"" else echo " Adding \"$MYID\" to \"$TYPE1STORE\"..." echo "$KEY" >> "$TYPE1STORE" fi else echo " I don't recognize \"$KEY\" as a valid SSH1 public key" fi # SSH will refuse to use world/group-readable authorized_hosts* files. Novice users can take a # *long* time to track down why SSH is still requiring a password. Let's fix it now, just in case. set_perms "$TYPE1STORE" } add_type_2() { KEY="$1" # Is there a file to put it in already? if [ ! -f "$TYPE2STORE" ] then echo " Couldn't find \"$TYPE2STORE\". Creating empty one." touch "$TYPE2STORE" fi # Get the key to add MYID=`echo "$KEY" | cut -d" " -f3` # Is this DSA or RSA? MYTYPE=`echo "$KEY" | cut -d" " -f1` case "$MYTYPE" in ssh-rsa | ssh-dss) if ( cat "$TYPE2STORE" | cut -d" " -f4 | grep -q "^$MYTYPE .* $MYID" "$TYPE2STORE" ) then echo " \"$MYID\" already exists in \"$TYPE2STORE\"" else echo " Adding $MYTYPE key for \"$MYID\" to \"$TYPE2STORE\"..." echo "$KEY" >> "$TYPE2STORE" fi ;; *) echo " I don't recognize \"$KEY\" as a valid SSH2 public key" ;; esac # SSH will refuse to use world/group-readable authorized_hosts* files. Novice users can take a # *long* time to track down why SSH is still requiring a password. Let's fix it now, just in case. set_perms "$TYPE2STORE" } ENDOFSCRIPT } ################################### ################################### ################################### # REMOTE SCRIPT END ################################### ################################### ################################### ############### # Beginning of local script ############### echo "" # We need a host name if [ "$#" -gt 0 ] then REMOTE_HOSTS="$1" shift while [ "$#" -gt 0 ] do REMOTE_HOSTS="$REMOTE_HOSTS $1" shift done fi if [ -z "$REMOTE_HOSTS" ] then echo "Usage: $0 [remoteuser@]remotehost ..." exit 1 fi # Check to see if the user even has any public keys to migrate if [ ! -f "$SSH1PUBKEY" -a ! -f "$SSH2RSAPUBKEY" -a ! -f "$SSH2DSAPUBKEY" ] then echo "It doesn't appear that you have any public keys to migrate." echo "You need one of the following files:" echo " $SSH1PUBKEY" echo " $SSH2RSAPUBKEY" echo " $SSH2DSAPUBKEY" echo "" echo "Perhaps you need to run \"ssh-keygen\" first." exit 1 fi # SSH1 key if [ -f "$SSH1PUBKEY" ] then echo " SSH1 key : Found" TYPE1KEY=`cat "$SSH1PUBKEY"` else echo " SSH1 key : NOT Found" fi # SSH2 DSA key if [ -f "$SSH2DSAPUBKEY" ] then echo " SSH2-DSA key : Found" TYPE2DSA=`cat "$SSH2DSAPUBKEY"` else echo " SSH2-DSA key : NOT Found (Create one with \"ssh-keygen -t dsa\"" fi # SSH2 RSA key if [ -f "$SSH2RSAPUBKEY" ] then echo " SSH2-RSA key : Found" TYPE2RSA=`cat "$SSH2RSAPUBKEY"` else echo " SSH2-RSA key : NOT Found (Create one with \"ssh-keygen -t rsa\"" fi echo "" echo "SSHMigrate is now going to attempt to send your ssh keys to all" echo "of the remote accounts that you have chosen. Ssh will probably" echo "ask for your password on the remote host. If all goes as planned," echo "this will be the last time you'll be asked for a password when" echo "connecting to them from here..." echo "" for REMOTEHOST in $REMOTE_HOSTS do echo "Migrating to $REMOTEHOST..." # Copy our script and our public keys to the remote host ( send_remote_script [ -n "$TYPE1KEY" ] && echo "add_type_1 \"$TYPE1KEY\"" [ -n "$TYPE2DSA" ] && echo "add_type_2 \"$TYPE2DSA\"" [ -n "$TYPE2RSA" ] && echo "add_type_2 \"$TYPE2RSA\"" # Do we also send the authorized_keys* files? if [ "$SEND_AUTHKEYS" -eq 1 ] then # SSH1 keys if [ -f "$SSH1AUTHKEYS" ] then cat "$SSH1AUTHKEYS" | while read line do echo "add_type_1 \"$line\"" done fi # SSH2 keys if [ -f "$SSH2AUTHKEYS" ] then cat "$SSH2AUTHKEYS" | while read line do echo "add_type_2 \"$line\"" done fi fi ) | ssh -T "$REMOTEHOST" # Are we supposed to run this script on the remote site, or merely copy it? if [ "$REFLECT" -eq 1 -o "$SEND_SCRIPT" -eq 1 ] then echo " Copying this script to the remote host" scp "$0" $REMOTEHOST echo "chmod +x \"$SCRIPTNAME\"" | ssh -T "$REMOTEHOST" # Are we supposed to run it there, too? if [ "$REFLECT" -eq 1 ] then # This isn't implemented, yet, because we need to prevent infinite recursion # echo "\"./$SCRIPTNAME\" \"$WHOAMI@$WHEREAMI\"" | ssh -T "$REMOTEHOST" echo " REFLECT isn't implemented, yet" fi fi echo "Done with $REMOTEHOST" echo "" done echo "SSHMigrate has finished" echo ""