- bootstrap.yml: support pkg for FreeBSD sudo/python3 install - base role: FreeBSD package sets, sudoers paths, host key regen, admin group, usermod process-in-use tolerance - freebsd role: pkg update/upgrade tasks - general role: standalone hostname tasks (ungated from network.skip), hostname_override support - inspircd role: deploy configs for ca/us manero.org irc servers with vault-backed secrets - uisp role: download and run installer on fresh hosts, skip if already running - netbox role: stop services before usermod to avoid process-in-use failures - hosts: add irc_servers group, ca/us.manero.org (Tailscale), drop staging.towerops.net - all.yml: graham user gets static ed25519 key alongside github keys
124 lines
4.4 KiB
YAML
124 lines
4.4 KiB
YAML
# User and group management tasks
|
|
|
|
- name: Ensure admin group exists when defined
|
|
ansible.builtin.group:
|
|
name: "{{ admin_group }}"
|
|
when: admin_group | default('') | length > 0
|
|
|
|
- name: Ensure managed groups exist
|
|
ansible.builtin.group:
|
|
name: "{{ item.name }}"
|
|
gid: "{{ item.gid | default(omit) }}"
|
|
state: "{{ item.state | default('present') }}"
|
|
loop: "{{ managed_groups | default([]) }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
|
|
- name: Ensure primary groups for managed users exist
|
|
ansible.builtin.group:
|
|
name: "{{ item.primary_group }}"
|
|
gid: "{{ item.primary_gid | default(omit) }}"
|
|
state: present
|
|
loop: "{{ managed_users | default([]) }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
when: item.primary_group is defined
|
|
|
|
- name: Ensure managed users are present
|
|
ansible.builtin.user:
|
|
name: "{{ item.name }}"
|
|
uid: "{{ item.uid | default(omit) }}"
|
|
shell: "{{ item.shell | default('/bin/bash') }}"
|
|
home: "{{ item.home | default(omit) }}"
|
|
group: "{{ item.primary_group | default(omit) }}"
|
|
groups: "{{ (user_groups | join(',')) if user_groups else omit }}"
|
|
append: "{{ true if user_groups else omit }}"
|
|
create_home: "{{ item.create_home | default(true) }}"
|
|
state: "{{ item.state | default('present') }}"
|
|
vars:
|
|
user_groups: >-
|
|
{{ ((item.groups | default([])) +
|
|
([admin_group] if item.admin | default(false) and admin_group | default('') | length > 0 else []))
|
|
| unique }}
|
|
loop: "{{ managed_users | default([]) }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
when: item.state | default('present') != 'absent'
|
|
register: user_result
|
|
failed_when:
|
|
- user_result is failed
|
|
- '"currently used by process" not in user_result.msg'
|
|
|
|
- name: Remove managed users marked absent
|
|
ansible.builtin.user:
|
|
name: "{{ item.name }}"
|
|
state: absent
|
|
remove: "{{ item.remove | default(false) }}"
|
|
loop: "{{ managed_users | default([]) }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
when: item.state | default('present') == 'absent'
|
|
|
|
- name: Install authorized keys from GitHub
|
|
ansible.posix.authorized_key:
|
|
user: "{{ item.0.name }}"
|
|
state: "{{ item.1.state | default('present') }}"
|
|
key: "https://github.com/{{ item.1.value }}.keys"
|
|
manage_dir: "{{ item.1.manage_dir | default(true) }}"
|
|
exclusive: "{{ item.1.exclusive | default(false) }}"
|
|
loop: "{{ managed_users | default([]) | subelements('authorized_keys', skip_missing=True) }}"
|
|
loop_control:
|
|
label: "{{ item.0.name }} (github: {{ item.1.value }})"
|
|
when:
|
|
- item.1.type | default('github') == 'github'
|
|
- item.0.state | default('present') != 'absent'
|
|
|
|
- name: Install authorized keys from files
|
|
ansible.posix.authorized_key:
|
|
user: "{{ item.0.name }}"
|
|
state: "{{ item.1.state | default('present') }}"
|
|
key: "{{ lookup('file', item.1.value) }}"
|
|
manage_dir: "{{ item.1.manage_dir | default(true) }}"
|
|
exclusive: "{{ item.1.exclusive | default(false) }}"
|
|
loop: "{{ managed_users | default([]) | subelements('authorized_keys', skip_missing=True) }}"
|
|
loop_control:
|
|
label: "{{ item.0.name }} (file: {{ item.1.value }})"
|
|
when:
|
|
- item.1.type | default('github') == 'file'
|
|
- item.0.state | default('present') != 'absent'
|
|
|
|
- name: Install authorized keys from inline strings
|
|
ansible.posix.authorized_key:
|
|
user: "{{ item.0.name }}"
|
|
state: "{{ item.1.state | default('present') }}"
|
|
key: "{{ item.1.value }}"
|
|
manage_dir: "{{ item.1.manage_dir | default(true) }}"
|
|
exclusive: "{{ item.1.exclusive | default(false) }}"
|
|
loop: "{{ managed_users | default([]) | subelements('authorized_keys', skip_missing=True) }}"
|
|
loop_control:
|
|
label: "{{ item.0.name }} (string key)"
|
|
when:
|
|
- item.1.type | default('github') == 'string'
|
|
- item.0.state | default('present') != 'absent'
|
|
|
|
- name: Configure sudo for ansible user
|
|
ansible.builtin.template:
|
|
src: sudoers_ansible.j2
|
|
dest: "{{ sudoers_dir }}/ansible"
|
|
mode: '0440'
|
|
validate: "{{ visudo_path }} -cf %s"
|
|
|
|
- name: Configure sudo for graham user
|
|
ansible.builtin.template:
|
|
src: sudoers_graham.j2
|
|
dest: "{{ sudoers_dir }}/graham"
|
|
mode: '0440'
|
|
validate: "{{ visudo_path }} -cf %s"
|
|
|
|
- name: Enable passwordless sudo for admin group
|
|
ansible.builtin.lineinfile:
|
|
path: "{{ sudoers_path }}"
|
|
state: present
|
|
regexp: '^%{{ admin_group }}'
|
|
line: '{{ admin_group }} ALL=(ALL) NOPASSWD: ALL'
|
|
validate: "{{ visudo_path }} -cf %s"
|