ssh-add when ssh-agent fails - ssh

I am trying to write a script that makes use of {ssh,gpg}-agents effortless (like keychain, but I discovered it too late). This script will be run in a sensitive environment, so I set a timeout in order to remove the keys from the agent after some time.
I managed to write the spawn/reuse part but now, I want ssh-add to be called automatically when the user is opening a ssh connection if the agent has no proper key.
Is there any way to make ssh-agent call ssh-add on failure or something better ?

What I am doing (assuming the key has a distinctive name)
I have a script in ~/bin/ (which is in my PATH)
!/bin/bash
if ! ssh-add -l | grep -q nameOfmyKey
then
ssh-add -t 2h ~/path-to-mykeys/nameOfmyKey.key
fi
ssh myuser#myserver.example.net
ssh -l lists all keys currently active in the agent.
The parameter -t ensures that the key is enabled for a restricted time only.

Related

what is the difference between ssh-add and ssh-keygen

I know ssh-keygen it can create a public and private key inside ~/.ssh by default as id_rsa and id_rsa.pub
eg:
ssh-keygen
Later on we add the id_rsa.pub to the known_hosts of the server, so that we can do
ssh user#hostname.com
But I see we use ssh-add to pass private key so that we can login without the need of password
Eg:
ssh-add <(echo "$SSH_PRIVATE_KEY")
for this we need to start ssh-agent
eval $(ssh-agent -s)
and then
ssh user#hostname.com
Assuming there is already ~/.ssh/id_rsa. So here how does ssh know which private key it has to use
ssh, if it finds a value for SSH_AUTH_SOCK in the environment, will ask that agent for all private keys and try them one by one, unless you tell it which specific key to use via the -i command-line option or the IdentitiyFile configuration option.
The main benefit of ssh-agent is that it can hold unencrypted keys in memory, so that you only need to use the key's passphrase once, when it is added to the agent, rather than every time ssh tries to use the key.
(The other benefit is that if you have multiple ssh connections in a chain, you can keep the private keys in an agent on the first machine. The ssh client can forward the agent connection to the remote machine, where ssh clients can access the agent to use keys for the next step in the chain.)

How to run an ansible-playbook with a passphrase-protected-ssh-private-key?

I have created an autoscaling group for Amazon EC2 and I have added my public key when I created the AMI with packer, I can run ansible-playbook and ssh to the hosts.
But there is a problem when I run the playbook like this
ansible-playbook load.yml I am getting this message that I need to write my password
Enter passphrase for key '/Users/XXX/.ssh/id_rsa':
Enter passphrase
for key '/Users/XXX/.ssh/id_rsa':
Enter passphrase for key
'/Users/XXX/.ssh/id_rsa':
The problem is it doesn't accept my password (I am sure I am typing my password correctly).
I found that I can send my password with ask-pass flag, so I have changed my command to ansible-playbook load.yml --ask-pass and I got some progress but again for some other task it asks for the password again and it didn't accept my password
[WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] *************************************************************************************************************
TASK [ec2_instance_facts] ****************************************************************************************************
ok: [localhost]
TASK [add_host] **************************************************************************************************************
changed: [localhost] => (item=xx.xxx.xx.xxx)
changed: [localhost] => (item=yy.yyy.yyy.yyy)
PLAY [instances] *************************************************************************************************************
TASK [Copy gatling.conf] *****************************************************************************************************
ok: [xx.xxx.xx.xxx]
ok: [yy.yyy.yyy.yyy]
Enter passphrase for key '/Users/ccc/.ssh/id_rsa': Enter passphrase for key '/Users/ccc/.ssh/id_rsa':
Enter passphrase for key '/Users/ccc/.ssh/id_rsa':
Enter passphrase for key '/Users/ccc/.ssh/id_rsa':
Enter passphrase for key '/Users/ccc/.ssh/id_rsa':
If I don't use ask-pass flag even the task [Copy gatling.conf] doesn't complete and complaining about could not access the hosts. By adding the flag this part passes, but my next task again asks for pass.
How should I solve this issue? What am I doing wrong here?
In ansible There is no option to store passphrase-protected private key
For that we need to add the passphrase-protected private key in the ssh-agent
Start the ssh-agent in the background.
# eval "$(ssh-agent -s)"
Add SSH private key to the ssh-agent
# ssh-add ~/.ssh/id_rsa
Now try running ansible-playbook and ssh to the hosts.
I solved it by running ssh-add once and use it like if it's not password protected.
Building up on #javeed-shakeel's answer, I added the following lines to my .bashrc:
command -v ansible > /dev/null &&
alias ansible='ssh-add -l > /dev/null || ssh-add 2> /dev/null && ansible'
command -v ansible-playbook > /dev/null &&
alias ansible-playbook='ssh-add -l > /dev/null || ssh-add 2> /dev/null && ansible-playbook'
This will run ssh-add before ansible(-playbook) iff there was no key added to the ssh-agent, yet. This has the advantage that one does not need to run ssh-add by hand and one will be asked for the passphrase only if it is necessary.
A passphrase is something else than a password. When ssh asks for a password, then you login as a user with a password that is checked by the computer you ssh into. It might be a company-wide password (AD, LDAP, etc.), or a local admin password.
A passphrase is used to encrypt the private key of your ssh key-pair. Typically the key-pair is generated with ssh-keygen, this command asks for a passphrase twice when you create your key-pair. That is for security, because when there is no passphrase on the private key, then anyone with a copy of the file can impersonate you! The passphrase is an added factor to the security.
ssh-agent is a program that creates a session for the use of your key-pair.
If you want to automate in GitLab with the use of an encrypted ssh key-pair this might help:
##
## Install ssh-agent if not already installed.
## (change apt-get to yum if you use an RPM-based image)
##
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
##
## Run ssh-agent (on the Ansible control host)
##
- eval $(ssh-agent)
##
## Create the SSH directory and give it the right permissions
##
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
## Create a shell script that will echo the environment variable SSH_PASSPHRASE
- echo 'echo $SSH_PASSPHRASE' > ~/.ssh/tmp && chmod 700 ~/.ssh/tmp
## If ssh-add needs a passphrase, it will read the passphrase from the current
## terminal if it was run from a terminal. If ssh-add does not have a terminal
## associated with it but DISPLAY and SSH_ASKPASS are set, it will execute the
## program specified by SSH_ASKPASS and open an X11 window to read the
## passphrase. This is particularly useful when calling ssh-add from a
## .xsession or related script. Setting DISPLAY=None drops the use of X11.
## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
## We're using tr to fix line endings which makes ed25519 keys work
## without extra base64 encoding.
## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
##
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | DISPLAY=None SSH_ASKPASS=~/.ssh/tmp ssh-add -
##
## Use ssh-keyscan to scan the keys of your private server. Replace example.com
## with your own domain name. You can copy and repeat that command if you have
## more than one server to connect to.
##
- ssh-keyscan example.com >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts

How to make an SSH RSA key auto accept?

I need to check a bunch of servers via SSH (RAM, disk, CPU model, etc).
I want to make a script for it. But the RSA key yes/no is getting in the way.
Is it possible to auto accept the RSA key while connecting to the server via SSH?
(I.e. ssh root#ip "yes" or some workaround?)
To tell ssh not to worry about host keys, simply set the StrictHostKeyChecking option to no, i.e.
ssh -o StrictHostKeyChecking=no root#ip
If you also want to pass the password to it, you can do that using sshpass:
sshpass -p your_password ssh -o StrictHostKeyChecking=no root#ip
However, you'd be much better off using an ssh agent (such as PAgeant) and ssh key pairs - better than having your password hard-coded into a script somewhere.

How to stop SSH working with removed private key

On Ubuntu 14.04 I have a private key in:
~/.ssh/id_rsa
I have installed the public key on the server I wish to connect to and indeed when I run the following, I do connect as expected:
ssh me#my-server-ip.com
I then deleted the private key on the client but running the above command still connects me. This leads me to believe that the SSH binary is running in some kind of daemon mode wherein it is caching the private key in memory? Is that correct? Short of a reboot, how do I 'flush' SSH to stop using the private key. Thanks
Run the following command after removing ~/.ssh/id_rsa
ssh-add -D
This commando removes all cached ssh identities from the ssh-agent.
If you type ssh me#my-server-ip.com now, the password prompt will show.
You can check with ssh-add -L what identities the ssh-agent has cached.
I know I'm a little late to this party, but for the enlightenment of others...
It sounds like you have your private SSH key (identity) cached in ssh-agent. Now it is worth noting that ssh-agent does not retain the key cache over a reboot or logout/login cycle, although some systems depending on configuration may add your key during either of those processes. However, in your instance, a reboot or possibly a logout/login cycle would remove the private key from the agent's cache. This is because you have already removed the ~/.ssh/id_rsa file and it therefore cannot be re-initialized into the agent.
For everyone else who may not have yet deleted their ~/.ssh/id_rsa file(s) or if you don't want to reboot or logout/in right now the following should prove useful.
First, you will want to remove any ~user/.ssh/id_rsa files which you wish to no longer be cached by ssh-agent.
Next, verify that there are, in fact, identities still being held open in 'ssh-agent' by running the following command:
ssh-add -L
This will list the public key parameters of all identities that the agent has actively cached. (Note: ssh-add -l will instead list the fingerprints of all keys/identities that are actively cached.) For each that you would like to remove you should run the following:
ssh-add -d /path/to/matching/public/key/file
If you just want to clear out ALL keys/identities from the agent then run this instead:
ssh-add -D
At this point, the key(s) desired to be removed will be no longer accessible to the agent and with the actual identity file removed, there shouldn't' be any way possible for an attempted remote SSH connection with that user to connect without using a different authorization method if configured/allowed.

How to make ssh receive the password from stdin

How can you make SSH read the password from stdin, which it doesn't do by default?
based on this post you can do:
Create a command which open a ssh session using SSH_ASKPASS (seek SSH_ASKPASS on man ssh)
$ cat > ssh_session <<EOF
export SSH_ASKPASS="/path/to/script_returning_pass"
setsid ssh "your_user"#"your_host"
EOF
NOTE: To avoid ssh to try to ask on tty we use setsid
Create a script which returns your password (note echo "echo)
$ echo "echo your_ssh_password" > /path/to/script_returning_pass
Make them executable
$ chmod +x ssh_session
$ chmod +x /path/to/script_returning_pass
try it
$ ./ssh_session
Keep in mind that ssh stands for secure shell, and if you store your user, host and password in plain text files you are misleading the tool an creating a possible security gap
You can use sshpass which is for example in the offical debian repositories. Example:
$ apt-get install sshpass
$ sshpass -p 'password' ssh username#server
You can't with most SSH clients. You can work around it with by using SSH API's, like Paramiko for Python. Be careful not to overrule all security policies.
Distilling this answer leaves a simple and generic script:
#!/bin/bash
[[ $1 =~ password: ]] && cat || SSH_ASKPASS="$0" DISPLAY=nothing:0 exec setsid "$#"
Save it as pass, do a chmod +x pass and then use it like this:
$ echo mypass | pass ssh user#host ...
If its first argument contains password: then it passes its input to its output (cat) otherwise it launches whatver was presented after setting itself as the SSH_ASKPASS program.
When ssh encounters both SSH_ASKPASS AND DISPLAY set, it will launch the program referred to by SSH_ASKPASS, passing it the prompt user#host's password:
An old post reviving...
I found this one while looking for a solution to the exact same problem, I found something and I hope someone will one day find it useful:
Install ssh-askpass program (apt-get, yum ...)
Set the SSH_ASKPASS variable (export SSH_ASKPASS=/usr/bin/ssh-askpass)
From a terminal open a new ssh connection without an undefined TERMINAL variable (setsid ssh user#host)
This looks simple enough to be secure but did not check yet (just using in a local secure context).
Here we are.
FreeBSD mailing list recommends the expect library.
If you need a programmatic ssh login, you really ought to be using public key logins, however -- obviously there are a lot fewer security holes this way as compared to using an external library to pass a password through stdin.
a better sshpass alternative is :
https://github.com/clarkwang/passh
I got problems with sshpass, if ssh server is not added to my known_hosts sshpass will not show me any message, passh do not have this problem.
I'm not sure the reason you need this functionality but it seems you can get this behavior with ssh-keygen.
It allows you to login to a server without using a password by having a private RSA key on your computer and a public RSA key on the server.
http://www.linuxproblem.org/art_9.html