Search code examples
shellsshsolarisexpect

Solaris 11 Expect script test for ssh-key already installed? WITHOUT ssh-copy-id ssh-pass


I have the following expect script on a Solaris 11.4 server. As Solaris 11 does not ship with ssh-copy-id or ssh-pass. I want to create a script to automate copying my ssh key to 100+ servers. After a bit of Google expect seems to be only option - unless someone knows better ?

I can get the script to copy the key onto the target server, but what I require is the script not to copy if they key is already installed.

The only way I can check for this is if the ssh login goes straight on without asking for a password. My issue is how do I test for an empty prompt ? .

If the key is not installed I get password prompt - then I can use expect to complete the password and copy the key. I've tried testing for "" (empty) but that seems to match everything. Any advise greatly appreciated.

#!/usr/bin/expect

set timeout 1200
set user [lindex $argv 0]
set host [lindex $argv 1]
set pass [lindex $argv 2]

set sshkeyfile  [open  ~/.ssh/id_rsa.pub r]
set sshid [read $sshkeyfile]
close $sshkeyfile

spawn ssh $user@$host "mkdir -m 700 ~/.ssh ; echo \" $sshid\" >> ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys"

expect {
"continue" { send "Yes\n" ; exp_continue }
"Password" { send "$pass\r"; interact}
"" { send "exit\n" ; exit 0 } # Exit if not asked for "continue/Password"
}

Solution

  • How about this: ssh without the command; if the password is seen, set a boolean variable; when you hit the shell prompt, if the variable is true, append to the authorized_keys

    #!/usr/bin/expect
    
    set timeout 1200
    lassign $argv  user host pass
    
    set sshkeyfile  [open  ~/.ssh/id_rsa.pub r]
    set sshid [read -nonewline $sshkeyfile]
    close $sshkeyfile
    
    set sentPassword false
    set prompt {\$ $}        ;# shell prompt ends with "dollar space"
    
    spawn ssh $user@$host
    
    expect {
        "continue" {
            send "Yes\r" 
            exp_continue
        }
        "Password" {
            set sentPassword true
            send "$pass\r"
            exp_continue
        }
        -re $prompt
    }
    if {$sentPassword} {
        send "mkdir -p -m 700 ~/.ssh ; echo \"$sshid\" >> ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys\r"
        expect -re $prompt
    }
    send "exit\r"
    expect eof
    

    other changes:

    • lassign to handle the command line arguments in one command
    • read -nonewline to omit the trailing newline from the public key
    • mkdir -p to prevent error message if the directory already exists.