Need to use ansible to connect to a host via a jump host using a key in the jump host

Viewed 1381

I have a machine that is accessible through a jump host.

What I need is this.

A is my local machine

B is the jump host

C is the destination machine

I need to connect to C using ansible via B but use a private key in B.

Current config is the inventory file is as shown below

    [deployment_host:vars]
ansible_port = 22 # remote host port
ansible_user = <user_to_the_Target_machine> # remote user host
private_key_file = <key file to bastion in my laptop> # laptop key to login to bastion host
ansible_ssh_common_args='-o StrictHostKeyChecking=no -o ProxyCommand="ssh -o \'ForwardAgent yes\' <user>@<bastion> -p 2222 \'ssh-add /home/<user>/.ssh/id_rsa && nc %h 22\'"'
[deployment_host]
10.200.120.218  ansible_ssh_port=22 ansible_ssh_extra_args='-o StrictHostKeyChecking=no'

How can I do that

I have not made any changes to my ssh config and when i run ansible like below

ansible -vvv all -i inventory.ini -m shell -a 'hostname'

I get this error

ansible 2.9.0
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/dist-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.9.5 (default, May 11 2021, 08:20:37) [GCC 10.3.0]
No config file found; using defaults
host_list declined parsing /root/temp_ansible/inventory.ini as it did not pass its verify_file() method
script declined parsing /root/temp_ansible/inventory.ini as it did not pass its verify_file() method
auto declined parsing /root/temp_ansible/inventory.ini as it did not pass its verify_file() method
yaml declined parsing /root/temp_ansible/inventory.ini as it did not pass its verify_file() method
Parsed /root/temp_ansible/inventory.ini inventory source with ini plugin
META: ran handlers
<10.200.120.218> ESTABLISH SSH CONNECTION FOR USER: <user> # remote user host
<10.200.120.218> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="<user> # remote user host"' -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o 'ProxyCommand=ssh -o '"'"'ForwardAgent yes'"'"' <user>@35.223.214.105 -p 2222 '"'"'ssh-add /home/<user>/.ssh/id_rsa && nc %h 22'"'"'' -o StrictHostKeyChecking=no -o ControlPath=/root/.ansible/cp/ec0480070b 10.200.120.218 '/bin/sh -c '"'"'echo '"'"'"'"'"'"'"'"'~<user> # remote user host'"'"'"'"'"'"'"'"' && sleep 0'"'"''
<10.200.120.218> (255, b'', b'kex_exchange_identification: Connection closed by remote host\r\nConnection closed by UNKNOWN port 65535\r\n')
10.200.120.218 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: kex_exchange_identification: Connection closed by remote host\r\nConnection closed by UNKNOWN port 65535",
    "unreachable": true
}
1 Answers

I figured out the solution.

For me this was adding both entries of my server A and B into the ~/.ssh/config

Host bastion1
    HostName <IP/FQDN>
    StrictHostKeyChecking no
    User <USER>
    IdentityFile <File to log into the first bastion server> # should be present in your local machine.
Host bastion2
    HostName <IP/FQDN>
    StrictHostKeyChecking no
    User <USER>
    IdentityFile <File to log into the second bastion server> # should be present in your local machine. 
    ProxyJump bastion

Then editing the inventory file like shown below.

[deployment_host]
VM_IP  ansible_user=<vm_user> ansible_ssh_extra_args='-o StrictHostKeyChecking=no' ansible_ssh_private_key_file=<file to login to VM> 
[deployment_host:vars]
ansible_ssh_common_args='-J bastion1,bastion2'

Then any ansible command with this inventory should work without issue

❯ ansible all -i inventory.ini -m shell -a "hostname"
<VM_IP> | CHANGED | rc=0 >>
development-host-1

NOTE: All these ssh keys should be in your local system. You can get the bastion2 private key from bastion1 using ansible and the same for the VM from bastion2 using ansible ad-hoc fetch

Related