Ansible Level 04 Day 02: Create Users and Groups¶
This document outlines the solution for Ansible Level 04 Day 02. The objective was to onboard new team members by creating user accounts, assigning them to specific groups (admins and developers), setting custom home directories, and securely applying passwords using Ansible Vault.
Table of Contents¶
Task Overview¶
Objective: Create users and groups on App Server 2 (stapp02) based on a provided YAML list, applying specific constraints and secure passwords.
Requirements:
1. Target: App Server 2.
2. Groups to Create: developers and admins.
3. Data Source: ~/playbooks/data/users.yml (contains lists of users for each group).
4. Developers Group: * Home Directory: /var/www (exact path, not /var/www/user).
* Password: Rc5C9EyvbU (Must be encrypted).
5. Admins Group:
* Home Directory: Default (/home/{USER}).
* Password: YchZHRcLkL (Must be encrypted).
* Privileges: Must be added to the wheel group for sudo access.
6. Vault: Use ~/playbooks/secrets/vault.txt as the vault password file. Configure ansible.cfg to use this file automatically.
7. Playbook: ~/playbooks/add_users.yml. Must run with ansible-playbook -i inventory add_users.yml.
Step-by-Step Solution¶
1. Configure Ansible for Vault¶
Since the validation script will run the playbook without the --vault-password-file argument, we must configure Ansible to find the vault password automatically.
Command:
cd ~/playbooks
vi ansible.cfg
Content:
[defaults]
inventory = ./inventory
vault_password_file = ./secrets/vault.txt
vault_password_file line).
2. Encrypt the Passwords¶
Instead of writing plain text passwords in our playbook, we will create a dedicated secrets file, encrypt it with Ansible Vault, and load it into our playbook.
Create the secrets file:
vi secrets.yml
Initial Content (Plain Text):
dev_pass_plain: "Rc5C9EyvbU"
admin_pass_plain: "YchZHRcLkL"
Encrypt the file:
Run the following command. Because we configured ansible.cfg in Step 1, Ansible will automatically use vault.txt to encrypt this file without prompting you for a password.
ansible-vault encrypt secrets.yml
cat secrets.yml now, you will see it is fully encrypted with $ANSIBLE_VAULT headers).
3. Create the Playbook¶
Now we construct the playbook. We use vars_files to pull in the user lists from data/users.yml and the encrypted passwords from secrets.yml.
Note: The structure of data/users.yml typically defines two lists: developers: and admins:. We will loop over these.
Command:
vi add_users.yml
Content:
---
- name: Create Users and Groups for Nautilus Project
hosts: stapp02
become: yes
vars_files:
- data/users.yml
- secrets.yml
tasks:
- name: Create developers group
group:
name: developers
state: present
- name: Create admins group
group:
name: admins
state: present
- name: Add users to developers group
user:
name: "{{ item }}"
group: developers
home: /var/www
password: "{{ dev_pass_plain | password_hash('sha512') }}"
state: present
loop: "{{ developers }}"
# Note: If your users.yml nests them under a parent key (e.g., users: developers:),
# adjust this loop to "{{ users.developers }}"
- name: Add users to admins group
user:
name: "{{ item }}"
group: admins
groups: wheel
append: yes
password: "{{ admin_pass_plain | password_hash('sha512') }}"
state: present
loop: "{{ admins }}"
# Note: Adjust to "{{ users.admins }}" if nested under a parent 'users' key.
4. Execute and Validate¶
Run the playbook. Thanks to our ansible.cfg, we don't need any extra arguments.
Execution Command:
ansible-playbook -i inventory add_users.yml
Expected Output: You should see tasks executing successfully, creating groups, and dynamically looping over the lists to create the users.
Deep Dive: Ansible Concepts Used¶
Ansible Vault & ansible.cfg¶
Storing plain text passwords in Git or playbooks is a massive security risk. Ansible Vault encrypts variables and files. By defining vault_password_file in ansible.cfg, you streamline automation. The CI/CD pipeline (or the validation script, in this case) just needs access to that file to decrypt on the fly, keeping the execution command perfectly clean.
Password Hashing in Ansible¶
The Ansible user module's password parameter does not accept plain text passwords. If you pass plain text, Linux will literally store that text in /etc/shadow, rendering the account un-loggable because the system expects a hash there.
By applying the Jinja2 filter | password_hash('sha512'), Ansible takes our decrypted plain-text string from the vault, hashes it using the SHA-512 algorithm, and feeds the resulting secure hash to the Linux system.
Loading Variable Files (vars_files)¶
Instead of hardcoding lists of users inside the playbook, we imported an external data file (data/users.yml). This is excellent practice because it separates Data from Logic. If HR hires a new developer tomorrow, you only update users.yml—the playbook logic (add_users.yml) remains completely untouched.