Connect to a Windows machine via Bastion using Ansible
In an AWS environment, you do not want your machines to be exposed to the internet. Therefore you create another instance (Bastion) and using tunnels, you can access your machines that have only a private IP address.
During installation of these machines, ansible connects to your machines through the Bastion. You can either have your Bastion as an Asible host or as a docker host and use a docker container with Ansible installed.
We have decided to use a docker container with Ansible installed because our Bastion cannot be a TeamCity agent and our TC agent does not have Asible installed. At first, we have decided to run a docker container on our TC agent that’ll run a docker container on the Bastion that’ll install our private IP machines. Problem was that we couldn’t see the output of Ansible tasks that are being executed on the Bastion till the task of running the docker from the TC agent has ended (succeedded or failed).
The only solution that can overcome the above problem is to use the Bastion only as a tunnel/proxy to the none public IP machines.
For Linux machines, it should have been quite strait forward but one thing was a bit tricky. Most of the examples that I had found on the internet claims that you need to create a custom ssh configuration file with something like: Host bastion Hostname ebsbastion.us-west-2.elb.amazonaws.com User ec2-user IdentityFile ~/Downloads/EBS-Jenkins.pem
Host 10.0.2.* IdentityFile ~/Downloads/EBS-Jenkins.pem User ec2-user ProxyCommand ssh -W %h:%p ec2-user@bastion
and ansible.cfg that looks like this: [ssh_connection] ssh_args = -o ControlPersist=15m -F ssh.config -q scp_if_ssh = True control_path = ~/.ssh/mux-%%r@%%h:%%p
The -F flag in the ansible.cfg gets the path to the custome ssh configuration file but that didn’t work for us. Only when we have used the user’s (~/.ssh/config) or system’s (/etc/ssh_config) ssh configuration path it worked. Even without mentioning that in the ansible.cfg file.
Now for the main part of the post, connecting to a windows machine through the bastion. I’ve used this blog post as a base instructions for my trial and error but for me this thread missed the most important part that Ansible doesn’t load any ssh configurations when connection to a non-ssh machine. So whatever I have tried to configure in the~/.ssh/config file, didn’t work. The only way to do it is to run the command that the blogger has suggested before running the ansible command. For example:
ssh -o "ControlMaster=auto" -o "ControlPersist=no" -o "ControlPath=~/.ssh/ssh-%r@%h:%p" -CfNq -D 0.0.0.0:1234 -p <bastion ssh port (22)> <bastion user>@<bastion IP> -i <path to private key> ansible-playbook <args> ssh -o "ControlPath=~/.ssh/ssh-%r@%h:%p" -p <bastion ssh port (22)> -O stop <bastion user>@<bastion IP> -i <path to private key>
The above three commands does the following: The first one creates a socket on the ansible host (in our case it is a docker container). The socket will be listening on port 1234 (-D 0.0.0.0:1234). whenever you are trying to reach a remote machine, all requests will go through the bastion using ssh. The bastion will act as a gateway for any request to a remote machine until you’ll kill the ssh command using the third command that uses -O stop
We will contact you as soon as possible.