#SPDX-License-Identifier: MIT-0 --- # tasks file for bootstrap - name: Create directory for MOTD update scripts ansible.builtin.file: force: true group: root owner: root path: /etc/update-motd.d state: directory - name: Create MOTD update scripts ansible.builtin.copy: force: true backup: true group: root mode: "0744" owner: root dest: "/etc/update-motd.d/{{ item }}" src: "update-motd.d/{{ item }}" state: present loop: "{{ hostvars[inventory_hostname].vps_service.ssh_motd_script_basenames }}" - name: Create hidden SSH directories under users' home directories when: hostvars[inventory_hostname].groups.remote.group_name in item.value.groups ansible.builtin.file: group: "{{ item.value.group | default(item.value.username) }}" mode: "0700" owner: "{{ item.value.username }}" path: "{{ item.value.home | default('/home/' ~ item.value.username) }}/.ssh" state: directory loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}" tags: - ensure_paths - ensure_files - name: Add authorized SSH public keys for users when: hostvars[inventory_hostname].groups.remote.group_name in item.value.groups and item.value.ssh_authorized_keys is not None and len(item.value.ssh_authorized_keys) > 0 ansible.builtin.copy: backup: true content: "{{ '\n'.join(item.value.ssh_authorized_keys) }}" dest: "{{ item.value.home | default('/home/' ~ item.value.username) }}/.ssh/authorized_keys" # follow: true force: true group: "{{ item.value.group | default(item.value.username) }}" mode: "0600" owner: "{{ item.value.username }}" loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}" tags: - ensure_files - name: Harden SSH security block: - name: Create public subdirectory for SSH's SFTP-exclusive user's chroot when: "'sftp' in item.value.services" ansible.builtin.file: group: "{{ item.value.group | default(item.value.username) }}" owner: "{{ item.value.username }}" path: "{{ item.value.home | default('/home/' ~ item.value.username) }}/public" state: directory loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}" - name: Set users in group ftp to only be usable with SSH's SFTP service when: "'sftp' in item.value.services" ansible.builtin.blockinfile: backup: true block: |2 Match User {{ item.value.username }} ForceCommand internal-sftp -d /public AuthorizedKeysFile {{ item.value.home | default('/home/' ~ item.value.username) }}/.ssh/authorized_keys Match Group {{ item.value.group | default(item.value.username) }} ForceCommand internal-sftp -d /%u ChrootDirectory {{ item.value.home | default('/home/' ~ item.value.username) }} AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no create: true group: root insertafter: EOF marker: "# {mark} ANSIBLE-MANAGED SFTP BLOCK" marker_begin: BEGIN marker_end: END owner: root path: /etc/ssh/sshd_config.d/sftp.conf append_newline: true state: present validate: /bin/sshd -t loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}" tags: - sftp_auth_step - name: Switch to preferred SSH authentication method ansible.builtin.template: backup: true comment_end_string: "#}" comment_start_string: "{#" dest: /etc/ssh/sshd_config.d/auth.conf # follow: true force: true group: root owner: root src: sshd_config.d/auth.conf.j2 validate: /bin/sshd -t vars: empty_auth_used: false pass_auth_used: false pam_auth_used: true key_auth_used: true tags: - ssh_auth_step - name: Constrain idle online user accounts ansible.builtin.template: backup: true comment_end_string: "#}" comment_start_string: "{#" dest: /etc/ssh/sshd_config.d/harden.conf force: true group: root owner: root src: sshd_config.d/harden.conf.j2 validate: /bin/sshd -t vars: client_subsistence: 900 client_subsist_warn_max: 3 tags: - ssh_timeout_step - name: Toggle ability to log in as root via SSH when: "hostvars[inventory_hostname].vps_service.root_fate == 'disposal'" ansible.builtin.template: backup: true comment_end_string: "#}" comment_start_string: "{#" dest: /etc/ssh/sshd_config.d/denyroot.conf force: true group: root owner: root src: sshd_config.d/denyroot.conf.j2 validate: /bin/sshd -t vars: root_login_allowed: false tags: - ssh_root_step - name: Specify users or groups to whitelist or blacklist for SSH login when: "hostvars[inventory_hostname].vps_service.root_fate == 'disposal'" ansible.builtin.template: backup: true comment_end_string: "#}" comment_start_string: "{#" dest: /etc/ssh/sshd_config.d/allowance.conf force: true group: root owner: root src: sshd_config.d/allowance.conf.j2 validate: /bin/sshd -t vars: list_type: whitelist policed_groups: - "{{ hostvars[inventory_hostname].groups.remote.group_name }}" tags: - ssh_gate_step tags: - ssh_harden_step