Computer Management
By now, all our Linux-based PCs (well, we don't have any others ;) are managed through Ansible -- which greatly facilitates harmonizing the machines' configurations or re-installing them from scratch. Here I present some useful procedures I follow in the context of family PC management.
Host-specific user management
If a computer in our inventory gets assigned to the familiy_boxes group, user accounts get automatically created according to configuration data found in a users list, each user configuration being defined by a dictionary of user-specific values (excerpt; in reality, some more configuration parameters are taken into account):
users:
- name: homer
full_name: Homer
password: $6$D'oh
is_kid: false
manage_desktop: true
- name: marge
full_name: Marge
password: $6$Hrmmm
is_kid: false
manage_desktop: false
- name: bart
full_name: Bart
password: $6$EatMyShorts
is_kid: true
manage_desktop: true
- name: lisa
full_name: Lisa
password: $6$IfAnyoneWantsMe,I'llBeInMyRoom
shell: /usr/bin/zsh
is_kid: true
manage_desktop: false
- name: maggie
full_name: Maggie
password: $6$SuckSuck
is_kid: true
manage_desktop: true
For certain hosts, it might turn out that some of these default values need to be changed, or it might even be necessary to create additional user accounts. In order to not need to explicitly re-type the whole users list, a role user_management was defined, which updates the users list according to a host-specific host_users dictionary. Such a dictionary might e. g. look like this:
host_users:
marge:
manage_desktop: false
lisa:
shell: /bin/bash
manage_desktop: false
guest:
full_name: Guest
manage_desktop: false
password: $6$guest
Here's the task carrying out the magic:
---
# Tasks for user_management role
- name: get list of default user names
set_fact:
# Creates a list of all the 'name' values of all dictionaries
# contained in the default users list.
_default_user_names: "{{
users
| map(attribute='name')
| list
}}"
- name: get list of host user_names
set_fact:
# Creates a list of all keys of the host_users dictionary, which are
# the names of all users to be configured specifically for this host.
_host_user_names: "{{
(host_users | default({}, true))
| dict2items
| map(attribute='key')
| list
}}"
- name: determine additional user names
set_fact:
# Excludes all default user names from the set of host-specific user names.
_additional_user_names: "{{
_host_user_names
| difference(_default_user_names)
}}"
- name: append additional users to default users
set_fact:
# For each host-specific user not yet contained in the default users dictionaries list,
# add a dicionary containing 'name' as key and the additional user's name as value.
users: "{{
(users | default([]))
+ [{
'name': item
}]
}}"
loop: "{{ _additional_user_names}}"
- name: process users' configuration
set_fact:
# For all users (both default and host-specific users, additional or not), merge/overwrite
# host-specific user configuration into the user's cohnfiguration dictionary.
_all_users: "{{
(_all_users | default([]))
+ [
item
| combine(
host_users[item.name] | default({}),
recursive = True
)
]
}}"
loop: "{{ users }}"
- name: get default user groups
set_fact:
# Ensures we have a list of default groups user are to assigned to.
_default_user_groups: "{{ default_user_groups | default([]) }}"
- name: show default user groups
debug:
# For debugging purposes.
msg: "{{ _default_user_groups }}"
- name: complete users' configuration
set_fact:
# Re-build the list of user dictionaries, ensuring all expected keys are present
# and have default values, if not specified otherwise in the configuration data
# gathered thus far.
_users: "{{
(_users | default([]))
+ [
item
| combine(
{
'groups': (_default_user_groups + (item.addidional_groups | default([]))),
'full_name': (item.full_name | default(item.name)),
'shell': (item.shell | default('/bin/bash')),
'is_system_user': (item.is_system_user | default(false)),
'home': (item.home | default('/home/' + item.name)),
'id_rsa': (item.id_rsa | default('id_rsa')),
'is_kid': (item.is_kid | default(false)),
'manage_home': (item.is_kid | default(false)),
'manage_desktop': (item.is_kid | default(false)),
'record_session': (item.is_kid | default(false))
}
)
]
}}"
loop: "{{ _all_users }}"
- name: apply users configuration
set_fact:
# Re-assign the newly created user configuration list to the users variable.
users: "{{ _users}}"
- name: show users
debug:
# For debugging purposes.
msg: "{{ users }}"
And here's the effective user configuration finally applied to the host (changes highlighted):
users:
- name: homer
full_name: Homer
password: $6$D'oh
is_kid: false
manage_desktop: true
- name: marge
full_name: Marge
password: $6$Hrmmm
is_kid: false
manage_desktop: false # Was: true
- name: bart
full_name: Bart
password: $6$EatMyShorts
is_kid: true
manage_desktop: true
- name: lisa
full_name: Lisa
password: $6$IfAnyoneWantsMe,I'llBeInMyRoom
shell: /bin/bash # Was: /usr/bin/zsh
is_kid: true
manage_desktop: false # Was: true
- name: maggie
full_name: Maggie
password: $6$SuckSuck
is_kid: true
manage_desktop: true
- name: guest # Completely new user entry
full_name: Guest
password: $6$guest
is_kid: false
manage_desktop: true