Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make ansible connect to windows host behind linux jump server

I want to provision Windows host that is in subnet accessible only with Linux jump host.

Windows machine uses winrm connection method. Linux jump server is available via SSH.

I have no problem accessing windows host if available directly with:

ansible_connection: winrm

If I try to delegate the task to the Linux jump server (that has direct access to Windows) by:

- name: Ping windows
  hosts: windows_machines
  tasks:
    - name: ping
      win_ping:
      delegate_to: "{{ item }}"
      with_items: "{{ groups['jump_servers'][0] }}"

it tries to connect to establish WINRM connection to the jump host. Not exactly what I had in mind.

Note that for windows_machines group I have group_vars defined:

ansible_port: 5986
ansible_connection: winrm
ansible_winrm_server_cert_validation: ignore

How should I provision Windows hosts via a bastion host?

like image 770
kwach Avatar asked Dec 17 '15 12:12

kwach


2 Answers

My priority was to have all the configuration in one place and not distribute part of Ansible to the bastion/jump host. I went for establishing ssh tunnel for the 5986 port. Here is the complete task:

- name: Tunneled configuration of Windows host in a subnet
  hosts: windows
  connection: local #This is the trick to connect to localhost not actual host
  gather_facts: no
  tasks:
    - name: First setup a tunnel
      local_action: command ssh -Nf -4 -o ControlPersist=1m -o ControlMaster=auto -o ControlPath="~/.ssh/mux2win-%r@%h:%p" -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o UserKnownHostsFile="/dev/null" -i {{ hostvars[item].ansible_ssh_private_key_file }} {{ hostvars[item].ansible_ssh_user }}@{{ hostvars[item].ansible_host }} -L {{ ansible_port }}:{{ actual_host }}:{{ ansible_port }}
      with_items:
        - "{{ groups['jump_servers'][0] }}" #I know my topology so I know which host to use
    - name: (optional) Second ensure it is up
      local_action: command ssh -O check -S "~/.ssh/mux2win-%r@%h:%p" {{ hostvars[item].ansible_ssh_user }}@{{ hostvars[item].ansible_host }}
      with_items:
        - "{{ groups['jump_servers'][0] }}"

    # ------- actual windows tasks (from ansible examples) ------------
    - name: Ping
      connection: local
      win_ping:
    - name: test raw module- run ipconfig
      raw: ipconfig
      register: ipconfig
    - debug: var=ipconfig

    - name: Test stat module- test stat module on file
      win_stat: path="C:/Windows/win.ini"
      register: stat_file

    - debug: var=stat_file

    - name: Check stat_file result
      assert:
          that:
             - "stat_file.stat.exists"
             - "not stat_file.stat.isdir"
             - "stat_file.stat.size > 0"
             - "stat_file.stat.md5"
    # ------- end of actual windows tasks ------------

    - name: Stop the tunnel. It would stop anyway after 1m.
      local_action: command ssh -O stop -S "~/.ssh/mux2win-%r@%h:%p" {{ hostvars[item].ansible_ssh_user }}@{{ hostvars[item].ansible_host }}
      with_items:
        - "{{ groups['jump_servers'][0] }}"

For this to work I had to modify slightly the inventory file:

[windows]
windows1 ansible_host=127.0.0.1 ansible_ssh_user=Administrator  actual_host=192.168.0.2 (...)

Ansible can connect by accessing 5986 port on local host, so ansible_host has to be set to 127.0.0.1 and to have the information on the actual ip of the Windows machine a custom variable actual_host is set.

like image 85
kwach Avatar answered Nov 11 '22 21:11

kwach


That's not what the delegate_to option on a task does.

Instead, delegate_to will make sure that the task only runs against a specific node rather than the group that is listed in the role/playbook.

So for example you may have a role that sets up MySQL on a cluster of boxes that are defined generically but then want to do specific configuration/tasks on the master alone, leaving the master to then replicate these out to the slaves.

You can do SSH proxying where you forward SSH connections through a bastion/jump host but that obviously needs your connection to be SSH throughout which doesn't help you.

The only thing I can think of to help you here would be to use Ansible directly from the bastion/jump host possibly triggered by Ansible (or anything else really) from your machine outside of the protected zone.

like image 44
ydaetskcoR Avatar answered Nov 11 '22 20:11

ydaetskcoR