What do I want to achieve? Using a single Ansible playbook,
---
- name: setup ssh-agent
hosts: localhost
gather_facts: false
vars_files:
- ../vars.yml
vars:
ansible_ssh_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/{{sshkeyname}}"
ansible_ssh_pass: "{{sshpassphrs}}"
tasks:
- name: Start ssh-agent and Retrieve the SSH_AUTH_SOCK and SSH_AGENT_PID environment variables
shell: |
eval $(ssh-agent -s) > /dev/null
echo '{"SSH_AUTH_SOCK":"'$SSH_AUTH_SOCK'","SSH_AGENT_PID":"'$SSH_AGENT_PID'"}'
register: env_vars_stdout
- name: save to env_vars
set_fact:
env_vars: "{{ env_vars_stdout.stdout }}"
- name: add {{ansible_ssh_private_key_file}} to ssh-agent
environment: "{{ env_vars }}"
expect:
command: ssh-add {{ ansible_ssh_private_key_file }}
responses:
passphrase: "{{ ansible_ssh_pass }}"
- name: main jobs
hosts: all
gather_facts: false
environment: "{{ hostvars['localhost']['env_vars'] }}"
vars_files:
- ../vars.yml
vars:
ansible_user: "{{username}}"
tasks:
- name: Do a ping test
shell: ping -c 20 -w 50 fb.me
It throws an error for the ping test, as destination hosts are unreachable with msg "Failed to connect to the host via ssh".
I know this is quite a hacky way, adding the key through ssh-agent in the terminal session would have been straightforward. But anyway to achieve this?
I think the issue here is that, the enviroment keyword, as per the doc, helps in setting the remote environment. i.e. by then the SSH connection to the remote host should have been made.
In order to change the arguments, which are used to connect to the remote_host, we need to use the ansible_ssh_common_args
variable. You can use the IdentityAgent
option, in the ssh_config, to specify the SSH Agent socket.
I have added a couple of statements to your solution.
---
- name: setup ssh-agent
hosts: localhost
gather_facts: false
vars_files:
- ../vars.yml
vars:
ansible_ssh_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/{{sshkeyname}}"
ansible_ssh_pass: "{{sshpassphrs}}"
tasks:
- name: Start ssh-agent and Retrieve the SSH_AUTH_SOCK and SSH_AGENT_PID environment variables
shell: |
eval $(ssh-agent -s) > /dev/null
echo '{"SSH_AUTH_SOCK":"'$SSH_AUTH_SOCK'","SSH_AGENT_PID":"'$SSH_AGENT_PID'"}'
register: env_vars_stdout
- name: save to env_vars
set_fact:
env_vars: "{{ env_vars_stdout.stdout }}"
ssh_auth_sock: "{{ env_vars_stdout.stdout | from_json | json_query('SSH_AUTH_SOCK') }}" # install jmespath if not already present
- name: add {{ansible_ssh_private_key_file}} to ssh-agent
environment: "{{ env_vars }}"
expect:
command: ssh-add {{ ansible_ssh_private_key_file }}
responses:
passphrase: "{{ ansible_ssh_pass }}"
- name: main jobs
hosts: all
gather_facts: false
environment: "{{ hostvars['localhost']['env_vars'] }}"
vars_files:
- ../vars.yml
vars:
ansible_user: "{{username}}"
ansible_ssh_common_args: "-o 'IdentityAgent={{ hostvars['localhost']['ssh_auth_sock'] }}'"
tasks:
- name: Do a ping test
shell: ping -c 20 -w 50 fb.me
When you run the job, we can pass the -vvv
option to, see that, our agent is actually being used when making a connection to the remote_host
I saw something like below, in the output
<remote.host> SSH: EXEC ssh -C -o IdentityAgent=/var/folders/1s/rwv4vb6n01ld3sxfzqp5svtm0000gn/T//ssh-KGeKsXlC8bGO/agent.14769 -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PasswordAuthentication=no -o 'User="phanirajgoutham"' -o ConnectTimeout=10 remote.host
You could see the IdentityAgent
option being passed along with the other options, when making a connection to the remote_host.
Please let me know if this does not work for you.