Search code examples
linuxbashsshexpectopenssh

ssh-add from bash script and automate passphrase entry


I am trying to do ssh-add from script (don't care about about security at the moment).

Now ssh prompts for passphrase, which needs to be automated, so i read couple of things like this and found expect.

And now i do following:

eval `ssh-agent -s`

script tmp.sh defined as :

#!/usr/bin/expect
spawn ssh-add /root/.ssh/id_rsa
expect "Enter passphrase for /root/.ssh/id_rsa:"
send "my_pass"
interact

./tmp.sh

ssh-add -l

If ssh-add would have worked it shows something like

4096 SHA256:wlfP/nhVSWXLcljBOen5GSYZXJGgfi/XJWfZeBwqRsM id_rsa (RSA)

But instead i get The agent has no identities. Seems like ssh-agent looses it's context.

Am open to other solutions to do this.


Solution

  • Personally, I find the use of expect a bit cumbersome. The following approach found how to make ssh-add read passphrase from a file rather informative.

    So if your version of ssh-add allows the -p argument and you are not worried about security then this should work:

    #!/bin/bash
    # store a file somewheres with your passphrase. For example's sake
    # I'll just use $HOME/.myscrt
    
    <$HOME/.myscrt ssh-add -p ~/.ssh/id_rsa
    

    Now if -p is not an option for you, I found the second method mildly ingenious:

    #!/bin/bash
    # Same passfile and some minor enhancements from the OP of the linked
    # solution
    PASS="$(<$HOME/.myscrt)"
    
    # the following is just a one-liner method of making an executable
    # one-line script echoing the password to STDOUT
    install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
    
    # then the magic happens. NOTE: your DISPLAY variable should be set
    # for this method to work (see ssh-add(1))
    [[ -z "$DISPLAY" ]] && export DISPLAY=:0
    < id_rsa SSH_ASKPASS="$PWD/ps.sh" ssh-add - && shred -n3 -uz  $PWD/ps.sh    
    

    When I tested the script I called "j", see below:

    $ cd /tmp
    $ ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/me/.ssh/id_rsa): /tmp/id_rsa
    Enter passphrase (empty for no passphrase): asdfasdf
    Enter same passphrase again: asdfasdf
    Your identification has been saved in /tmp/id_rsa.
    Your public key has been saved in /tmp/id_rsa.pub.
    The key fingerprint is:
    ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d jimconn@redapt-240
    The key's randomart image is:
    +--[ RSA 2048]----+
    |       o         |
    |      o E        |
    |     . . o       |
    |    o o o.o      |
    |   . O oS .o     |
    |    + o o..      |
    |       =...      |
    |       .*o       |
    |      o=o        |
    +-----------------+
    $ echo 'asdfasdf' > ~/.myscrt
    $ chmod 0600 ~/.myscrt
    $ ls -altr ~/.myscrt
    -rw------- 1 me me 9 Feb 16 19:00 /home/me/.myscrt
    $ cat ~/.myscrt
    asdfasdf
    $ ls -ltr
    total 12
    -rw-r--r-- 1 me me  400 Feb 16 18:59 id_rsa.pub
    -rw------- 1 me me 1766 Feb 16 18:59 id_rsa
    -rwx------ 1 me me  151 Feb 16 19:04 j
    $ cat j
    #!/bin/bash
    PASS="$(<$HOME/.myscrt)"
    install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
    cat id_rsa | SSH_ASKPASS="$PWD/ps.sh" ssh-add - && shred -n3 -uz     $PWD/ps.sh
    $ ./j
    ‘/dev/fd/63’ -> ‘/tmp/so/ps.sh’
    Identity added: (stdin) ((stdin))
    $ ls
    id_rsa  id_rsa.pub  j
    

    So, one thing to quickly note about this method is that listing the identities loaded into ssh-agent will only show that stdin was loaded:

    $ ssh-add -D
    All identities removed.
    $ ssh-add -l
    2048 ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d (stdin) (RSA)
    $ ./j
    ‘/dev/fd/63’ -> ‘/tmp/so/ps.sh’
    Identity added: (stdin) ((stdin))
    $ ssh-add -l
    2048 ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d (stdin) (RSA)