diff --git a/README.md b/README.md index 3afc0e6..5defc50 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,8 @@ The Option of these directory-variables are the following. | ``password`` | password hash | - | See [official FAQ](https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module) | | ``groups`` | list | - | Additional groups for your user | | ``remove`` | ``false`` | - | completly remove user if ``state: absent`` | -| ``only_sshd_config`` | ``false`` | Skip user and permission creation and only add user to SSHD config | + +There is also the ``l3d_users__ssh_login`` variable which only supports ``name`` and ``state``. It can be used to whitelist users to the sshd config. ### Other variables | name | default value | description | diff --git a/roles/admin/README.md b/roles/admin/README.md index f8acf49..462b140 100644 --- a/roles/admin/README.md +++ b/roles/admin/README.md @@ -31,7 +31,6 @@ The Option of these directory-variables are the following. | ``password`` | password hash | - | See [official FAQ](https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module) | | ``groups`` | list | - | Additional groups for your user | | ``remove`` | ``false`` | - | completly remove user if ``state: absent`` | -| ``only_sshd_config`` | ``false`` | Skip user and permission creation and only add user to SSHD config | ### Other diff --git a/roles/admin/tasks/users.yml b/roles/admin/tasks/users.yml index a82a2f9..aee20e8 100644 --- a/roles/admin/tasks/users.yml +++ b/roles/admin/tasks/users.yml @@ -11,7 +11,7 @@ loop_control: label: "user={{ user.name }}" loop_var: user - when: user.state | default ('present') == 'present' and user.admin | default(false) | bool and not user.only_sshd_config | default(false) | bool + when: user.state | default ('present') == 'present' and user.admin | default(false) | bool - name: Remove superpowers from Users become: true diff --git a/roles/dotfiles/README.md b/roles/dotfiles/README.md new file mode 100644 index 0000000..01fb07f --- /dev/null +++ b/roles/dotfiles/README.md @@ -0,0 +1,78 @@ + Ansible Role dotfiles +==================== + +Ansible role l3d.users.dotfiles create some dotfiles dor your users. + +There are two variables to define users. The ``l3d_users__default_users`` is ment to put to your group_vars to define a default for your system. The ``l3d_users__local_users`` could be put in your host_vars to define host-specific user and admin roles. + + Variables: +----------- + +### User Management + ++ The dictionary-variable for your group_vars to set your general users and admins is ``l3d_users__default_users``. ++ The dictionary-variable for your host_vars to set your host-specific users and admins is: ``l3d_users__local_users``. +The Option of these directory-variables are the following. + +| option | values | required | description | +| ------ | ------ | --- | --- | +| ``name`` | *string* | ``required`` | The user you want to create | +| ``state`` | ``present`` | - | Create or delete user | +| ``shell`` | ``/bin/bash`` | - | The Shell of the User | +| ``create_home`` | ``true`` | - | create a user home *(needed to store ssh keys)* | +| ``admin`` | ``false`` | - | enable it to give the user superpowers | +| ``admin_commands`` | *string or list* | - | Commands that are allows to be run as admin, eg. 'ALL' or specific script | +| ``admin_nopassword`` | ``false`` | - | Need no Password for sudo | +| ``admin_ansible_login`` | ``true`` | - |if ``admin: true`` and ``l3d_users__create_ansible: true`` your ssh keys will be added to ansible user | +| ``pubkeys`` | string or lookup | - | see examples | +| ``exklusive_pubkeys`` | ``true`` | - | delete all undefined ssh keys | +| ``password`` | password hash | - | See [official FAQ](https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module) | +| ``groups`` | list | - | Additional groups for your user | +| ``remove`` | ``false`` | - | completly remove user if ``state: absent`` | + +There is a third directory-variable called ``l3d_users__ssh_login: []`` which only support ``name`` and ``state`` for users, that sould be able to login on that system. + +### Other Variables + +| name | default value | description | +| --- | --- | --- | +| ``l3d_users__limit_login`` | ``true`` | Only allow SSH login for specified users | +| ``l3d_users__sshd_port`` | ``22`` | Port for SSH | +| ``l3d_users__sshd_password_authentication`` | ``false`` | Allow login with Password | +| ``l3d_users__sshd_permitrootlogin`` | ``false`` | Allow login as root | +| ``l3d_users__create_ansible`` | ``true`` | Create Ansible User | +| ``l3d_users__ansible_user_state`` | ``present`` | Ansible User State | +| ``l3d_users__sshd_manage_server_key_types`` | ``true`` | Manage Server SSH Key types | +| ``l3d_users__sshd_server_key_types`` | ``['ed25519']`` | List of supported SSH Key Types | +| ``l3d_users__sshd_manage_key_algorithmus`` | ``true`` | Manage SSH Key Algorythmins | +| ``l3d_users__sshd_key_algorithmus`` | ``['ssh-ed25519-cert-v01@openssh.com', 'ssh-ed25519', 'ecdsa-sha2-nistp521-cert-v01@openssh.com', 'ecdsa-sha2-nistp384-cert-v01@openssh.com', 'ecdsa-sha2-nistp256-cert-v01@openssh.com']`` | Used SSH Key Algorithms | +| ``l3d_users__sshd_manage_kex_algorithmus`` | ``true`` | Manage SSH Kex Algorythms | +| ``l3d_users__sshd_kex_algorithmus`` | ``['curve25519-sha256@libssh.org', 'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group-exchange-sha1']`` | Used Kex Algorythms | +| ``l3d_users__sshd_manage_ciphers`` | ``true`` | Manage SSH Ciphers | +| ``l3d_users__sshd_ciphers`` | ``['chacha20-poly1305@openssh.com', 'aes256-gcm@openssh.com', 'aes256-ctr']`` | Used SSH Ciphers | +| ``l3d_users__sshd_manage_macs`` | ``true`` | Manage Used MACs | +| ``l3d_users__sshd_macs`` | ``['hmac-sha2-512-etm@openssh.com', 'hmac-sha2-256-etm@openssh.com', 'hmac-sha2-512']`` | Used MACs | +| ``l3d_users__sshd_xforwarding`` |``true`` | Enable X-Forwarding | +| ``submodules_versioncheck`` | ``false`` | Optionaly enable simple versionscheck of this role | + + Example Playbook +----------------- +```yaml +- name: Create System with User and Passwords + hosts: example.com + roles: + - {role: l3d.users.dotfiles, tags: 'dotfiles'} + vars: + l3d_users__local_users: + - name: 'alice' + state: 'present' + - name: 'bob' + state: 'present' + l3d_users__ssh_login: + - name: 'charlie' + state: 'present' + + l3d_users__limit_login: true + l3d_users__create_ansible: true + submodules_versioncheck: true +``` diff --git a/roles/dotfiles/defaults/main.yml b/roles/dotfiles/defaults/main.yml new file mode 100644 index 0000000..ea1a278 --- /dev/null +++ b/roles/dotfiles/defaults/main.yml @@ -0,0 +1,85 @@ +--- +# create users +l3d_users__default_users: [] +# - name: 'alice' +# state: 'present' +# shell: '/bin/bash' +# create_home: true +# pubkeys: | +# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPvvXN33GwkTF4ZOwPgF21Un4R2z9hWUuQt1qIfzQyhC +# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAG65EdcM+JLv0gnzT9LcqVU47Pkw0SqiIg7XipXENi8 +# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJz7zEvUVgJJJsIgfG3izsqYcM22IaKz4jGVUbNRL2PX +# exklusive_pubkeys: true +# password: "$Password_hash" +# admin: true +# admin_commands: 'ALL' +# admin_nopassword: false +# admin_ansible_login: true +# - name: 'bob' +# state: 'present' +# shell: '/bin/zsh' +# admin: false +# pubkeys: "{{ lookup('url', 'https://github.com/do1jlr.keys', split_lines=False) }}" +# exklusive_pubkeys: false + +l3d_users__local_users: [] +# - name: 'charlie' +# state: 'present' +# admin: false +# pubkeys: "{{ lookup('url', 'https://github.com/do1jlr.keys', split_lines=False) }}" + +l3d_users__ssh_login: [] +# - name: 'dora' +# state: 'present' + +l3d_users__limit_login: true + +l3d_users__sshd_port: 22 +l3d_users__sshd_password_authentication: false +l3d_users__sshd_permitrootlogin: false +l3d_users__create_ansible: true +l3d_users__ansible_user_state: 'present' + +l3d_users__sshd_manage_server_key_types: true +l3d_users__sshd_server_key_types: + - 'ed25519' + # - 'rsa' + # - 'ecdsa' + +l3d_users__sshd_manage_key_algorithmus: true +l3d_users__sshd_key_algorithmus: + - 'ssh-ed25519-cert-v01@openssh.com' + - 'ssh-ed25519' + - 'ecdsa-sha2-nistp521-cert-v01@openssh.com' + - 'ecdsa-sha2-nistp384-cert-v01@openssh.com' + - 'ecdsa-sha2-nistp256-cert-v01@openssh.com' + # - 'rsa-sha2-512-cert-v01@openssh.com' + # - 'rsa-sha2-256-cert-v01@openssh.com' + # - 'ssh-rsa-cert-v01@openssh.com' + # - 'ecdsa-sha2-nistp521' + # - 'ecdsa-sha2-nistp384' + # - 'ecdsa-sha2-nistp256' + # - 'rsa-sha2-512' + # - 'rsa-sha2-256' + # - 'ssh-rsa' + +l3d_users__sshd_manage_kex_algorithmus: true +l3d_users__sshd_kex_algorithmus: + - 'curve25519-sha256@libssh.org' + - 'diffie-hellman-group-exchange-sha256' + - 'diffie-hellman-group-exchange-sha1' + # - 'diffie-hellman-group14-sha1' + # - 'diffie-hellman-group1-sha1' + +l3d_users__sshd_manage_ciphers: true +l3d_users__sshd_ciphers: + - 'chacha20-poly1305@openssh.com' + - 'aes256-gcm@openssh.com' + - 'aes256-ctr' + # - 'aes256-cbc' + # - 'aes128-ctr' + # - 'aes128-cbc' + + +# run simple versionscheck +submodules_versioncheck: false diff --git a/roles/dotfiles/handlers/main.yml b/roles/dotfiles/handlers/main.yml new file mode 100644 index 0000000..9c3acd9 --- /dev/null +++ b/roles/dotfiles/handlers/main.yml @@ -0,0 +1,8 @@ +--- +- name: Restart SSHD Server + become: true + listen: 'systemctl restart sshd' + ansible.builtin.systemd: + name: "{{ l3d_users__sshd_service }}" + state: restarted + when: sshd__service is defined and ansible_service_mgr == 'systemd' diff --git a/roles/dotfiles/meta/main.yml b/roles/dotfiles/meta/main.yml new file mode 100644 index 0000000..fcc32c0 --- /dev/null +++ b/roles/dotfiles/meta/main.yml @@ -0,0 +1,23 @@ +--- +galaxy_info: + role_name: sshd + author: l3d + description: Ansible role l3d.users.sshd to Manage SSHD Configuration of the system and which Accounts are allowed to login + license: "MIT" + min_ansible_version: "2.16" + platforms: + - name: Debian + versions: ['all'] + - name: Ubuntu + versions: ['all'] + - name: Fedora + versions: ['all'] + - name: EL + versions: ['all'] + galaxy_tags: + - sshd + - ssh + - users + - setup + - linux +dependencies: [] diff --git a/roles/dotfiles/tasks/main.yml b/roles/dotfiles/tasks/main.yml new file mode 100644 index 0000000..35e92aa --- /dev/null +++ b/roles/dotfiles/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- name: Perform optional versionscheck + ansible.builtin.include_tasks: + file: 'versioncheck.yml' + when: submodules_versioncheck | bool + +- name: Install dotfiles packages + ansible.builtin.include_tasks: + file: 'packages.yml' + +- name: Setup and configure bashrc + ansible.builtin.include_tasks: + file: 'packages.yml' + when: diff --git a/roles/dotfiles/tasks/packages.yml b/roles/dotfiles/tasks/packages.yml new file mode 100644 index 0000000..34f5001 --- /dev/null +++ b/roles/dotfiles/tasks/packages.yml @@ -0,0 +1,15 @@ +--- +- name: Update apt cache + become: true + ansible.builtin.apt: + cache_valid_time: 3600 + update_cache: true + when: + - ansible_pkg_mgr == "apt" + +- name: Install dotfile packages + become: true + ansible.builtin.package: + name: "{{ item }}" + state: 'present' + with_items: "{{ l3d_users__dotfiles_packages }}" diff --git a/roles/dotfiles/tasks/versioncheck.yml b/roles/dotfiles/tasks/versioncheck.yml new file mode 100644 index 0000000..e901618 --- /dev/null +++ b/roles/dotfiles/tasks/versioncheck.yml @@ -0,0 +1,46 @@ +--- +# Copyright (c) 2021 L3D +# this file is released with the MIT license. +# License: https://github.com/roles-ansible/ansible_role_template/blob/main/LICENSE +- name: Create directory for versionscheck + become: true + ansible.builtin.file: + path: '/etc/.ansible-version' + state: directory + mode: '0755' + when: submodules_versioncheck | bool + +- name: Check playbook version + become: true + ansible.builtin.slurp: + src: "/etc/.ansible-version/{{ playbook_version_path }}" + register: playbook_version + when: submodules_versioncheck | bool + failed_when: false + +- name: Print remote role version # noqa: H500 + ansible.builtin.debug: + msg: "Remote role version: {{ playbook_version.content | default('Y3VycmVudGx5IG5vdCBkZXBsb3llZAo=') | b64decode | string }}" + when: submodules_versioncheck | bool + +- name: Print locale role version # noqa: H500 + ansible.builtin.debug: + msg: "Local role version: '{{ playbook_version_number | string }}'." + when: submodules_versioncheck | bool + +- name: Check if your version is outdated + ansible.builtin.fail: + msg: "Your ansible module has the version '{{ playbook_version_number }}' and is outdated. You need to update it!" + when: + - playbook_version.content|default("Mgo=")|b64decode|int - 1 >= playbook_version_number|int and submodules_versioncheck | bool + +- name: Write new version to remote disk + become: true + ansible.builtin.copy: + content: "{{ playbook_version_number }}" + dest: "/etc/.ansible-version/{{ playbook_version_path }}" + mode: '0644' + when: submodules_versioncheck | bool + tags: skip_ansible_lint_template-instead-of-copy + notify: + - 'systemctl restart sshd' diff --git a/roles/dotfiles/templates/sshd_config.j2 b/roles/dotfiles/templates/sshd_config.j2 new file mode 100644 index 0000000..b61a262 --- /dev/null +++ b/roles/dotfiles/templates/sshd_config.j2 @@ -0,0 +1,136 @@ +# Attention, local changew will be overwritten +# MIT (C) L3D +# {{ ansible_managed }} +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +{% if _sshd_version | default(7.0) | float > 8.0 | bool %} +# Include SSHD config snippets +# Support fot this starts with sshd 8.0 +Include /etc/ssh/sshd_config.d/*.conf +{% endif %} + +# Networking +Port {{ l3d_users__sshd_port }} +AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: + +TCPKeepAlive yes + +# SSHD Key exchange +{% if l3d_users__sshd_manage_key_algorithmus | bool %} +# -> HostkeyAlgorithms +HostkeyAlgorithms {{ l3d_users__sshd_key_algorithmus | join(',') }} +{% else %} +# No HostkeyAlgorithms defined +{% endif %} + +{% if l3d_users__sshd_manage_kex_algorithmus | bool %} +# -> KexAlgorithms +KexAlgorithms {{ l3d_users__sshd_kex_algorithmus | join(',') }} +{% else %} +# No KexAlgorithms defined +{% endif %} + +# Ciphers and keying +{% if l3d_users__sshd_manage_ciphers | bool %} +# -> Ciphers +Ciphers {{ l3d_users__sshd_ciphers | join(',') }} +{% else %} +# No Ciphers defined +{% endif %} + +{% if l3d_users__sshd_manage_macs | bool %} +# -> Macs +MACs {{ l3d_users__sshd_macs | join(',') }} +{% else %} +# No MACs defined +{% endif %} + +# Server Authentication +Protocol 2 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# SSHD Host Keys +{% if l3d_users__sshd_manage_server_key_types | bool %} +{% for key in l3d_users__sshd_server_key_types %} +# -> {{ key }} +HostKey /etc/ssh/ssh_host_{{ key }}_key +{% endfor %} +{% endif %} + +# Client authentication +MaxAuthTries 6 +MaxSessions 10 +PasswordAuthentication {{ l3d_users__sshd_password_authentication | ternary('yes', 'no') }} +ChallengeResponseAuthentication no +PubkeyAuthentication yes +PermitRootLogin {{ l3d_users__sshd_permitrootlogin | ternary('without-password', 'no') }} +LoginGraceTime 120 +StrictModes yes +X11Forwarding {{ l3d_users__sshd_xforwarding | ternary('yes', 'no') }} + +AllowTcpForwarding yes +#GatewayPorts no +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PermitTTY yes + +PrintMotd no +PrintLastLog yes +TCPKeepAlive yes + +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS no +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 +#PermitTunnel no +#ChrootDirectory none +#VersionAddendum none + +# no default banner path +#Banner none + + +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM yes + +{% set _sshd_accounts = [] %} +{% for user in _l3d_users__merged_users %} +{% if user.name is defined and user.state | default('present') == 'present' %} +{% set _ = _sshd_accounts.append(user.name) %} +{% endif %} +{% endfor %} + +# User Authentication +{% if l3d_users__create_ansible | bool and l3d_users__ansible_user_state == 'present' %} +AllowUsers ansible {{ _sshd_accounts | join(' ') }} + +# Group Authentication +AllowGroups ansible {{ _sshd_accounts | join(' ') }} +{% else %} +AllowUsers {{ _sshd_accounts | join(' ') }} + +# Group Authentication +AllowGroups {{ _sshd_accounts | join(' ') }} +{% endif %} + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +# sftp (required by ansible) +# Subsystem sftp /usr/lib/openssh/sftp-server +{% if ansible_os_family == 'RedHat' %} +Subsystem sftp /usr/libexec/openssh/sftp-server +{% else %} +Subsystem sftp /usr/lib/openssh/sftp-server +{% endif %} diff --git a/roles/dotfiles/vars/main.yml b/roles/dotfiles/vars/main.yml new file mode 100644 index 0000000..1cdd8e7 --- /dev/null +++ b/roles/dotfiles/vars/main.yml @@ -0,0 +1,9 @@ +--- +l3d_users__dotfiles_packages: + - bash + - vim + - htop + - ranger + +playbook_version_number: 2 +playbook_version_path: 'l3d.users.dotfiles.version' diff --git a/roles/sshd/README.md b/roles/sshd/README.md index 22ceb8c..26d93f1 100644 --- a/roles/sshd/README.md +++ b/roles/sshd/README.md @@ -29,7 +29,6 @@ The Option of these directory-variables are the following. | ``password`` | password hash | - | See [official FAQ](https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module) | | ``groups`` | list | - | Additional groups for your user | | ``remove`` | ``false`` | - | completly remove user if ``state: absent`` | -| ``only_sshd_config`` | ``false`` | Skip user and permission creation and only add user to SSHD config | There is a third directory-variable called ``l3d_users__ssh_login: []`` which only support ``name`` and ``state`` for users, that sould be able to login on that system. diff --git a/roles/user/README.md b/roles/user/README.md index d256777..354685d 100644 --- a/roles/user/README.md +++ b/roles/user/README.md @@ -31,7 +31,6 @@ The Option of these directory-variables are the following. | ``password`` | password hash | - | See [official FAQ](https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module) | | ``groups`` | list | - | Additional groups for your user | | ``remove`` | ``false`` | - | completly remove user if ``state: absent`` | -| ``only_sshd_config`` | ``false`` | Skip user and permission creation and only add user to SSHD config | ### Other Variables diff --git a/roles/user/tasks/pubkeys.yml b/roles/user/tasks/pubkeys.yml index d5a0927..58b2684 100644 --- a/roles/user/tasks/pubkeys.yml +++ b/roles/user/tasks/pubkeys.yml @@ -10,4 +10,4 @@ loop_control: label: "user={{ user.name }}" loop_var: user - when: user.state | default ('present') == 'present' and not user.only_sshd_config | default(false) | bool + when: user.state | default ('present') == 'present' diff --git a/roles/user/tasks/users.yml b/roles/user/tasks/users.yml index 07dd62c..c5c49be 100644 --- a/roles/user/tasks/users.yml +++ b/roles/user/tasks/users.yml @@ -8,7 +8,7 @@ loop_control: label: "user={{ user.name }}" loop_var: user - when: user.state | default ('present') == 'present' and not user.only_sshd_config | default(false) | bool + when: user.state | default ('present') == 'present' - name: Create Accounts for Users become: true @@ -26,7 +26,7 @@ loop_control: label: "user={{ user.name }}" loop_var: user - when: user.state | default ('present') == 'present' and not user.only_sshd_config | default(false) | bool + when: user.state | default ('present') == 'present' - name: Remove Accounts for Users become: true