To configure the system to notify users of last logon/access using pam_lastlog,
add or correct the pam_lastlog settings in /etc/pam.d/postlogin
to include showfailed option, such as:
session [default=1] pam_lastlog.so showfailed
And make sure that the silent option is not set for this specific line.
warning alert:
Warning
If the system relies on authselect tool to manage PAM settings, the remediation
will also use authselect tool. However, if any manual modification was made in
PAM files, the authselect integrity check will fail and the remediation will be
aborted in order to preserve intentional changes. In this case, an informative message will
be shown in the remediation report.
warning alert:
Warning
authselect contains an authselect feature to easily and properly enable Last Logon
notifications with pam_lastlog.so module. If a custom profile was created and used
in the system before this authselect feature was available, the new feature can't be used
with this custom profile and the remediation will fail. In this case, the custom profile
should be recreated or manually updated.
Rationale
Users need to be aware of activity that occurs regarding their account. Providing users with
information regarding the number of unsuccessful attempts that were made to login to their
account allows the user to determine if any unauthorized activity has occurred and gives them
an opportunity to notify administrators.
ISA-62443-2-1-2009, Security for Industrial Automation and Control Systems Part 2-1: Establishing an Industrial Automation and Control Systems Security Program
- name: Gather the package facts
package_facts:
manager: auto
tags:
- CJIS-5.5.2
- DISA-STIG-RHEL-09-412075
- NIST-800-53-AC-9
- NIST-800-53-AC-9(1)
- PCI-DSS-Req-10.2.4
- PCI-DSSv4-10.2.1.4
- configure_strategy
- display_login_attempts
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- name: Ensure PAM Displays Last Logon/Access Notification - Check if system relies
on authselect tool
ansible.builtin.stat:
path: /usr/bin/authselect
register: result_authselect_present
when: '"pam" in ansible_facts.packages'
tags:
- CJIS-5.5.2
- DISA-STIG-RHEL-09-412075
- NIST-800-53-AC-9
- NIST-800-53-AC-9(1)
- PCI-DSS-Req-10.2.4
- PCI-DSSv4-10.2.1.4
- configure_strategy
- display_login_attempts
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- name: Ensure PAM Displays Last Logon/Access Notification - Collect the Available
authselect Features
ansible.builtin.command:
cmd: authselect list-features minimal
register: result_authselect_available_features
changed_when: false
when:
- '"pam" in ansible_facts.packages'
- result_authselect_present.stat.exists
tags:
- CJIS-5.5.2
- DISA-STIG-RHEL-09-412075
- NIST-800-53-AC-9
- NIST-800-53-AC-9(1)
- PCI-DSS-Req-10.2.4
- PCI-DSSv4-10.2.1.4
- configure_strategy
- display_login_attempts
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- name: Ensure PAM Displays Last Logon/Access Notification - Configure pam_lastlog.so
Using authselect Feature
block:
- name: Ensure PAM Displays Last Logon/Access Notification - Check integrity of
authselect current profile
ansible.builtin.command:
cmd: authselect check
register: result_authselect_check_cmd
changed_when: false
failed_when: false
- name: Ensure PAM Displays Last Logon/Access Notification - Informative message
based on the authselect integrity check result
ansible.builtin.assert:
that:
- result_authselect_check_cmd.rc == 0
fail_msg:
- authselect integrity check failed. Remediation aborted!
- This remediation could not be applied because an authselect profile was not
selected or the selected profile is not intact.
- It is not recommended to manually edit the PAM files when authselect tool
is available.
- In cases where the default authselect profile does not cover a specific demand,
a custom authselect profile is recommended.
success_msg:
- authselect integrity check passed
- name: Ensure PAM Displays Last Logon/Access Notification - Get authselect Features
Currently Enabled
ansible.builtin.shell:
cmd: authselect current | tail -n+3 | awk '{ print $2 }'
register: result_authselect_features
changed_when: false
when:
- result_authselect_check_cmd is success
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure "with-silent-lastlog"
Feature is Disabled Using authselect Tool
ansible.builtin.command:
cmd: authselect disable-feature with-silent-lastlog
register: result_authselect_disable_feature_cmd
when:
- result_authselect_check_cmd is success
- result_authselect_features.stdout is search("with-silent-lastlog")
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure authselect changes
are applied
ansible.builtin.command:
cmd: authselect apply-changes -b
when:
- result_authselect_disable_feature_cmd is not skipped
- result_authselect_disable_feature_cmd is success
when:
- '"pam" in ansible_facts.packages'
- result_authselect_present.stat.exists
- result_authselect_available_features.stdout is search("with-silent-lastlog")
tags:
- CJIS-5.5.2
- DISA-STIG-RHEL-09-412075
- NIST-800-53-AC-9
- NIST-800-53-AC-9(1)
- PCI-DSS-Req-10.2.4
- PCI-DSSv4-10.2.1.4
- configure_strategy
- display_login_attempts
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- name: Ensure PAM Displays Last Logon/Access Notification - Configure pam_lastlog.so
in appropriate PAM files
block:
- name: Ensure PAM Displays Last Logon/Access Notification - Define the PAM file
to be edited as a local fact
ansible.builtin.set_fact:
pam_file_path: /etc/pam.d/postlogin
- name: Ensure PAM Displays Last Logon/Access Notification - Check if system relies
on authselect tool
ansible.builtin.stat:
path: /usr/bin/authselect
register: result_authselect_present
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure authselect custom
profile is used if authselect is present
block:
- name: Ensure PAM Displays Last Logon/Access Notification - Check integrity of
authselect current profile
ansible.builtin.command:
cmd: authselect check
register: result_authselect_check_cmd
changed_when: false
failed_when: false
- name: Ensure PAM Displays Last Logon/Access Notification - Informative message
based on the authselect integrity check result
ansible.builtin.assert:
that:
- result_authselect_check_cmd.rc == 0
fail_msg:
- authselect integrity check failed. Remediation aborted!
- This remediation could not be applied because an authselect profile was
not selected or the selected profile is not intact.
- It is not recommended to manually edit the PAM files when authselect tool
is available.
- In cases where the default authselect profile does not cover a specific
demand, a custom authselect profile is recommended.
success_msg:
- authselect integrity check passed
- name: Ensure PAM Displays Last Logon/Access Notification - Get authselect current
profile
ansible.builtin.shell:
cmd: authselect current -r | awk '{ print $1 }'
register: result_authselect_profile
changed_when: false
when:
- result_authselect_check_cmd is success
- name: Ensure PAM Displays Last Logon/Access Notification - Define the current
authselect profile as a local fact
ansible.builtin.set_fact:
authselect_current_profile: '{{ result_authselect_profile.stdout }}'
authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
when:
- result_authselect_profile is not skipped
- result_authselect_profile.stdout is match("custom/")
- name: Ensure PAM Displays Last Logon/Access Notification - Define the new authselect
custom profile as a local fact
ansible.builtin.set_fact:
authselect_current_profile: '{{ result_authselect_profile.stdout }}'
authselect_custom_profile: custom/hardening
when:
- result_authselect_profile is not skipped
- result_authselect_profile.stdout is not match("custom/")
- name: Ensure PAM Displays Last Logon/Access Notification - Get authselect current
features to also enable them in the custom profile
ansible.builtin.shell:
cmd: authselect current | tail -n+3 | awk '{ print $2 }'
register: result_authselect_features
changed_when: false
when:
- result_authselect_profile is not skipped
- authselect_current_profile is not match("custom/")
- name: Ensure PAM Displays Last Logon/Access Notification - Check if any custom
profile with the same name was already created
ansible.builtin.stat:
path: /etc/authselect/{{ authselect_custom_profile }}
register: result_authselect_custom_profile_present
changed_when: false
when:
- authselect_current_profile is not match("custom/")
- name: Ensure PAM Displays Last Logon/Access Notification - Create an authselect
custom profile based on the current profile
ansible.builtin.command:
cmd: authselect create-profile hardening -b {{ authselect_current_profile
}}
when:
- result_authselect_check_cmd is success
- authselect_current_profile is not match("custom/")
- not result_authselect_custom_profile_present.stat.exists
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure authselect
changes are applied
ansible.builtin.command:
cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
when:
- result_authselect_check_cmd is success
- result_authselect_profile is not skipped
- authselect_current_profile is not match("custom/")
- authselect_custom_profile is not match(authselect_current_profile)
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure the authselect
custom profile is selected
ansible.builtin.command:
cmd: authselect select {{ authselect_custom_profile }}
register: result_pam_authselect_select_profile
when:
- result_authselect_check_cmd is success
- result_authselect_profile is not skipped
- authselect_current_profile is not match("custom/")
- authselect_custom_profile is not match(authselect_current_profile)
- name: Ensure PAM Displays Last Logon/Access Notification - Restore the authselect
features in the custom profile
ansible.builtin.command:
cmd: authselect enable-feature {{ item }}
loop: '{{ result_authselect_features.stdout_lines }}'
register: result_pam_authselect_restore_features
when:
- result_authselect_profile is not skipped
- result_authselect_features is not skipped
- result_pam_authselect_select_profile is not skipped
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure authselect
changes are applied
ansible.builtin.command:
cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
when:
- result_authselect_check_cmd is success
- result_authselect_profile is not skipped
- result_pam_authselect_restore_features is not skipped
- name: Ensure PAM Displays Last Logon/Access Notification - Change the PAM file
to be edited according to the custom authselect profile
ansible.builtin.set_fact:
pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
| basename }}
when:
- result_authselect_present.stat.exists
- name: Ensure PAM Displays Last Logon/Access Notification - Check if expected PAM
module line is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
regexp: ^\s*session\s+{{ '[default=1]' | regex_escape() }}\s+pam_lastlog.so\s*.*
state: absent
check_mode: true
changed_when: false
register: result_pam_line_present
- name: Ensure PAM Displays Last Logon/Access Notification - Include or update the
PAM module line in {{ pam_file_path }}
block:
- name: Ensure PAM Displays Last Logon/Access Notification - Check if required
PAM module line is present in {{ pam_file_path }} with different control
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
regexp: ^\s*session\s+.*\s+pam_lastlog.so\s*
state: absent
check_mode: true
changed_when: false
register: result_pam_line_other_control_present
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure the correct
control for the required PAM module line in {{ pam_file_path }}
ansible.builtin.replace:
dest: '{{ pam_file_path }}'
regexp: ^(\s*session\s+).*(\bpam_lastlog.so.*)
replace: \1[default=1] \2
register: result_pam_module_edit
when:
- result_pam_line_other_control_present.found == 1
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure the required
PAM module line is included in {{ pam_file_path }}
ansible.builtin.lineinfile:
dest: '{{ pam_file_path }}'
insertafter: ^\s*session\s+.*pam_succeed_if\.so.*
line: session [default=1] pam_lastlog.so
register: result_pam_module_add
when:
- result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
> 1
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure authselect
changes are applied
ansible.builtin.command:
cmd: authselect apply-changes -b
when:
- result_authselect_present is defined
- result_authselect_present.stat.exists
- |-
(result_pam_module_add is defined and result_pam_module_add.changed)
or (result_pam_module_edit is defined and result_pam_module_edit.changed)
when:
- result_pam_line_present.found is defined
- result_pam_line_present.found == 0
- name: Ensure PAM Displays Last Logon/Access Notification - Check if the required
PAM module option is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
regexp: ^\s*session\s+{{ '[default=1]' | regex_escape() }}\s+pam_lastlog.so\s*.*\sshowfailed\b
state: absent
check_mode: true
changed_when: false
register: result_pam_module_showfailed_option_present
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure the "showfailed"
PAM option for "pam_lastlog.so" is included in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
regexp: ^(\s*session\s+{{ '[default=1]' | regex_escape() }}\s+pam_lastlog.so.*)
line: \1 showfailed
state: present
register: result_pam_showfailed_add
when:
- result_pam_module_showfailed_option_present.found == 0
- name: Ensure PAM Displays Last Logon/Access Notification - Ensure the "silent"
option from "pam_lastlog.so" is not present in {{ pam_file_path }}
ansible.builtin.replace:
dest: '{{ pam_file_path }}'
regexp: (.*session.*{{ '[default=1]' | regex_escape() }}.*pam_lastlog.so.*)\bsilent\b=?[0-9a-zA-Z]*(.*)
replace: \1\2
register: result_pam_option_removal
when: '"pam" in ansible_facts.packages'
tags:
- CJIS-5.5.2
- DISA-STIG-RHEL-09-412075
- NIST-800-53-AC-9
- NIST-800-53-AC-9(1)
- PCI-DSS-Req-10.2.4
- PCI-DSSv4-10.2.1.4
- configure_strategy
- display_login_attempts
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
Remediation - Shell Script
# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then
if [ -f /usr/bin/authselect ]; then
if authselect list-features minimal | grep -q with-silent-lastlog; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect disable-feature with-silent-lastlog
authselect apply-changes -b
else
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "/etc/pam.d/postlogin")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
if [ -e "$PAM_FILE_PATH" ] ; then
PAM_FILE_PATH="$PAM_FILE_PATH"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "$PAM_FILE_PATH")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if ! grep -qP '^\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so\s*.*' "$PAM_FILE_PATH"; then
# Line matching group + control + module was not found. Check group + module.
if [ "$(grep -cP '^\s*session\s+.*\s+pam_lastlog.so\s*' "$PAM_FILE_PATH")" -eq 1 ]; then
# The control is updated only if one single line matches.
sed -i -E --follow-symlinks 's/^(\s*session\s+).*(\bpam_lastlog.so.*)/\1'"\[default=1\]"' \2/' "$PAM_FILE_PATH"
else
LAST_MATCH_LINE=$(grep -nP "^\s*session\s+.*pam_succeed_if\.so.*" "$PAM_FILE_PATH" | tail -n 1 | cut -d: -f 1)
if [ ! -z $LAST_MATCH_LINE ]; then
sed -i --follow-symlinks $LAST_MATCH_LINE' a session '"\[default=1\]"' pam_lastlog.so' "$PAM_FILE_PATH"
else
echo 'session '"\[default=1\]"' pam_lastlog.so' >> "$PAM_FILE_PATH"
fi
fi
fi
# Check the option
if ! grep -qP '^\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so\s*.*\sshowfailed\b' "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks '/\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so.*/ s/$/ showfailed/' "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "$PAM_FILE_PATH was not found" >&2
fi
if [ -e "$PAM_FILE_PATH" ] ; then
PAM_FILE_PATH="$PAM_FILE_PATH"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "$PAM_FILE_PATH")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if grep -qP '^\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so\s.*\bsilent\b' "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks 's/(.*session.*'"\[default=1\]"'.*pam_lastlog.so.*)\ssilent=?[[:alnum:]]*(.*)/\1\2/g' "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "$PAM_FILE_PATH was not found" >&2
fi
fi
else
if [ -e "/etc/pam.d/postlogin" ] ; then
PAM_FILE_PATH="/etc/pam.d/postlogin"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "/etc/pam.d/postlogin")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if ! grep -qP '^\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so\s*.*' "$PAM_FILE_PATH"; then
# Line matching group + control + module was not found. Check group + module.
if [ "$(grep -cP '^\s*session\s+.*\s+pam_lastlog.so\s*' "$PAM_FILE_PATH")" -eq 1 ]; then
# The control is updated only if one single line matches.
sed -i -E --follow-symlinks 's/^(\s*session\s+).*(\bpam_lastlog.so.*)/\1'"\[default=1\]"' \2/' "$PAM_FILE_PATH"
else
LAST_MATCH_LINE=$(grep -nP "^\s*session\s+.*pam_succeed_if\.so.*" "$PAM_FILE_PATH" | tail -n 1 | cut -d: -f 1)
if [ ! -z $LAST_MATCH_LINE ]; then
sed -i --follow-symlinks $LAST_MATCH_LINE' a session '"\[default=1\]"' pam_lastlog.so' "$PAM_FILE_PATH"
else
echo 'session '"\[default=1\]"' pam_lastlog.so' >> "$PAM_FILE_PATH"
fi
fi
fi
# Check the option
if ! grep -qP '^\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so\s*.*\sshowfailed\b' "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks '/\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so.*/ s/$/ showfailed/' "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "/etc/pam.d/postlogin was not found" >&2
fi
if [ -e "/etc/pam.d/postlogin" ] ; then
PAM_FILE_PATH="/etc/pam.d/postlogin"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "/etc/pam.d/postlogin")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if grep -qP '^\s*session\s+'"\[default=1\]"'\s+pam_lastlog.so\s.*\bsilent\b' "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks 's/(.*session.*'"\[default=1\]"'.*pam_lastlog.so.*)\ssilent=?[[:alnum:]]*(.*)/\1\2/g' "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "/etc/pam.d/postlogin was not found" >&2
fi
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi