Non-interactively add a password to the SSH agent
This is a small
expect (1) script to make it easy to add a private SSH key to the running SSH agent by passing along the key's password to ssh-add.
The script takes 2 arguments:
- The SSH private key filename
- The SSH private key password filename
Due to security concerns, only reading a password from a file is allowed. When using a file with a plaintext password like this, you must make sure that the file only has minimal permissions (ie. only you should be able to read from it) and it should be deleted as soon as possible.
If you want to be extra paranoid, you can make sure to only write the file into memory using a filesystem like tmpfs (remember that tmpfs is still readable from RAM, even if it's encrypted so that doesn't eliminate attack vectors completely). You can also try using something like
shred (1) to overwrite the contents of your file before deleting it in order to make sure it's not recoverable.
Use With Gitlab CI and Ansible
The reason this script is here in the first place, is for simplifying the process of using a password-protected SSH key in order to access remote servers through Ansible. Below is an example of what you would need in order to accomplish this task. Your particular needs may be a little bit different, but the gist should be the same:
before_script: - yum -y install expect jq python-pip openssh-clients which - pip install yq[yaml] - mkdir -p $HOME/.ssh - touch $HOME/.ssh/id_rsa - chmod 600 $HOME/.ssh/id_rsa - echo $KEY | base64 -d > $HOME/.ssh/id_rsa - curl -vs https://gitlab.triumf.ca/snippets/52/raw > ssh-agent-add-password.exp - chmod 755 ssh-agent-add-password.exp - eval `ssh-agent` - | for h in $(yq -r '.all.children["my-group"].hosts | keys | .' inventory.yml); do echo $KEY_PASSWORD > tmppw ./ssh-agent-add-password.exp $HOME/.ssh/id_rsa tmppw rm -f tmppw done
In this example,
$KEY is an SSH key supplied through the Gitlab CI variables section and represents a base64 encoded SSH private key. The
$KEY_PASSWORD value is also supplied through the Gitlab CI variables and represents the password used to unlock the private key. We're also assuming that this Ansible deployment is using a
inventory.yml file to map out the deployment inventory and that
my-group is the group that lists all of the hosts we're connecting to. If this is not the case, then you might need to change the for loop or possibly remove it and just do manual calls to the
ssh-agent-add-password.exp; one after the other.
This example also gets more complicated with multiple hosts that have different keys, but should still follow the same general flow.
Finally, we assume a CentOS system (for the initial
yum command). If you're running this on a different O/S or distribution, you will need to install dependencies in your own way.