3sky's notes

Minimal blog about IT

Ansible with jump host

2021-03-23 4 min read 3sky

Welcome

Long time no sea. It’s not a typo last time when I saw the see was in September in Greece. Almost the same thing I can say about Ansible. The last time when I used this tool for resolving real problems was more-less 2years ago. To be honest, during this period Ansible becomes (in my mind at least) just another boring and old-fashioned tool. Who is using Ansible if we have containers, Kubernetes Engines and Serverless? Only boring people. However, do you know who does not use Ansible? People without personal life or interesting problem to solve. I’m boring…

Problem

As you can assume I’m not an Ansible uber-master, I know most of the bases, but still, sometimes I stuck with some small, hidden option or strange use case a bit too long. That will be one of this use-case. Run Ansible through jump server.

Scenario

I have a VM. Brand new and fresh machine with some awesome hardware - let’s say GPU monster for machine learning processes. It’s based in some office. No static IP. I can connect to this machine via SSH Tunneling through another machine. How to make the connection easier?

SSH config

If You wondering why Linux user don’t use tools like MobaXterm, ~/.ssh/config is the answer. Basic config will looks like that:

Host test-3sky-dev
    # test, Suse
    HostName 3.22.11.33
    User kuba
    Port 31
    IdentityFile ~/.ssh/id_rsa_xy

With that I can only type ssh test-3sky-dev and buum I’m on my test VM. Cool.

Add jump host

For our case let’s assume that I can access monster-3sky-dev only from test-3sky-dev. How to do that? Another simple example.

Host test-3sky-dev
    # test, Suse
    HostName 3.22.11.33
    User kuba
    Port 31
    IdentityFile ~/.ssh/id_rsa_xy

Host monster-3sky-dev
    # prod, ubuntu
   HostName 12.22.11.33
   User kuba
   Port 45
   ProxyJump test-3sky-dev

Authentication

I like to avoid password authentication so, let’s use ssh-copy-id

# on test-3sky-dev machine
ssh-keygen -t rsa -b 4096 -C "test-3sky-dev"
ssh-copy-id -i ~/.ssh/id_rsa_yx.pub kuba@12.22.11.33 -p 45

And configure `~/.ssh/config` on my jump station

Host monster-3sky-dev
   HostName 12.22.11.33
   User kuba
   Port 45
   IdentityFile ~/.ssh/id_rsa_yx

Finally

Just run from my workstation - sweet.

ssh monster-3sky-dev

Implementation

As you can see I can connect to VM via SSH Tunneling, it was simple and rather fast. Now integration with Ansible. Let’s write some super simple playbook, like:

---
- name: ADD NEW USER
  gather_facts: false
  user: kuba
  hosts: monster-3sky-dev
  become: yes
  vars:
    user: "adam"

  tasks:
    - name: Ensure group "{{ user }}" exists
      ansible.builtin.group:
        name: "{{ user }}"
        state: present

    - name: Add the user "{{ user }}"
      ansible.builtin.user:
        name: "{{ user }}"
        shell: /bin/bash
        groups:
          - "{{ user }}"
          - docker
        append: yes
        home: /home/{{ user }}
        password: "{{ 'password' | password_hash('sha512') }}"
        update_password: on_create

    - name: Creat home dirs
      ansible.builtin.file:
        path: "{{ item }}"
        state: directory
        mode: '0755'
        owner: "{{ user }}"
        group: "{{ user }}"
      loop:
        - /home/{{ user }}
        - /home/{{ user }}/bin
        - /home/{{ user }}/tools

Now I need to provide only differences between normal host, and host behind the firewall.

Look on my inventory file:

[gpu]
monster-3sky-dev ansible_python_interpreter=/usr/bin/python3

There is no IP. And that’s the point. While executing the ansible-playbook command I need to specify one environment variable - ANSIBLE_SSH_ARGS. And that is how it looks:

ANSIBLE_SSH_ARGS="-F /home/kuba/.ssh/config" ansible monster-3sky-dev -m ping -i host.ini
monster-3sky-dev | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

One important thing. Hostname from inventory file needs to match with Host from `.ssh/config` file.

How to run a playbook? In the almost same way.

ANSIBLE_SSH_ARGS="-F /home/kuba/.ssh/config" ansible-playbook add_users/add_user.yaml -i host.ini

Summary

OK, so that is it. Nothing very fancy, but It takes me a while to find the right solution for me. Also is one of these things which are worth working with. No more need to googling the solution I have it here. This article was written in org-mode, then converted into Hugo MD file. That was an interesting adventure, especially when Emacs become my main tool as I said. Ah and OpenSuse. Recently I had some issue with Fedora related to dns-resolver. Since the beginning of March, I’m a happy user of OpenSuse Tumbleweed and I need to say it’s an awesome distro. Something between Archlinux(it’s rolling release system) and Fedora(easy to use, and stable). Maybe some longe review? I’m not sure, but until now I’m super happy with SUSE.