Computerverwaltung
Inzwischen werden all unsere Linux-basierten PCs (wir haben keine anderen mehr ;) per Ansible verwaltet -- was es deutlich erleichtert, alle Geräte auf dem gleichen Stand zu halten oder neu zu installieren. Hier ein paar Kniffe, die ich im Rahmen der Familien-PC-Verwaltung anwende.
Host-spezifische Userverwaltung
In unserem Inventar können Computer die Gruppe family_boxes
zugewiesen bekommen, wodurch auf ihnen eine Reihe von Accounts angelegt werden, die in einer users
-Liste mit Dictionaries definiert sind, die jeweils benutzer*innen-spezifische Konfigurationswerte enthalten (Auszug; bei uns es gibt pro User in Wirklichkeit noch mehr Konfigurationsparameter):
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
Nun kann es für einzelne Hosts nötig sein, manche dieser Default-Werte zu verändern oder gar neue Benutzer*innen hinzuzufügen. Um nicht die gesamte users
-Liste neu explizit hinschreiben zu müssen, wird eine Rolle user_management
definiert, die die users
-Liste entsprechend einem host-spezifischen host_users
-Dictionary aktualisiert und/oder ergänz. Ein solches Dictionary könnte z. B. wie folgt aussehen:
host_users:
marge:
manage_desktop: false
lisa:
shell: /bin/bash
manage_desktop: false
guest:
full_name: Guest
manage_desktop: false
password: $6$guest
Hier der Task, in dem die Magie passiert:
---
# 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 }}"
Hier die effektive user
-Liste, die auf dem betreffenden Host zum Tragen kommt (Änderungen hervorgehoben):
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: 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
is_kid: true
manage_desktop: true
- name: maggie
full_name: Maggie
password: $6$SuckSuck
is_kid: true
manage_desktop: true
- name: guest
full_name: Guest
password: $6$guest
is_kid: false
manage_desktop: true