Create and manage users with Ansible – automatically create sudo users

Creating users is a very trivial task that requires time, especially if there is not a Active Directory mechanism integrated with the Linux servers. In order to make your life easier as an administrator you can run the below playbook that will create users based on a list and add them sudo capabilities.

Task 1
creates the users that have been specified on the loop section.

Task 2
creates the appropriate sudoers file

  1 ---               
  2 - name: create sudoers users based on request
  3   hosts: localhost
  4   become: true    
  5   tasks:          
  6     - name: create users based on a list
  7       user:       
  8         name: "{{ item }}"
  9         password: "{{ '#Passw0rd#' | password_hash('sha512') }}"
 10         shell: /bin/bash
 11       loop:       
 12         - user1
 13         - user2
 14                   
 15     - name: create sudoers file for user
 16       copy:       
 17         content: '{{ item }} ALL = (ALL) ALL'
 18         dest: "/etc/sudoers.d/{{item}}"
 19       loop:       
 20         - user1
 21         - user2

Run the playbook and verify that the password is correct and user has sudo capabilities.

ansible-playbook createusers.yml

Bad HTTP response returned from server Code 500 – Ansible authentication

When you try to connect through kerberos with a domain account on Ansible windows hosts, you may encounter the error that is shown below:

The configuration for the kerberos connection. is listed below, and you can find the steps on my previous article.

[all:vars]

ansible_connection = winrm
ansible_winrm_server_cert_validation = ignore
ansible_port =  5985
ansible_user = domainUser
ansible_password = password
ansible_become_method= runas
ansible_winrm_transport = kerberos

The problem occur while trying to connect with port 5985 unencrypted on the remote machine. To bypass the problem you could run on PowerShell the below command which allows an unencrypted connection through winrm protocol.

Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value true

Lastly you could try a test connection to verify the result.

How to create a hello world Ansible module with Documentation

If you cannot locate a plugin that suits your needs by using Ansible, you can easily extend the default functionality by creating your own python module. In this article I will explain the procedure for the creation of a module.

First of all you should create a python code and use Ansible SDK. A detailed description for the creation of the development environment can be found on official documentation.

The example module is a hello world, that gets as an input your name, surname and prints a hello message.

Copy your hello.py on ansible modules location. On my working machine this is the path /usr/local/lib/python3.9/site-packages/ansible/modules

When you include your documentation on the python file, you can explore it with:

ansible-doc hello
Documentation for module

If you try a module run without the required parameters, it will fail as shown below:

Plugin run without required parameters

Run your custom module by using the below playbook:

Input with only name as parameter:

---
- name: test playbook using custom code
  hosts: localhost
  tasks:
    - name: using my custom module
      hello:
        name: Gerasimos
      register: result
      
    - name: show output
      debug:
        var: result

Input with name and surname as parameters:

---
- name: test playbook using custom code
  hosts: localhost
  tasks:
    - name: using my custom module
      hello:
        name: Gerasimos
        surname: Alexiou
      register: result
      
    - name: show output
      debug:
        var: result

Code for the example module can be found on my github repo.

Ansible loop over nested dictionary subelements – list object has no attribute

Sometimes it could be tricky in Ansible to loop over a nested key-value list. Take for example the below dictionary which includes a nested list of disks. The upper element of the .yml file is vms which includes name, folder, cpus, sockets, memory and disk.

The disk element consists of disksize and disktype. This .yml file has been created on a previous post which explains how to automatically provision VMware servers.

 vms:
 name: test1-ansible
 folder: ansible
 cpus: 1
 sockets: 1
 memory: 64
 disk:
  - disksize: 64
    disktype: thin
  - disksize: 100
    disktype: thin 

If you try to loop over this list you will probably get an error like list object has no attribute.

With the subelements command you can loop over your main list (vms) and access your nested one (disk) with a different index.

In order to retrieve the vm name you should use item.0. The nested values are placed under item.1

---
- name: test playbook 
  hosts: localhost 
  vars_files: vms.yml
  tasks:
    - name: loop over nested
      debug:
        msg: '"{{ item.1.disksize }}"  "{{ item.1.disktype }}"'
      loop: "{{ vms| subelements('disk') }}" 

By performing a debug print, we can successfully get the nested keys values.