diff --git a/group_vars/all/vars.yml b/group_vars/all/vars.yml index 28a109e78..a7f2929ee 100644 --- a/group_vars/all/vars.yml +++ b/group_vars/all/vars.yml @@ -48,6 +48,16 @@ auth_groups: umcg-atd: gid: 20005 # +# Default for a group of users that are only allowd to transfer data. +# Is used by the sshd role and listed in +# roles/sshd/defaults/main.yml, +# but that file is not used when the +# roles/sshd/templates/sshd_config +# is redeployed by other roles like the ldap or sssd roles. +# Therefore we set a default here too. +# +data_transfer_only_group: sftp-only +# # Custom/extra yum repos # yum_repos: diff --git a/roles/ldap/handlers/main.yml b/roles/ldap/handlers/main.yml index e74af4721..6a9b8e631 100644 --- a/roles/ldap/handlers/main.yml +++ b/roles/ldap/handlers/main.yml @@ -23,4 +23,9 @@ state: restarted become: true listen: restart_sshd + +- name: Run authconfig update to enable ldap. + command: "authconfig --enableldap --enableldapauth --update" + become: true + listen: authconfig_enable_ldap ... diff --git a/roles/ldap/tasks/main.yml b/roles/ldap/tasks/main.yml index 448306196..8465ac9bc 100644 --- a/roles/ldap/tasks/main.yml +++ b/roles/ldap/tasks/main.yml @@ -90,6 +90,13 @@ daemon_reload: true become: true +- name: Check if we need to update authconfig. + command: + cmd: /usr/sbin/authconfig --test + register: authconfig_test + changed_when: ('nss_ldap is disabled' in authconfig_test.stdout) or ('pam_ldap is disabled' in authconfig_test.stdout) + notify: authconfig_enable_ldap + - name: Redeploy sshd config. ansible.builtin.template: src: "{{ playbook_dir }}/roles/sshd/templates/sshd_config" diff --git a/roles/logins/files/login_checks.sh b/roles/logins/files/login_checks.sh deleted file mode 100644 index 9f17a375e..000000000 --- a/roles/logins/files/login_checks.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -set -u - -# -## -### Variables. -## -# -SLURM_ACCOUNT='users' -# Set a tag for the log entries. -LOGGER='logger --tag login_checks' - -# -## -### Functions. -## -# - -# -# Usage: run_with_timeout N cmd args... -# or: run_with_timeout cmd args... -# In the second case, cmd cannot be a number and the timeout will be 10 seconds. -# -run_with_timeout () { - local time=10 - if [[ $1 =~ ^[0-9]+$ ]]; then time=$1; shift; fi - # - # Run in a subshell to avoid job control messages. - # - ( "$@" & - child=$! - # - # Avoid default notification in non-interactive shell for SIGTERM. - # - trap -- "" SIGTERM - ( sleep $time - kill $child 2> /dev/null - ) & - wait $child - ) -} - -login_actions () { - # - # Check if login user exists as SLURM user in the SLURM accounting DB. - # - if [ "$(sacctmgr -p list user "${PAM_USER}" format=User | grep -o "${PAM_USER}")" == "${PAM_USER}" ]; then - if [ "${PAM_USER}" != 'root' ]; then - # Only log for users other than root to prevend flooding the logs... - $LOGGER "User ${PAM_USER} already exists in SLURM DB." - fi - else - # - # Create account in SLURM accounting DB. - # - local _log_message="Creating user ${PAM_USER} in SLURM accounting DB..." - local _status="$(sacctmgr -iv create user name=${PAM_USER} account=${SLURM_ACCOUNT} fairshare=1 2>&1)" - # - # Checking for exit status does not work when executed by pam-script :( - # Therefore we explicitly re-check if the user now exists in the SLURM DB... - # - #if [ $? -eq 0 ]; then - if [ "$(sacctmgr -p list user "${PAM_USER}" format=User | grep -o "${PAM_USER}")" == "${PAM_USER}" ]; then - _log_message="${_log_message}"' done!' - else - _log_message="${_log_message}"' FAILED. You cannot submit jobs. Contact an admin!' - $LOGGER "${_status}" - fi - $LOGGER -s "${_log_message}" - fi -} - -# -## -### Main. -## -# - -# -# Make sure we execute this file only for interactive sessions with a real shell. -# Hence not for SFTP connections, -# which will terminate instantly when anything that is not a valid FTP command is printed on STDOUT or STDERR. -# For SFTP connections as well as SLURM jobs the TERM type is dumb, -# but in the first case there are no SLURM related environment variables defined. -# - -# -# ToDo: fix this. As of CentOS 7.x interactive session that eventually report ${TERM} == 'bash' -# report ${TERM} == 'dumb' at the point where this script is executed in the PAM stack :(. -# Makes it impossible to determine the difference between an SFTP session versus a Bash session. -# -if [ ${TERM} == 'dumb' ] && [ -z "${SOURCE_HPC_ENV:-}" ]; then - $LOGGER "debug: exiting because of dumb terminal" - exit 0 -fi - -# -# Run the desired login actions with a timeout of 10 seconds. -# -run_with_timeout 10 login_actions - -exit 0 diff --git a/roles/logins/files/login_checks_regular_home.sh b/roles/logins/files/login_checks_regular_home.sh new file mode 100644 index 000000000..3ee8b58c8 --- /dev/null +++ b/roles/logins/files/login_checks_regular_home.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +set -u + +# +## +### Variables. +## +# +# Set a tag for the log entries. +LOGGER='logger --tag login_checks' + +# +## +### Functions. +## +# + +# +# Usage: run_with_timeout N cmd args... +# or: run_with_timeout cmd args... +# In the second case, cmd cannot be a number and the timeout will be 10 seconds. +# +run_with_timeout () { + local time=10 + if [[ "${1}" =~ ^[0-9]+$ ]]; then time="${1}"; shift; fi + # + # Run in a subshell to avoid job control messages. + # + ( "${@}" & + child="${!}" + # + # Avoid default notification in non-interactive shell for SIGTERM. + # + trap -- "" SIGTERM + ( sleep "${time}" + kill "${child}" 2> /dev/null + ) & + wait "${child}" + ) +} + +login_actions () { + # + # Check if permissions on home dir are correct if home dir exists. + # + if [[ "${PAM_USER}" != 'root' ]]; then + home_dir="/home/${PAM_USER}/" + if [[ -e "${home_dir}" ]]; then + owner=$(stat -L -c '%U' "${home_dir}") + group=$(stat -L -c '%G' "${home_dir}") + mode=$(stat -L -c '%a' "${home_dir}") + if [[ "${owner}" != "${PAM_USER}" ]]; then + ${LOGGER} "ERROR: Home dir for user ${PAM_USER} is owned by: ${owner}." + ${LOGGER} "WARN: Fixing owner for ${home_dir} ${owner} -> ${PAM_USER} ..." + chown --dereference --silent "${PAM_USER}" "${home_dir}" + fi + if [[ "${group}" != "${PAM_USER}" ]]; then + ${LOGGER} "ERROR: Home dir for user ${PAM_USER} is in the wrong group: ${group}." + ${LOGGER} "WARN: Fixing group for ${home_dir} ${group} -> ${PAM_USER} ..." + chgrp --dereference --silent "${PAM_USER}" "${home_dir}" + fi + mode_regex='700$' + if [[ ! "${mode}" =~ ${mode_regex} ]]; then + ${LOGGER} "ERROR: Home dir for user ${PAM_USER} has wrong permissions mode: ${mode}." + ${LOGGER} "WARN: Fixing permissions for ${home_dir} ${mode} -> 700 ..." + chmod --silent 700 "${home_dir}" + fi + fi + fi +} + +# +## +### Main. +## +# + +# +# Run the desired login actions with a timeout of 10 seconds. +# +run_with_timeout 10 login_actions + +exit 0 diff --git a/roles/logins/files/password-auth-ac b/roles/logins/files/password-auth-ac deleted file mode 100644 index b7036a578..000000000 --- a/roles/logins/files/password-auth-ac +++ /dev/null @@ -1,27 +0,0 @@ -#%PAM-1.0 -# This file is auto-generated. -# User changes will be destroyed the next time authconfig is run. -auth required pam_env.so -auth sufficient pam_ldap.so nullok try_first_pass -auth requisite pam_succeed_if.so uid >= 500 quiet -auth sufficient pam_unix.so use_first_pass -auth required pam_deny.so - -account required pam_unix.so broken_shadow -account sufficient pam_localuser.so -account sufficient pam_succeed_if.so uid < 500 quiet -account [default=bad success=ok user_unknown=ignore] pam_ldap.so -account required pam_permit.so - -password requisite pam_cracklib.so try_first_pass retry=3 type= -password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok -password sufficient pam_ldap.so use_authtok -password required pam_deny.so - -session optional pam_keyinit.so revoke -session required pam_limits.so -session optional pam_oddjob_mkhomedir.so umask=0077 skel=/etc/skel -session optional pam_script.so -session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid -session required pam_unix.so -session optional pam_ldap.so diff --git a/roles/logins/files/password-auth-local b/roles/logins/files/password-auth-local new file mode 100644 index 000000000..af2465f32 --- /dev/null +++ b/roles/logins/files/password-auth-local @@ -0,0 +1,12 @@ +#%PAM-1.0 +# +# This is managed with ansible. +# +auth include password-auth-ac + +account include password-auth-ac + +password include password-auth-ac + +session include password-auth-ac +session optional pam_script.so diff --git a/roles/logins/handlers/main.yml b/roles/logins/handlers/main.yml index 6160490c8..6669ed16d 100644 --- a/roles/logins/handlers/main.yml +++ b/roles/logins/handlers/main.yml @@ -7,7 +7,7 @@ - name: 'Run authconfig update.' command: "authconfig --enablemkhomedir --update" become: true - listen: authconfig_update + listen: authconfig_enable_mkhomedir # # Notes: diff --git a/roles/logins/tasks/main.yml b/roles/logins/tasks/main.yml index fd6e3ef1a..9f05f97bd 100644 --- a/roles/logins/tasks/main.yml +++ b/roles/logins/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: 'Create cron job to restart systemd-logind regularly as workaround for known DBus bug.' - cron: + ansible.builtin.cron: # # Silly workaround for bug in interaction dbus <-> logind # Need DBus 1.11.10 for a fix, but CentOS 7.6 is stuck on dbus 1.10.24. @@ -13,31 +13,19 @@ become: true - name: 'Install yum dependencies.' - yum: + ansible.builtin.yum: state: 'latest' update_cache: true name: - pam_script - oddjob-mkhomedir notify: - - authconfig_update - - restart_oddjobd - become: true - -- name: 'Deploy password-auth-ac for PAM.' - copy: - src: 'password-auth-ac' - dest: '/etc/pam.d/password-auth-ac' - owner: root - group: root - mode: '0600' - notify: - - authconfig_update + - authconfig_enable_mkhomedir - restart_oddjobd become: true - name: 'Enable pam_script.' - file: # noqa risky-file-permissions + ansible.builtin.file: # noqa risky-file-permissions src: 'pam_script' dest: "/etc/{{ item }}" state: link @@ -50,7 +38,7 @@ become: true - name: 'Create /etc/pam-script.d/ dir.' - file: + ansible.builtin.file: name: '/etc/pam-script.d' state: directory owner: root @@ -58,48 +46,36 @@ mode: '0755' become: true -# -# Login checks to handle slurm accounts currently disabled, -# because error handling/reporting no longer works on CentOS >= 7.x, -# due to changes in the PAM stack. -# Login checks were only used to create Slurm accounts in the Slurm accounting DB. -# This functionality has been relocated to the Slurm job_submit.lua plugin, -# which will now automatically create account, users and associations of slurm users to slurm accounts -# upon job submission when they do not already exist. -# -# - name: Install login_checks.sh script. -# copy: -# src: 'login_checks.sh' -# dest: '/etc/pam-script.d/login_checks.sh' -# owner: root -# group: root -# mode: '0755' -# when: inventory_hostname in groups['cluster'] -# become: true -# -# - name: Enable login_checks.sh script for ses_open. -# file: # noqa risky-file-permissions -# src: "{{ item }}" -# dest: "/etc/pam-script.d/{{ item }}_ses_open" -# owner: root -# group: root -# state: link -# with_items: -# - login_checks.sh -# when: inventory_hostname in groups['cluster'] -# become: true -# -- name: 'Disable login_checks.sh script as we use the Slurm job_submit.lua plugin now.' - file: - path: "/etc/pam-script.d/{{ item }}" - state: absent +- name: 'Install login_checks_regular_home.sh script.' + ansible.builtin.copy: + src: login_checks_regular_home.sh + dest: /etc/pam-script.d/login_checks_regular_home.sh + owner: root + group: root + mode: '0755' + when: + - inventory_hostname in groups['jumphost'] | default([]) or + inventory_hostname in groups['data_transfer'] | default([]) or + inventory_hostname in groups['cluster'] | default([]) + become: true + +- name: 'Enable login_checks.sh script for ses_open.' + ansible.builtin.file: # noqa risky-file-permissions + src: "{{ item }}" + dest: "/etc/pam-script.d/{{ item }}_ses_open" + owner: root + group: root + state: link with_items: - - login_checks.sh_ses_open - - login_checks.sh + - login_checks_regular_home.sh + when: + - inventory_hostname in groups['jumphost'] | default([]) or + inventory_hostname in groups['data_transfer'] | default([]) or + inventory_hostname in groups['cluster'] | default([]) become: true - name: 'Install login_checks_chrooted_home.sh script.' - template: + ansible.builtin.template: src: login_checks_chrooted_home.sh dest: /etc/pam-script.d/login_checks_chrooted_home.sh owner: root @@ -109,7 +85,7 @@ become: true - name: 'Enable login_checks_chrooted_home.sh script for ses_open.' - file: # noqa risky-file-permissions + ansible.builtin.file: # noqa risky-file-permissions src: login_checks_chrooted_home.sh dest: /etc/pam-script.d/login_checks_chrooted_home.sh_ses_open owner: root @@ -119,7 +95,7 @@ become: true - name: 'Install recycle-chrooted-home-for-expired-account.bash script in /root/.' - template: + ansible.builtin.template: src: recycle-chrooted-home-for-expired-account.bash dest: /root/recycle-chrooted-home-for-expired-account.bash owner: root @@ -129,7 +105,7 @@ become: true - name: 'Create cron job to run recycle-chrooted-home-for-expired-account.bash script daily.' - cron: + ansible.builtin.cron: name: 'Recycle chrooted home dirs for expired users in the {{ data_transfer_only_group }} group.' weekday: '*' hour: '05' @@ -141,14 +117,14 @@ become: true - name: 'Set tiny quota for regular users on the root partition.' - include_tasks: + ansible.builtin.include_tasks: file: tiny-user-quota-on-root-partition.yml when: - inventory_hostname in groups['jumphost'] | default([]) or inventory_hostname in groups['data_transfer'] | default([]) - name: 'Enable services.' - systemd: + ansible.builtin.systemd: name: "{{ item }}" enabled: true state: started @@ -157,7 +133,45 @@ - dbus.service - oddjobd.service notify: - - authconfig_update - restart_oddjobd become: true + +- name: 'Create custom /etc/pam.d/password-auth-local to include pam_script.so.' + ansible.builtin.copy: + src: password-auth-local + dest: /etc/pam.d/password-auth-local + owner: root + group: root + mode: '0600' + become: true + +# +# This patches old/outdated setups where pam_script.so was added to password-auth-ac. +# The authconfig utility does not support pam_script.so and when it is used in other roles +# to update password-auth-ac, custom settings like including pam_script.so will get lost. +# +- name: 'Remove pam_script.so from /etc/pam.d/password-auth-ac.' + ansible.builtin.lineinfile: + path: /etc/pam.d/password-auth-ac + state: absent + regexp: 'pam_script.so' + become: true + +- name: 'Enable custom /etc/pam.d/password-auth-local.' + ansible.builtin.file: # noqa risky-file-permissions + src: /etc/pam.d/password-auth-local + dest: /etc/pam.d/password-auth + owner: root + group: root + state: link + become: true + +- name: 'Check if we need to update authconfig.' + ansible.builtin.command: + cmd: /usr/sbin/authconfig --test + register: authconfig_test + changed_when: ('pam_oddjob_mkhomedir is disabled' in authconfig_test.stdout) + notify: + - authconfig_enable_mkhomedir + - restart_oddjobd ...