What kind of users? Well, a special user called Ansible, which will use SSH keys to login into remote devices, allowing for full automation on playbooks.
Creating a new key
If you have been following the series, maybe you remember that we already created keys on the Juniper Junos SSH Keys post.
To create a new key, let’s issue the ssh-keygen
command as follows. The -f flag tells the output path, and the -C flags specifies a comment.
$ ssh-keygen -f ansible.key -C ansible-login-passwordless
This should output two files, ansible.key and ansible.key.pub.
The public key should look something like this.
$ cat ansible.key.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtJUPfzJY6vKqLUssPPQe+LD7qRmIPbVhb/1i4Qab7T0Vf3x+ItfJyV4Ej4FsnRSU8iMU8J5eIdcetGQfsmwIZAm8glB0T6En5F9lvq2Yd+3RKIvxM3UlrIH6EaRedhsRUyV96CHfIO2nVqS9dmFfgrOJMIOwfTWIiRDNczUPw7aqw0FExslw9ZC0FO/1A6hYgofkGLrdIu9gK/WkNg5BE1EUCYPqbDBEHnnhv3C33LqiSJZnXJyqu53qz+jlv+1LZxerNHuovMGZMkjQsBo2f3r9Gk/9HqBmT0rcLr5prm4CqqryJ3S9VyVVlF599BlqYMuMjj+fCj277R8kSnLxl ansible-login-passwordless
Of course we need an inventory to use, which has the following content.
$ cat inventory.yml
---
all:
hosts:
vars:
ansible_ssh_user: ansible
ansible_ssh_private_key_file: ansible.key
ansible_python_interpreter: auto_silent
hosts:
localhost:
This inventory only has one host, localhost, and uses three main variables:
- ansible_ssh_user, which tell Ansible to use the user ansible
- ansible_ssh_private_key_file, which indicates the key for this user
- ansible_python_interpreter, just to avoid non needed logs
The playbook will looks like this. Notice we don’t need to gather_facts here, and we will instruct ansible to use become to gain privileges on the destination host.
---
- hosts: all
become: yes
tasks:
- name: Make sure we have a "wheel" group
group:
name: wheel
state: present
- name: Allow 'wheel' group to have passwordless sudo
lineinfile:
dest: /etc/sudoers
state: present
regexp: '^%wheel'
line: '%wheel ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
- name: Create "ansible" user
user:
name: ansible
comment: Ansible Automation User
groups: wheel
- name: Add ssh key
authorized_key:
user: ansible
state: present
key: "{{ lookup('file', './ansible.key.pub') }}"
First, we want to make sure there is a group called wheel which will group users with administrative privileges.
Then, the /etc/sudoers file will be edited by allowing the wheel group to gain privileges, with a failsafe using a visudo validation.
Once the group has been created, the new user will be created, and a SSH key will be added to it.
It seems allright, but, how should we run the playbook, if the default user is ansible and this user does not exists yet? Let’s give it a try.
$ ansible-playbook create-user.yml -i inventory.yml
PLAY [all] ************************************************************************
TASK [Gathering Facts] ************************************************************
fatal: [localhost]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ansible@localhost: Permission denied (publickey,password).", "unreachable": true}
PLAY RECAP ************************************************************************
localhost : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
It fails, as expected, because the ansible user does not exists in the host.
Well, there is a way to provide a one-time password by connecting a as different user. You will need to install sshpass with your favourite package manager, like apt install sshpass.
One installed, run the playbook once again with the following arguments:
- -e “ansible_ssh_user=xxxxx”, where xxxxx is a valid user on the remote host
- -kK, which tell Ansible to ask for a login and a sudo password
$ ansible-playbook create-user.yml -i inventory.yml -e "ansible_ssh_user=arturo" -kK
SSH password:
BECOME password[defaults to SSH password]:
PLAY [all] ************************************************************************
TASK [Gathering Facts] ************************************************************
ok: [localhost]
TASK [Make sure we have a "wheel" group] ******************************************
changed: [localhost]
TASK [Allow 'wheel' group to have passwordless sudo] ******************************
changed: [localhost]
TASK [Create "ansible" user] ******************************************************
changed: [localhost]
TASK [Add ssh key] ****************************************************************
changed: [localhost]
PLAY RECAP ************************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Awesome, we have sucessfully created a new user!
Let’s try to connect using the ansible user with its key, as defined in the playbook.
$ ansible -m ping -i inventory.yml all
localhost | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Stay tuned for more automation using Ansible.