On Linux every process runs as a particular user and every file and folder is owned by a certain user. Further, access to these files and folders are restricted by users. This shows how important it is to learn how user management is done on Linux as a normal user or an admin. Information about local users can be found in etc/passwd:
eugene@jCheredi:~$ tail -9 /etc/passwd colord:x:121:126:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin geoclue:x:122:127::/var/lib/geoclue:/usr/sbin/nologin pulse:x:123:128:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin gnome-initial-setup:x:124:65534::/run/gnome-initial-setup/:/bin/false gdm:x:125:130:Gnome Display Manager:/var/lib/gdm3:/bin/false eugene:x:1000:1000:Eugene,,,:/home/eugene:/bin/bash systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin mysql:x:126:133:MySQL Server,,,:/nonexistent:/bin/false redis:x:127:134::/var/lib/redis:/usr/sbin/nologin
The format is interpreted as follows:
username:password:uid:gid:gecos:home/dir:shell
Groups also have ID and every user belongs to a default group, User Private Group (UPG). Users can also have supplementary groups. These supplementary groups help users to have access to permissions for other files and processes. Information on groups is usually found at etc/group:
eugene@jCheredi:~$ tail -9 /etc/group gdm:x:130: lxd:x:131:eugene eugene:x:1000: sambashare:x:132:eugene systemd-coredump:x:999: mysql:x:133: redis:x:134: vboxusers:x:135: docker:x:136:
The format is interpreted as follows:
groupname:password:GID:<list of users>
You have heard of the root user. The root user is the superuser, they have all powers over the system. The root can override all powers over a file and is used to manage the system. Normally we log in as an unprivileged user then use the sudo command to gain root privileges.
As a Linux administrator, we are tasked with various tasks to manage user accounts like adding users, deleting them, etc. These tasks can be easily managed by Ansible. We will go through them using Ansible Playbook. In Ansible the user and group module helps us accomplish user management tasks. This playbook highlights various tasks.
Ansible Group module common options
- name – name of the group
- state – (absent/present) ensure a group is present or absent
- gid – specify group id
- system – (yes/no) if the group created is a system group or not
Ansible User module common options
- name – name of the user
- password – user’s encrypted password. Please note that the password should already been encrypted or use Ansible playbook encryption but hide the password in Ansible vault
- update_password – (always/on_create) whether to update password or just add it once when user is created
- uid – specify user id
- group – specify user primary group
- groups – add user to supplementary groups
- append – (no/yes) when adding user to supplementary group do not/or override primary group
- comment – set GECOS
- shell – set default shell for the user
- remove – remove user associated directories and files
Create/Add user and group using Ansible
Playbook, user.yml
:
---
- hosts: localhost #change to your hosts
become: yes
vars:
# NOTICE!!!:
# DO NOT PUT PLAIN TEXT PASSWORDS HERE!
# use encrypted passwords or put them in Ansible vault
# but this is just a demo
vaulted_password: mySecret.
tasks:
- name: Add a simple user called janedoe
user:
name: janedoe
comment: Jane Doe
- name: Add user anita with a password
user:
name: anita
password: "{{ vaulted_password | password_hash('sha512') }}"
update_password: on_create
- name: Add a group called developer
group:
name: developer
state: present
- name: Add a user johndoe and add them to a group developer
user:
name: johndoe
groups: developer
append: yes
- name: Add user jSmith and generate for them an SSH key
user:
name: jSmith
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
- name: Add user noHome with no home and set account to expire on certain date
user:
name: noHome
create_home: no
expires: 1590155615
Running the playbook, do not worry about the warning as I am running the playbook to my Ansible master as a node:
$ ansible-playbook user.yml -K BECOME password: [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [localhost] ************************************************************************************************************************************* TASK [Gathering Facts] ******************************************************************************************************************************* ok: [localhost] TASK [Add a simple user called janedoe] ************************************************************************************************************** changed: [localhost] TASK [Add user anita with a password] **************************************************************************************************************** changed: [localhost] TASK [Add a group called developer] ****************************************************************************************************************** changed: [localhost] TASK [Add a user johndoe and add them to a group developer] ****************************************************************************************** changed: [localhost] TASK [Add user jSmith and generate for them an SSH key] ********************************************************************************************** changed: [localhost] TASK [Add user noHome with no home and set account to expire on certain date] ************************************************************************ changed: [localhost] PLAY RECAP ******************************************************************************************************************************************* localhost : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Check users and groups:
eugene@jCheredi:~/Projects/Ansible/users$ tail -9 /etc/passwd
eugene:x:1000:1000:Eugene,,,:/home/eugene:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
mysql:x:126:133:MySQL Server,,,:/nonexistent:/bin/false
redis:x:127:134::/var/lib/redis:/usr/sbin/nologin
janedoe:x:1001:1001:Jane Doe:/home/janedoe:/bin/sh
anita:x:1002:1002::/home/anita:/bin/sh
johndoe:x:1003:1004::/home/johndoe:/bin/sh
jSmith:x:1004:1005::/home/jSmith:/bin/sh
noHome:x:1005:1006::/home/noHome:/bin/sh
eugene@jCheredi:~/Projects/Ansible/users$ tail -9 /etc/group
redis:x:134:
vboxusers:x:135:
docker:x:136:
janedoe:x:1001:
anita:x:1002:
developer:x:1003:johndoe
johndoe:x:1004:
jSmith:x:1005:
noHome:x:1006:
Delete/Remove users using Ansible
Playbook, user_delete.yml
:
---
- hosts: localhost
become: yes
tasks:
- name: Remove janedoe
user:
name: janedoe
state: absent
remove: yes
- name: Remove anita
user:
name: anita
state: absent
remove: yes
- name: Remove developer group
group:
name: developer
state: absent
- name: Remove johndoe
user:
name: johndoe
state: absent
remove: yes
- name: Remove jSmith
user:
name: jSmith
state: absent
remove: yes
- name: Remove noHome
user:
name: noHome
state: absent
remove: yes
Playbook run:
eugene@jCheredi:~/Projects/Ansible/users$ ansible-playbook user_delete.yml -K
BECOME password:
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] *************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************
ok: [localhost]
TASK [Remove janedoe] **************************************************************************************************************
changed: [localhost]
TASK [Remove anita] ****************************************************************************************************************
changed: [localhost]
TASK [Remove developer group] ******************************************************************************************************************
changed: [localhost]
TASK [Remove johndoe] ******************************************************************************************
changed: [localhost]
TASK [Remove jSmith] **********************************************************************************************
changed: [localhost]
TASK [Remove noHome] ************************************************************************
changed: [localhost]
PLAY RECAP *******************************************************************************************************************************************
localhost : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
There are more options for managing users on Ansible I haven’t covered everything but they are available on the Ansible documentation. You can check them out.
Ansible mastery courses:
That’s all for today, please support us by Buying us Coffee!
More on Ansible:
How To Generate Linux User Encrypted Password for Ansible
Setup Elasticsearch Cluster on CentOS / Ubuntu With Ansible
How To Use Ansible Playbook With Vagrant up