diff --git a/ansible/.gitignore b/ansible/.gitignore index 58c4c3511..17b539f45 100644 --- a/ansible/.gitignore +++ b/ansible/.gitignore @@ -90,3 +90,5 @@ roles/* !roles/gateway/** !roles/alertmanager/ !roles/alertmanager/** +!roles/sudoers/ +!roles/sudoers/** diff --git a/ansible/extras.yml b/ansible/extras.yml index c7cacb877..3790021be 100644 --- a/ansible/extras.yml +++ b/ansible/extras.yml @@ -28,6 +28,15 @@ - import_role: name: basic_users +- hosts: sudoers:!builder + become: true + tags: sudoers + gather_facts: yes + tasks: + - name: Configure sudoers + import_role: + name: sudoers + - name: Setup EESSI hosts: eessi tags: eessi diff --git a/ansible/roles/sudoers/README.md b/ansible/roles/sudoers/README.md new file mode 100644 index 000000000..27fd0e65a --- /dev/null +++ b/ansible/roles/sudoers/README.md @@ -0,0 +1,65 @@ +# sudoers + +Manage sudoers configuration by creating files in `/etc/sudoers.d/`. + +## Role Variables + + - `sudoers_groups`: Required list. A list of dictionaries defining sudo group configurations. Each dictionary should contain: + - `group`: Required string. The group name to grant sudo privileges to. + - `commands`: Required string. The sudo commands specification (e.g., "ALL=(ALL) ALL"). + - `state`: Optional string. Either "present" (default) or "absent" to remove the configuration. + +## Features + + - Creates individual sudoers files for each group in `/etc/sudoers.d/` + - Validates sudoers syntax using `visudo -cf` before applying + - Sanitizes group names by replacing spaces and slashes with underscores for filename safety + - Supports removing sudoers configurations by setting `state: absent` + - Sets proper permissions (0440) and ownership (root:root) on sudoers files + +## Dependencies + +None. + +## Example Playbook + +```yaml +- hosts: servers + become: yes + roles: + - role: sudoers + vars: + sudoers_groups: + - group: SITE_Admins + commands: "ALL=(ALL) ALL" + - group: SITE_Users + commands: "ALL=(ALL) ALL" + - group: developers + commands: "ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp" + - group: old_group + state: absent +``` + +## Example Variables + +```yaml +# Merge your existing groups like this: +sudoers_groups: "{{ sudo_groups + management_sudo_groups }}" + +# Where you have: +sudo_groups: + - group: SITE_Users + commands: "ALL=(ALL) ALL" + +management_sudo_groups: + - group: SITE_Admins + commands: "ALL=(ALL) ALL" +``` + +## License + +Apache v2 + +## Author Information + +StackHPC Ltd. diff --git a/ansible/roles/sudoers/defaults/main.yml b/ansible/roles/sudoers/defaults/main.yml new file mode 100644 index 000000000..4e7b605f6 --- /dev/null +++ b/ansible/roles/sudoers/defaults/main.yml @@ -0,0 +1,20 @@ +--- +# Default variables for sudoers role + +# List of sudo groups to configure +# Each item should have: +# - group: the group name (required) +# - commands: the sudo commands specification (required) +# - state: present (default) or absent (optional) +sudoers_groups: [] + +# Example: +# sudoers_groups: +# - group: SITE_Admins +# commands: "ALL=(ALL) ALL" +# - group: SITE_Users +# commands: "ALL=(ALL) ALL" +# - group: developers +# commands: "ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp" +# - group: old_group +# state: absent diff --git a/ansible/roles/sudoers/tasks/main.yml b/ansible/roles/sudoers/tasks/main.yml new file mode 100644 index 000000000..c8c1fe315 --- /dev/null +++ b/ansible/roles/sudoers/tasks/main.yml @@ -0,0 +1,24 @@ +--- +- name: Configure sudoers files + template: + src: sudoers.j2 + dest: /etc/sudoers.d/{{ item.group | replace(' ', '_') | replace('/', '_') }} + owner: root + group: root + mode: '0440' + validate: 'visudo -cf %s' + become: true + with_items: "{{ sudoers_groups }}" + when: + - sudoers_groups is defined + - sudoers_groups | length > 0 + +- name: Remove sudoers files for absent groups + file: + path: /etc/sudoers.d/{{ item.group | replace(' ', '_') | replace('/', '_') }} + state: absent + become: true + with_items: "{{ sudoers_groups }}" + when: + - sudoers_groups is defined + - item.state | default('present') == 'absent' diff --git a/ansible/roles/sudoers/templates/sudoers.j2 b/ansible/roles/sudoers/templates/sudoers.j2 new file mode 100644 index 000000000..0ee1c9aa5 --- /dev/null +++ b/ansible/roles/sudoers/templates/sudoers.j2 @@ -0,0 +1 @@ +%{{ item.group }} {{ item.commands }} diff --git a/environments/common/inventory/groups b/environments/common/inventory/groups index b6c216ef6..750e297c5 100644 --- a/environments/common/inventory/groups +++ b/environments/common/inventory/groups @@ -182,3 +182,6 @@ extra_packages [gateway] # Add builder to this group to install gateway ansible-init playbook into image + +[sudoers] +# Hosts to configure sudoers groups diff --git a/environments/common/layouts/everything b/environments/common/layouts/everything index 9f2c7c706..692d99b6b 100644 --- a/environments/common/layouts/everything +++ b/environments/common/layouts/everything @@ -125,3 +125,6 @@ builder [gateway:children] # Add builder to this group to install gateway ansible-init playbook into image builder + +[sudoers] +# Hosts to configure sudoers groups