I am trying to add a key to ssh-agent
and want ssh-add
to read the password from the key file I'm using. How is this possible?
How do I automate this process from the shell script?
I am trying to add a key to ssh-agent
and want ssh-add
to read the password from the key file I'm using. How is this possible?
How do I automate this process from the shell script?
Depending on your distribution and on the version of ssh-add you may be able or not to use the -p
option of ssh-add that reads the passphrase from stdin in this way:
cat passfile | ssh-add -p keyfile
If this is not working you can use Expect, a Unix tool to make interactive applications non-interactive. You'll have to install it from your package manager.
I have written a tool for you in expect. Just copy the content in a file named ssh-add-pass and set executable permissions on it (chmod +x ssh-add-pass
). You can also copy it to /usr/bin or /usr/local/bin to be accessible from the $PATH search.
#!/bin/bash
if [ $# -ne 2 ] ; then
echo "Usage: ssh-add-pass keyfile passfile"
exit 1
fi
eval $(ssh-agent)
pass=$(cat $2)
expect << EOF
spawn ssh-add $1
expect "Enter passphrase"
send "$pass\r"
expect eof
EOF
The usage is simply: ssh-add-pass keyfile passfile
eval $(ssh-agent)
with ssh-agent bash
or with eval `ssh-agent -s`
–
Omniumgatherum eval
ssh-agent -s
and it ran all commands but after that script return back to original bash and it lost that key. Its all depend on spawning bash and use same bash to run ssh-add –
Pastiche Similar to the answer by kenorb, but doesn't save the secret in a file:
$ SSH_ASKPASS=/path/to/ssh_give_pass.sh ssh-add $KEYFILE <<< "$KEYPASS"
where ssh_give_pass.sh is:
#!/bin/bash
# Parameter $1 passed to the script is the prompt text
# READ Secret from STDIN and echo it
read SECRET
echo $SECRET
If you have you secret in a $KEYPASSFILE, read it into a variable first with
KEYPASS=`cat $KEYPASSFILE`
Also make sure that ssh_give_pass.sh is not editable by unauthorized users - it will be easy to log all secrets passed through the script.
DISPLAY=:0 SSH_ASKPASS=/path/to/ssh_give_pass.sh ssh-add $KEYFILE <<< "$KEYPASS"
–
Politicking ${DISPLAY:=0}
–
Forked SSH_ASKPASS_REQUIRE=force
instead –
Oxalis Here is some workaround for systems not supporting -p
:
$ PASS="my_passphrase"
$ install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
$ cat id_rsa | SSH_ASKPASS="$PWD/ps.sh" ssh-add - && rm -v "$PWD/ps.sh"
where ps.sh
is basically your script printing your passphrase. See: man ssh-add
.
To make it more secure (to not keep it in the same file), use mktemp
to generate a random private file, make it executable (chmod
) and make sure it prints the passphrase to standard output once executed.
ssh-add
allows you to swap-out the SSH_ASKPASS
binary per-call like that. –
Undercroft ps.sh
is a security risk, and a rm is a quite weak way to hide it, you should at least do a shred -u
, but even shred is inefficient on modern fs like ext4 and a lot more on btrfs. So create your file in shared memory /dev/shm
or /run/user/<uid>
, and shred it after use. An other option is to put ps.sh
on an encrypted filesystem. –
Endurant DISPLAY=:0
as the man page for ssh-add suggests (Ubuntu 16.04) –
Anguine On my Ubuntu system, none of the answers worked:
ssh-add
did not support the -p
option.ssh-add
ignored SSH_ASKPASS, insisting on prompting for the passphrase on the controlling terminal.expect
.What worked in my case was:
password_source | SSH_ASKPASS=/bin/cat setsid -w ssh-add keyfile
password_source isn't really a program: it just represents whatever feeds the passphrase to ssh-add
. In my case, it is a program that executes setsid
and writes the passphrase to its stdin. If you keep your passphrase in a file, you are responsible for making the simple modifications: I will not enable you to hurt yourself.
setsid
was already installed, and detaches the controlling terminal so that ssh-add
will not try to use it to prompt for the passphrase. -w
causes setsid
to wait for ssh-add
to exit and make its return code available. /bin/cat
has the same effect as the script Ray Shannon provided, but uses a standard tool instead of replicating its functionality with a script.
Came here looking for a specific solution, to load ssh-add from pass
the unix password manager. Thanks to the great answers here, I put together a script that does this for me:
#!/usr/bin/env bash
# Get password from pass
set -euo pipefail
keyfile=$(echo "$1" | /usr/bin/env sed -n 's/Enter passphrase for \(.*\):\s*$/\1/p');
echo "Extracted key filename $keyfile" >&2
[[ -z "${keyfile}" ]] && exit 1
comment=$(/usr/bin/env ssh-keygen -l -f "$keyfile" | /usr/bin/env awk '{print $3}')
echo "Comment from keyfile $keyfile is $comment" >&2
[[ -z "${comment}" ]] && exit 1
passphrase=$(/usr/bin/env pass show "ssh/$comment")
[[ -z "${passphrase}" ]] && exit 1
echo "got passphrase for comment $comment: XXX" >&2
echo "$passphrase"
Invoked with this:
env SSH_ASKPASS=/usr/local/bin/pass-ssh-askpass.sh SSH_ASKPASS_REQUIRE=force ssh-add
This wouldn't be possible without the answers here, so thanks for that, making this as community wiki for the greater good.
Once my ssh-add
supports the -p
option, I'll look into a different solution, but until then this will have to do.
Shameless plug: https://github.com/YarekTyshchenko/pass-ssh-askpass
With this minimal changes worked for me this bash script of @enrico.basis
#!/bin/bash
if [ $# -ne 2 ] ; then
echo "Usage: ssh-add-pass passfile keyfile"
exit 1
fi
eval 'ssh-agent -s'
passwordToFileSSH=$1
pathFileSSH=$2
expect << EOF
spawn ssh-add $pathFileSSH
expect "Enter passphrase"
send "$passwordToFileSSH\r"
expect eof
EOF
The best way is to generate a key without a passphrase
© 2022 - 2024 — McMap. All rights reserved.
ssh-add -K
orssh-add --apple-use-keychain
; superuser.com/questions/1127067/… – Simplicidentate