Ansible SSH Key transfer from one host to another - local and remote

SSH Key-based authentication setup in LINUX (or) UNIX based OS is one of the major platform services related task and most frequently executed task by Unix admins. Ansible, An IT Automation tool could automate this tedious task as well.

SSH Key based authentication is indispensable when it comes to automation. Even some of the Ansible related tasks like SCP and RSYNC(synchronize) requires SSH Key based authentication to be enabled before running the ansible playbook.

In this post, we are going to see

How to enable the SSH Key-based authentication setup between multiple servers (or) hosts using Ansible ad-hoc commands and playbook

Or How to transfer SSH Keys using ansible playbook and ad-hoc commands.

The Objective

I have two Red Hat Enterprise Linux servers named mwiapp01 and mwiapp02 and I have to enable SSH key based (passwordless) authentication between them, in both directions.

 

 

Index

  1.  The Plan ( What we are trying to achieve in this article)
  2.  SSH Key creation and Exchange using Ansible AD HOC commands
  3.  SSH Key Creation and Exchange using Ansible Playbook
    1.  Using Shell Module
    2.  Using the authorized_key module
  4. SSH Key Creation and Exchange between multiple hosts 

 

The Plan

We are going to see how to achieve our objective (or) requirement using Ansible ad-hoc command and ansible playbook with and without SSH authorized_key module.

Now we will see how to do this with both Ansible ad-hoc commands and playbook.

Let us consider that I have already grouped these servers into a host group  named "app" in ansible_hosts inventory file

 Enable SSH Key based authentication using Ansible

 

Ansible AD-HOC Commands - Ansible SSH Key

In this method, we are going to use the Ansible ad hoc commands to perform the ssh key exchange and to copy the ssh keys between hosts. to know more about ansible ad hoc command refer to this article

Step 1:  Create SSH Private key using SSH-KEYGEN for the user weblogic

aksarav@middlewareinventory:~$ ansible app -m shell -a "ssh-keygen -q -b 2048 -t rsa -N '' -C 'creating SSH' -f ~/.ssh/id_rsa creates='~/.ssh/id_rsa'" -i ansible_hosts -b – become-user=weblogic

mwiapp02 | SUCCESS | rc=0 >>
mwiapp01 | SUCCESS | rc=0 >>

 

Step 2:  Make sure the Private key file is created

aksarav@middlewareinventory:~$ ansible app -m shell -a "ls -lrt  ~/.ssh/id_rsa" -i ansible_hosts -b – become-user=weblogic

mwiapp02 | SUCCESS | rc=0 >>
-rw----- – 1 weblogic weblogic 1679 Sep 10 17:25 /home/weblogic/.ssh/id_rsa
mwiapp01 | SUCCESS | rc=0 >>
-rw----- – 1 weblogic weblogic 1675 Sep 10 17:25 /home/weblogic/.ssh/id_rsa

 

Step 3:  Fetch the Key  Public Key from the servers to the ansible master

aksarav@middlewareinventory:~$ ansible app -m fetch -a "src='~/.ssh/id_rsa.pub' dest='buffer/{{inventory_hostname}}-id_rsa.pub' flat='yes'" -i ansible_hosts -b – become-user=weblogic

mwiapp02 | SUCCESS => {

    "changed": true,
    "checksum": "e128efa0cf4008d6f0a8652da44249d016a1c4fb",
    "dest": "/Users/aksarav/VirtualBox VMs/vagrantVM/buffer/mwiapp02-id_rsa.pub",
    "md5sum": "92332ffb86a310f2f7fa55e9e18e1f65",
    "remote_checksum": "e128efa0cf4008d6f0a8652da44249d016a1c4fb",
    "remote_md5sum": null
}

mwiapp01 | SUCCESS => {
    "changed": true,
    "checksum": "8ccbec5b91fd027e0e3ba8ca6fe2fa5e6faec0e8",
    "dest": "/Users/aksarav/VirtualBox VMs/vagrantVM/buffer/mwiapp01-id_rsa.pub",
    "md5sum": "f46044276aba3e4e6d4e918192676b76",
    "remote_checksum": "8ccbec5b91fd027e0e3ba8ca6fe2fa5e6faec0e8",
    "remote_md5sum": null

}

 

 

Step 4:   Copy the public key files to their respective destination servers to update authorized_keysmwiapp01 server's public key mwiapp01-id_rsa.pub would go to mwiapp02 server and vice versa

4a) Copy the mwiapp01 public key to mwiapp02 and update authorized key using ansible authorized_key module

aksarav@middlewareinventory:~$ ansible app -m authorized_key -a "user='weblogic' state='present' key='{{ lookup('file','buffer/mwiapp01-id_rsa.pub')}}'" – limit=mwiapp02 -i ansible_hosts -b – become-user=weblogic

mwiapp02 | SUCCESS => {
    "changed": true,
    "comment": null,
    "exclusive": false,
    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIRJwtqDW614wf9vKm51oTi3mNt4CkYXB7aLxhT1sEsZILUBYBLFqc78QB2eqelmbvgWN471CcR4XAYPxImB+ibZLhBuLqz49lPWpaVl+D55THVJFiCJ5MrXZBeSD73hRX0y1cR4kuPflaYLodz/sNOeScufomlhs+cQzwGpShSXqNtTJMl9KqqWnczBut6mdK5X/+ETruCTVigLrKfoAGDbpFHm2MNuVNud34HUffKcnqXz8ihbH1tmlW5jy+j6mMDsMNfIA7coP/bKoa2vVMX1sFpAQQCPhejLV26IYM5fYABVYrzxLtaiioylRyvSWl7NFTpgua+dtkbdV7aEWr creating SSH",
    "key_options": null,
    "keyfile": "/home/weblogic/.ssh/authorized_keys",
    "manage_dir": true,
    "path": null,
    "state": "present",
    "unique": false,
    "user": "weblogic",
    "validate_certs": true
}

 

 

4b)  Copy the mwiapp02's public key to mwiapp01and update authorized key using ansible authorized_key module

aksarav@middlewareinventory:~$ ansible app -m authorized_key -a "user='weblogic' state='present' key='{{ lookup('file','buffer/mwiapp02-id_rsa.pub')}}'" – limit=mwiapp01 -i ansible_hosts -b – become-user=weblogic

mwiapp01 | SUCCESS => {

    "changed": true,
    "comment": null,
    "exclusive": false,
    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDh50TVgulXoAEcRz0rn8SEXgVVoLpaebqk+PvhpRO27JbGC6WMlwpDNxEOdXjEn9Qlotm7zF/JUAjXaxEiPS7P5QSQjSTRxBu6YrTEV8sPnJyiocp+ll+1U74r18R88jE03+JOdxDroKROz3qpfT/vqzTHi6hnMdWs0n8vE09+oWPorW9lqrdWQ0C+AZShIWoSc/9nrLVDXci4rxhbwgrzyJbPd77sbV5yDoDfFLTKf3z3NQ48Gku/7zTdTNxrHOz8wop5Iqy7fqfH7jWAxlT0mWdJ6Ac+++ARj+x/v59hNfwMswc3rI2fE4tPNXIKC9tcnwVG3teaV1h4XxpHyWEt creating SSH",
    "key_options": null,
    "keyfile": "/home/weblogic/.ssh/authorized_keys",
    "manage_dir": true,
    "path": null,
    "state": "present",
    "unique": false,
    "user": "weblogic",
    "validate_certs": true
}

 

 

Step 5: Validate the SSH Key-based authentication between each server as weblogic user ( If everything we did is correct, we should be able to execute commands over SSH from one another.

5a)  Invoke SSH login from mwiapp01 to mwiapp02  and execute uname -n command

aksarav@middlewareinventory:~$ ansible app -m shell -a "ssh mwiapp02 'uname -a'" -i ansible_hosts -b – become-user=weblogic – limit=mwiapp01

mwiapp01 | SUCCESS | rc=0 >>
Linux mwiapp02 3.10.0-514.2.2.el7.x86_64 #1 SMP Wed Nov 16 13:15:13 EST 2016 x86_64 x86_64 x86_64 GNU/Linux

5b) Invoke SSH login from mwiapp02 to mwiapp01  and execute uname -n command

aksarav@middlewareinventory:~/VirtualBox VMs/vagrantVM$ ansible app -m shell -a "ssh mwiapp01 'uname -a'" -i ansible_hosts -b – become-user=weblogic – limit=mwiapp02

mwiapp02 | SUCCESS | rc=0 >>
Linux mwiapp01 3.10.0-514.2.2.el7.x86_64 #1 SMP Wed Nov 16 13:15:13 EST 2016 x86_64 x86_64 x86_64 GNU/Linux

 

Ansible Playbook  to Exchange keys between hosts

Type1: With Ansible Shell module and Typical Commands

 How to enable SSH Key based authentication using Ansible

In this method, We are not going to use any ansible in-built module and every step is done manually by executing the shell command. The Playbook contains the following tasks

  1. Create an SSH Private and Public Key using  ssh-keygen command
  2. Fetch generated key files from remote servers [mwiapp01,mwiapp02]  to ansible master
  3. Copy the file from the master to remote destination servers
  4. Add the public to the mentioned user's authorized_keys file

 

---
- name: Exchange Keys between servers
  become: yes
  become_user: weblogic
  hosts: app
  tasks:
    - name: SSH KeyGen command
      shell: > 
        ssh-keygen -q -b 2048 -t rsa -N "" -C "creating SSH" -f ~/.ssh/id_rsa
        creates="~/.ssh/id_rsa"

    - name: Fetch the keyfile from one server to another
      fetch: 
        src: "~/.ssh/id_rsa.pub"
        dest: "buffer/{{ansible_hostname}}-id_rsa.pub"
        flat: yes

    - name: Copy the file from master to the destination
      copy:
        src: "buffer/{{item.dest}}-id_rsa.pub"
        dest: "/tmp/remote-id_rsa.pub"  
      when: "{{ item.dest != ansible_hostname }}"
      with_items: 
        - { dest: "{{groups['app'][1]}}"}
        - { dest: "{{groups['app'][0]}}"}

    - name: add the public key into Authorized_keys file to enable Key Auth
      shell: "cat /tmp/remote-id_rsa.pub >> ~/.ssh/authorized_keys"
      register: addtoauth

 

 

Type2: With Ansible authorized_key module

In this method, we are going to use the ansible built-in module named "authorized_key".  The following playbook has three steps

  1. Create an SSH Private and Public Key using  ssh-keygen command
  2. Fetch generated key files from remote servers [mwiapp01,mwiapp02]  to ansible master
  3. Use the authorized_key module to copy the file remote machine and add it to the mentioned user's authorized_keys file ( If you could notice, the authorized_key module is actually performing the step3 and step4 from the manual method )

 

---
- name: Exchange Keys between servers
  become: yes
  become_user: weblogic
  hosts: app
  tasks:
    - name: SSH KeyGen command
      tags: run
      shell: > 
        ssh-keygen -q -b 2048 -t rsa -N "" -C "creating SSH" -f ~/.ssh/id_rsa
        creates="~/.ssh/id_rsa"

    - name: Fetch the keyfile from one server to another
      tags: run
      fetch: 
        src: "~/.ssh/id_rsa.pub"
        dest: "buffer/{{ansible_hostname}}-id_rsa.pub"
        flat: yes

    - name: Copy the key add to authorized_keys using Ansible module
      tags: run
      authorized_key:
        user: weblogic
        state: present
        key: "{{ lookup('file','buffer/{{item.dest}}-id_rsa.pub')}}"
      when: "{{ item.dest != ansible_hostname }}"
      with_items: 
        - { dest: "{{groups['app'][1]}}"}
        - { dest: "{{groups['app'][0]}}"}

 

 

Ansible SSH Key Exchange between multiple hosts

Though the previously given examples have talked about Creating and Exchanging the Keys between only two servers. With a Simple modification in the same playbook. you would be able to achieve Exchanging the SSH Keys across multiple servers (or) all the servers in the host group.

Here is the Playbook to exchange SSH key between multiple hosts.

---
- name: Exchange Keys between servers
  hosts: multi
  tasks:
    - name: SSH KeyGen command
      tags: run
      shell: > 
        ssh-keygen -q -b 2048 -t rsa -N "" -C "creating SSH" -f ~/.ssh/id_rsa
        creates="~/.ssh/id_rsa"

    - name: Fetch the keyfile from the node to master
      tags: run
      fetch: 
        src: "~/.ssh/id_rsa.pub"
        dest: "buffer/{{ansible_hostname}}-id_rsa.pub"
        flat: yes

    - name: Copy the key add to authorized_keys using Ansible module
      tags: runcd
      authorized_key:
        user: vagrant
        state: present
        key: "{{ lookup('file','buffer/{{item}}-id_rsa.pub')}}"
      when: "{{ item != ansible_hostname }}"
      with_items: 
        - "{{ groups['multi'] }}"       

What is the difference

we have changed the loop with_items to parse all the servers in the host group instead of two specific servers. These are the two modified lines from the previous example.

 when: "{{ item != ansible_hostname }}"
 with_items: 
        - "{{ groups['multi'] }}"

Playbook execution Output

We have saved the Type1 playbook in the name sshkey-exchange-t1.yaml and executed it. and here is the output.

In the last task. you could see that we successfully initiated an SSH connection  from one another and ran the uname -a command

 Enable SSH Key based authentication using Ansible

Hope it helps.

We recommend the following article in case if you are looking to exchange IP between multiple hosts in Ansible. adding an IP in /etc/hosts file of multiple hosts in Ansible.

ansible update /etc/hosts file with IP of all hosts across all hosts

For any questions (or) support. Please feel free to comment

Rate this article [ratings]

Cheers,

Sarav AK

Follow me on Linkedin My Profile
Follow DevopsJunction onFacebook orTwitter
For more practical videos and tutorials. Subscribe to our channel

Buy Me a Coffee at ko-fi.com

Signup for Exclusive "Subscriber-only" Content

Loading