From ecbe40af1d36bbbb0efaed1f96eba88d9a16346b Mon Sep 17 00:00:00 2001 From: holger Date: Wed, 15 Jul 2026 18:01:01 +0200 Subject: [PATCH] first commit --- README.md | 93 +++++++++++++++++++++++ users/ansible.cfg | 4 + users/inventory/group_vars/all/users.yaml | 27 +++++++ users/inventory/hosts.yaml | 6 ++ users/roles/users/README.md | 93 +++++++++++++++++++++++ users/roles/users/defaults/main.yaml | 2 + users/roles/users/floss | 7 ++ users/roles/users/floss.pub | 1 + users/roles/users/handlers/main.yaml | 6 ++ users/roles/users/meta/main.yaml | 52 +++++++++++++ users/roles/users/tasks/groups.yaml | 7 ++ users/roles/users/tasks/main.yaml | 21 +++++ users/roles/users/tasks/sshd.yaml | 14 ++++ users/roles/users/tasks/sudoers.yaml | 15 ++++ users/roles/users/tasks/sudoers.yaml~ | 12 +++ users/roles/users/tasks/users.yaml | 36 +++++++++ users/roles/users/tests/inventory | 2 + users/roles/users/tests/test.yaml | 5 ++ users/roles/users/vars/main.yaml | 2 + users/site.yaml | 10 +++ 20 files changed, 415 insertions(+) create mode 100644 README.md create mode 100644 users/ansible.cfg create mode 100644 users/inventory/group_vars/all/users.yaml create mode 100644 users/inventory/hosts.yaml create mode 100644 users/roles/users/README.md create mode 100644 users/roles/users/defaults/main.yaml create mode 100644 users/roles/users/floss create mode 100644 users/roles/users/floss.pub create mode 100644 users/roles/users/handlers/main.yaml create mode 100644 users/roles/users/meta/main.yaml create mode 100644 users/roles/users/tasks/groups.yaml create mode 100644 users/roles/users/tasks/main.yaml create mode 100644 users/roles/users/tasks/sshd.yaml create mode 100644 users/roles/users/tasks/sudoers.yaml create mode 100644 users/roles/users/tasks/sudoers.yaml~ create mode 100644 users/roles/users/tasks/users.yaml create mode 100644 users/roles/users/tests/inventory create mode 100644 users/roles/users/tests/test.yaml create mode 100644 users/roles/users/vars/main.yaml create mode 100644 users/site.yaml diff --git a/README.md b/README.md new file mode 100644 index 0000000..550ad8c --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +# How to use: + +## Adding a new user +To create a ssh key pair on the new users PC. +ssh-keygen -f new_floss_key +The 'private' part should NEVER leave the user's PC. + ( It is a good idea to add a keyphrase to protect the key, if the client PC is ever stolen or hacked.) + +you only need: new_floss_key.pub + +open inventory/group_vars/all/users.yaml +add a new entry: + - username: alice + groups: + - ssh_login + - floss_sudo + - floss_admin + ssh_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... alice@laptop + - replace this ^^^^ line, with new_floss_key.pub... + +deploy with: + ansible-playbook site.yaml + +## delete user: +open inventory/group_vars/all/users.yaml +add: + - username: alice + __state: absent__ +and rerun: + ansible-playbook site.yaml + + +# Troubleshoot: + +## ssh: +Check permissions in the users home. All files must be owned by the user, + # sudo find ~alice -ls + 4 drwxr-x--- 6 alice alice 4096 Jul 15 16:59 /home/alice + 4 drwx------ 2 alice alice 4096 Jul 15 16:58 /home/alice/.ssh + 4 -rw------- 1 alice alice 709 Jul 15 16:58 /home/alice/.ssh/authorized_keys +(only showing the important files ) Note, ssh may fail, if permission are too open, DONT do chmod 777 ... + +check groups: ( look for ssh_login ) + # id alice + uid=1005(alice) gid=1007(alice) groups=1007(alice),27(sudo),1005(ssh_login),1006(admin),1010(floss_sudo),1011(floss_admin) + +check that sshd is running + # sudo systemctl status ssh # (or ps -ef | grep sshd ) +and the config is ok: + # sudo sshd -t ( no output is good ) +restart with: + # sudo systemctl status ssh + +## sudo: +check groups ( look for floss_sudo and/or floss_admin ) + +check the sudoers file: + # visudo -cf /etc/sudoers.d/floss-sudo + /etc/sudoers.d/floss-sudo: parsed OK + +Try to redeploy, if it was changed. + + +# About the role: +# Users Ansible Role + +This role manages local Linux users, groups, SSH access, SSH keys, and sudo permissions. + +The role is designed to be multi-distribution and does not rely on distro-specific groups such as `sudo` or `wheel`. + +## Managed groups + +The role uses these groups: + +| Group | Purpose | +|---|---| +| `ssh_login` | Users in this group are allowed to log in via SSH | +| `floss_sudo` | Users in this group get passwordless sudo/root access | +| `floss_admin` | Users in this group get limited administrative commands | + +Additional groups can be added as required. + + +License +------- + +BSD + +Author Information +------------------ +version 1: holger + chatgpt + diff --git a/users/ansible.cfg b/users/ansible.cfg new file mode 100644 index 0000000..cf42903 --- /dev/null +++ b/users/ansible.cfg @@ -0,0 +1,4 @@ + +[defaults] +inventory = inventory/hosts.yaml +roles_path = roles diff --git a/users/inventory/group_vars/all/users.yaml b/users/inventory/group_vars/all/users.yaml new file mode 100644 index 0000000..429dcc5 --- /dev/null +++ b/users/inventory/group_vars/all/users.yaml @@ -0,0 +1,27 @@ +--- +users: + - username: alice + groups: + - ssh_login + - floss_sudo + - floss_admin + ssh_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABvA6ktfo/Y2/bW5LY1EwnGCvN3oxRE4w9X+VLbIxys1mSUbbYHJNgoruFT5CgxQqKMJSWlUYw+BPusLnxRsq6u4OAwWsVIWV2aTCLZIP1UzvuqKl3xQ1lEOd+9sKIwOAvprimkDU4u9qC6/ls96raMZXqxQLqw6IL4b4wleednPdv4uLIpvjQpJ/xNFGTWFV43vnfGUVIMsF+wtVVWVKytQOgGcCxJK+tzKRmF/G/+QuDoGROhiytehb8d3hkykVqKP/aA32Xhwrvb6EIBxJkNb5whb+ZaB2xoLqqWA5ggGMy4taboaY0YIac8Y7Sm7Sv/Mx8C2zYTos63D7kbwsVmMsFOck8RB2ezUieZlccD1QelqS/kYI1y/BVqORPXDdPE7YXm4wPh0uebvmAtI2k/9hb73ejmMcOt6HH8Lo5ReQLNMwnwqcsTFGMCLQ8190d7xmnUH7iNvYQhtsX6e6lW/nZ0hYMLZI8S58Kxsf3rLaHhhtWA2FvRl0Mp4QurWtfrsR9etj0z8sFdSEHO6shv6j8/YX0rLkIyxjIe+NNmvpwSxaN4MI9ONvA52PqrxUeZZFg/3O4QuL7mFheHQ== holger2014 + + - username: bob + groups: + - ssh_login + - floss_admin + ssh_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABvA6ktfo/Y2/bW5LY1EwnGCvN3oxRE4w9X+VLbIxys1mSUbbYHJNgoruFT5CgxQqKMJSWlUYw+BPusLnxRsq6u4OAwWsVIWV2aTCLZIP1UzvuqKl3xQ1lEOd+9sKIwOAvprimkDU4u9qC6/ls96raMZXqxQLqw6IL4b4wleednPdv4uLIpvjQpJ/xNFGTWFV43vnfGUVIMsF+wtVVWVKytQOgGcCxJK+tzKRmF/G/+QuDoGROhiytehb8d3hkykVqKP/aA32Xhwrvb6EIBxJkNb5whb+ZaB2xoLqqWA5ggGMy4taboaY0YIac8Y7Sm7Sv/Mx8C2zYTos63D7kbwsVmMsFOck8RB2ezUieZlccD1QelqS/kYI1y/BVqORPXDdPE7YXm4wPh0uebvmAtI2k/9hb73ejmMcOt6HH8Lo5ReQLNMwnwqcsTFGMCLQ8190d7xmnUH7iNvYQhtsX6e6lW/nZ0hYMLZI8S58Kxsf3rLaHhhtWA2FvRl0Mp4QurWtfrsR9etj0z8sFdSEHO6shv6j8/YX0rLkIyxjIe+NNmvpwSxaN4MI9ONvA52PqrxUeZZFg/3O4QuL7mFheHQ== holger2014 + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBBobKeyHere bob@workstation + #state: present + state: absent + + - username: charlie + groups: + - ssh_login + - floss_sudo + ssh_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABvA6ktfo/Y2/bW5LY1EwnGCvN3oxRE4w9X+VLbIxys1mSUbbYHJNgoruFT5CgxQqKMJSWlUYw+BPusLnxRsq6u4OAwWsVIWV2aTCLZIP1UzvuqKl3xQ1lEOd+9sKIwOAvprimkDU4u9qC6/ls96raMZXqxQLqw6IL4b4wleednPdv4uLIpvjQpJ/xNFGTWFV43vnfGUVIMsF+wtVVWVKytQOgGcCxJK+tzKRmF/G/+QuDoGROhiytehb8d3hkykVqKP/aA32Xhwrvb6EIBxJkNb5whb+ZaB2xoLqqWA5ggGMy4taboaY0YIac8Y7Sm7Sv/Mx8C2zYTos63D7kbwsVmMsFOck8RB2ezUieZlccD1QelqS/kYI1y/BVqORPXDdPE7YXm4wPh0uebvmAtI2k/9hb73ejmMcOt6HH8Lo5ReQLNMwnwqcsTFGMCLQ8190d7xmnUH7iNvYQhtsX6e6lW/nZ0hYMLZI8S58Kxsf3rLaHhhtWA2FvRl0Mp4QurWtfrsR9etj0z8sFdSEHO6shv6j8/YX0rLkIyxjIe+NNmvpwSxaN4MI9ONvA52PqrxUeZZFg/3O4QuL7mFheHQ== holger2014 + diff --git a/users/inventory/hosts.yaml b/users/inventory/hosts.yaml new file mode 100644 index 0000000..286de60 --- /dev/null +++ b/users/inventory/hosts.yaml @@ -0,0 +1,6 @@ + +--- +all: + hosts: + localhost: + ansible_connection: local diff --git a/users/roles/users/README.md b/users/roles/users/README.md new file mode 100644 index 0000000..550ad8c --- /dev/null +++ b/users/roles/users/README.md @@ -0,0 +1,93 @@ +# How to use: + +## Adding a new user +To create a ssh key pair on the new users PC. +ssh-keygen -f new_floss_key +The 'private' part should NEVER leave the user's PC. + ( It is a good idea to add a keyphrase to protect the key, if the client PC is ever stolen or hacked.) + +you only need: new_floss_key.pub + +open inventory/group_vars/all/users.yaml +add a new entry: + - username: alice + groups: + - ssh_login + - floss_sudo + - floss_admin + ssh_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... alice@laptop + - replace this ^^^^ line, with new_floss_key.pub... + +deploy with: + ansible-playbook site.yaml + +## delete user: +open inventory/group_vars/all/users.yaml +add: + - username: alice + __state: absent__ +and rerun: + ansible-playbook site.yaml + + +# Troubleshoot: + +## ssh: +Check permissions in the users home. All files must be owned by the user, + # sudo find ~alice -ls + 4 drwxr-x--- 6 alice alice 4096 Jul 15 16:59 /home/alice + 4 drwx------ 2 alice alice 4096 Jul 15 16:58 /home/alice/.ssh + 4 -rw------- 1 alice alice 709 Jul 15 16:58 /home/alice/.ssh/authorized_keys +(only showing the important files ) Note, ssh may fail, if permission are too open, DONT do chmod 777 ... + +check groups: ( look for ssh_login ) + # id alice + uid=1005(alice) gid=1007(alice) groups=1007(alice),27(sudo),1005(ssh_login),1006(admin),1010(floss_sudo),1011(floss_admin) + +check that sshd is running + # sudo systemctl status ssh # (or ps -ef | grep sshd ) +and the config is ok: + # sudo sshd -t ( no output is good ) +restart with: + # sudo systemctl status ssh + +## sudo: +check groups ( look for floss_sudo and/or floss_admin ) + +check the sudoers file: + # visudo -cf /etc/sudoers.d/floss-sudo + /etc/sudoers.d/floss-sudo: parsed OK + +Try to redeploy, if it was changed. + + +# About the role: +# Users Ansible Role + +This role manages local Linux users, groups, SSH access, SSH keys, and sudo permissions. + +The role is designed to be multi-distribution and does not rely on distro-specific groups such as `sudo` or `wheel`. + +## Managed groups + +The role uses these groups: + +| Group | Purpose | +|---|---| +| `ssh_login` | Users in this group are allowed to log in via SSH | +| `floss_sudo` | Users in this group get passwordless sudo/root access | +| `floss_admin` | Users in this group get limited administrative commands | + +Additional groups can be added as required. + + +License +------- + +BSD + +Author Information +------------------ +version 1: holger + chatgpt + diff --git a/users/roles/users/defaults/main.yaml b/users/roles/users/defaults/main.yaml new file mode 100644 index 0000000..4d24c02 --- /dev/null +++ b/users/roles/users/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +# defaults file for users diff --git a/users/roles/users/floss b/users/roles/users/floss new file mode 100644 index 0000000..e9fdc34 --- /dev/null +++ b/users/roles/users/floss @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACDal1rP22oyImJzn6y4bzX3jPbMb+/5uso7nDX5jICNEQAAAJDUrVqG1K1a +hgAAAAtzc2gtZWQyNTUxOQAAACDal1rP22oyImJzn6y4bzX3jPbMb+/5uso7nDX5jICNEQ +AAAEBl5KA/jERAaBNMVfdGKlssfRt2BEHlq7D9FHqOkErBitqXWs/bajIiYnOfrLhvNfeM +9sxv7/m6yjucNfmMgI0RAAAAB2htQHRpbmsBAgMEBQY= +-----END OPENSSH PRIVATE KEY----- diff --git a/users/roles/users/floss.pub b/users/roles/users/floss.pub new file mode 100644 index 0000000..2c30fe4 --- /dev/null +++ b/users/roles/users/floss.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINqXWs/bajIiYnOfrLhvNfeM9sxv7/m6yjucNfmMgI0R hm@tink diff --git a/users/roles/users/handlers/main.yaml b/users/roles/users/handlers/main.yaml new file mode 100644 index 0000000..b689f6f --- /dev/null +++ b/users/roles/users/handlers/main.yaml @@ -0,0 +1,6 @@ + +--- +- name: Restart sshd + ansible.builtin.service: + name: ssh + state: restarted diff --git a/users/roles/users/meta/main.yaml b/users/roles/users/meta/main.yaml new file mode 100644 index 0000000..c572acc --- /dev/null +++ b/users/roles/users/meta/main.yaml @@ -0,0 +1,52 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.1 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/users/roles/users/tasks/groups.yaml b/users/roles/users/tasks/groups.yaml new file mode 100644 index 0000000..55dc302 --- /dev/null +++ b/users/roles/users/tasks/groups.yaml @@ -0,0 +1,7 @@ + +--- +- name: Ensure user groups exist + ansible.builtin.group: + name: "{{ item }}" + state: present + loop: "{{ users | map(attribute='groups') | flatten | unique }}" diff --git a/users/roles/users/tasks/main.yaml b/users/roles/users/tasks/main.yaml new file mode 100644 index 0000000..62ce863 --- /dev/null +++ b/users/roles/users/tasks/main.yaml @@ -0,0 +1,21 @@ +--- + +- name: Manage sudoers + ansible.builtin.import_tasks: sudoers.yaml + tags: + - sudoers + +- name: Manage groups + ansible.builtin.import_tasks: groups.yaml + tags: + - groups + +- name: Manage sshd + ansible.builtin.import_tasks: sshd.yaml + tags: + - sshd + +- name: Manage users + ansible.builtin.import_tasks: users.yaml + tags: + - users diff --git a/users/roles/users/tasks/sshd.yaml b/users/roles/users/tasks/sshd.yaml new file mode 100644 index 0000000..40fb00a --- /dev/null +++ b/users/roles/users/tasks/sshd.yaml @@ -0,0 +1,14 @@ +--- + +- name: Restrict SSH access to ssh_login group + ansible.builtin.copy: + dest: /etc/ssh/sshd_config.d/99-allowgroups.conf + content: | + AllowGroups ssh_login + owner: root + group: root + mode: "0644" + validate: "/usr/sbin/sshd -t -f %s" + notify: Restart sshd + +... diff --git a/users/roles/users/tasks/sudoers.yaml b/users/roles/users/tasks/sudoers.yaml new file mode 100644 index 0000000..0733e13 --- /dev/null +++ b/users/roles/users/tasks/sudoers.yaml @@ -0,0 +1,15 @@ + +--- +- name: Configure passwordless sudo for sudo group + ansible.builtin.copy: + dest: /etc/sudoers.d/floss-sudo + content: | + Defaults shell_noargs + %floss_sudo ALL=(ALL) NOPASSWD: ALL + %floss_admin ALL=(ALL) NOPASSWD: /usr/bin/netstat -ltp + %floss_admin ALL=(ALL) NOPASSWD: /bin/netstat -ltp + owner: root + group: root + mode: "0440" + validate: "/usr/sbin/visudo -cf %s" + diff --git a/users/roles/users/tasks/sudoers.yaml~ b/users/roles/users/tasks/sudoers.yaml~ new file mode 100644 index 0000000..411a807 --- /dev/null +++ b/users/roles/users/tasks/sudoers.yaml~ @@ -0,0 +1,12 @@ + +--- +- name: Configure passwordless sudo for sudo group + ansible.builtin.copy: + dest: /etc/sudoers.d/floss-sudo + content: | + %sudo ALL=(ALL:ALL) NOPASSWD: ALL + owner: root + group: root + mode: "0440" + validate: "/usr/sbin/visudo -cf %s" + diff --git a/users/roles/users/tasks/users.yaml b/users/roles/users/tasks/users.yaml new file mode 100644 index 0000000..58c8979 --- /dev/null +++ b/users/roles/users/tasks/users.yaml @@ -0,0 +1,36 @@ +--- +- name: Manage user accounts + ansible.builtin.user: + name: "{{ item.username }}" + state: "{{ item.state | default('present') }}" + create_home: "{{ item.create_home | default(true) }}" + shell: "{{ item.shell | default('/bin/bash') }}" + groups: "{{ item.groups | default([]) | join(',') }}" + append: true + remove: "{{ item.remove_home | default(true) }}" + loop: "{{ users }}" + + +- name: Create .ssh directories + ansible.builtin.file: + path: "/home/{{ item.username }}/.ssh" + state: directory + owner: "{{ item.username }}" + group: "{{ item.username }}" + mode: "0700" + loop: "{{ users }}" + when: item.state | default('present') == 'present' + +- name: Add SSH authorized keys + ansible.builtin.lineinfile: + path: "/home/{{ item.0.username }}/.ssh/authorized_keys" + line: "{{ item.1 }}" + create: true + owner: "{{ item.0.username }}" + group: "{{ item.0.username }}" + mode: "0600" + state: present + loop: "{{ users | subelements('ssh_keys', skip_missing=True) }}" + when: item.0.state | default('present') == 'present' + + diff --git a/users/roles/users/tests/inventory b/users/roles/users/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/users/roles/users/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/users/roles/users/tests/test.yaml b/users/roles/users/tests/test.yaml new file mode 100644 index 0000000..7925515 --- /dev/null +++ b/users/roles/users/tests/test.yaml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - users diff --git a/users/roles/users/vars/main.yaml b/users/roles/users/vars/main.yaml new file mode 100644 index 0000000..4070860 --- /dev/null +++ b/users/roles/users/vars/main.yaml @@ -0,0 +1,2 @@ +--- +# vars file for users diff --git a/users/site.yaml b/users/site.yaml new file mode 100644 index 0000000..9e91d28 --- /dev/null +++ b/users/site.yaml @@ -0,0 +1,10 @@ + +--- +- name: Configure Linux users and SSH access + hosts: all + become: true + gather_facts: false + + roles: + - users +