General situation
- There is a department of N different employees + M soulless machines (such as an integration server).
- There are many hosts. A part is used for tests, others in combat, those and those can be grouped according to the tasks performed.
- You need to control user access to hosts, keeping the configuration in one place. It may be necessary:
- Grant the user access to a host or group by creating a user on the system and registering an ssh key.
- Revoke access, for example by deleting an ssh key,
- Enable or disable
sudo
, - Limit
sudo
, - Enable or disable
NOPASSWD
.
Current solution
Now for registration of users I use such a scheme (so far I’m trying only on two hosts and two users):
Own playbook and role in which standard modules are used:
- user (creates a user, can pass a password hash created via
passwd --method=SHA-512
) - authorized_key (the required public key is added to the created user’s .ssh / authorized_hosts)
Plus a custom task that creates
/etc/sudoers.d/username
:copy: content: "{{ item.key }} ALL=(ALL) NOPASSWD:ALL" dest: "/etc/sudoers.d/{{ item.key }}" owner: root group: root mode: 0400 with_dict: "{{ users_list }}" when: users_list is defined become: true
- user (creates a user, can pass a password hash created via
Shared inventory files (same as for other playbooks)
Files
group_vars/hostname.yaml
, in which the public keys and user password hashes are stored. They are stored in the form of a dictionary:users_list: username: ssh_key: "ssh-rsa ..." password: "$6$..." comment: "User Name"
This implementation forces me to keep a separate document for each host or group of hosts, in which data on users is repeated. This makes it extremely difficult to support.
Desired result
I would like to implement it like this:
The user_credentials.yaml
file, one for all:
user_credentials: username: ssh_key: "ssh-rsa ..." password: "$6$..." comment: "User Name" username_2: ...
In each group_vars/hostname.yaml
:
users_list: username: sudoer: yes nopasswd: yes username_2: sudoer: yes nopasswd: no some_fired_employee: state: absent
Now, when the rights change, you just need to change the config in one place and execute a playbook on the necessary group of hosts.
Problem
I do not understand how to write specific tasks so that they take values ​​from the necessary files. Somehow it is necessary to form a dictionary on the go, in which there will be data from user_credentials.yaml
, filtered by the fact that the user is in the users_list
, combined with the data from users_list
.