-
Notifications
You must be signed in to change notification settings - Fork 671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor display_login_attempts rule for simplicity and avoid noise #10979
Refactor display_login_attempts rule for simplicity and avoid noise #10979
Conversation
This rule demands the pam_lastlog.so module to be properly configured in order to show the previous successfull logins. This is already implicit in login program and configurable in ssh and other programs which uses PAM, but it is not ensured in other programs such as gdm* and su*. To complement program whitout a native option to show the last login, the pam_lastlog.so module is used. This is extensively documented in ComplianceAsCode#9031
One one line of pam_lastlog.so without the silent option is enough. In general the pam_lastlog.so is used to complement tools without the native capability to show the "Last login" information but is used without conditionals the information will be duplicated. This commit simplify the OVAL in alignment to this expected behavior.
In the context of pam_lastlog and postlogin or login files, the control is not so relevant and don't need to be tested since it can depend on other lines, such as conditionals. In fact, it is important to check if the "showfailed" is present without the "silent" in the same line.
This datastream diff is auto generated by the check Click here to see the full diffNew content has different text for rule 'xccdf_org.ssgproject.content_rule_display_login_attempts'.
--- xccdf_org.ssgproject.content_rule_display_login_attempts
+++ xccdf_org.ssgproject.content_rule_display_login_attempts
@@ -3,13 +3,25 @@
Ensure PAM Displays Last Logon/Access Notification
[description]:
-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 read as follows:
-session required pam_lastlog.so showfailed
-And make sure that the silent option is not set for
-pam_lastlog module.
+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]:
+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]:
+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.
[reference]:
1
@@ -147,11 +159,10 @@
SV-230381r858726_rule
[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.
+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.
[ident]:
CCE-80788-3
OVAL for rule 'xccdf_org.ssgproject.content_rule_display_login_attempts' differs.
--- oval:ssg-display_login_attempts:def:1
+++ oval:ssg-display_login_attempts:def:1
@@ -1,3 +1,2 @@
-criteria AND
+criteria None
criterion oval:ssg-test_display_login_attempts:tst:1
-criterion oval:ssg-test_display_login_attempts_silent:tst:1
OCIL for rule 'xccdf_org.ssgproject.content_rule_display_login_attempts' differs.
--- ocil:ssg-display_login_attempts_ocil:questionnaire:1
+++ ocil:ssg-display_login_attempts_ocil:questionnaire:1
@@ -2,6 +2,6 @@
$ sudo grep pam_lastlog /etc/pam.d/postlogin
-session required pam_lastlog.so showfailed
- Is it the case that "pam_lastlog" is missing from "/etc/pam.d/postlogin" file, or the silent option is present?
+session [default=1] pam_lastlog.so showfailed
+ Is it the case that "pam_lastlog.so" is not properly configured in "/etc/pam.d/postlogin" file?
bash remediation for rule 'xccdf_org.ssgproject.content_rule_display_login_attempts' differs.
--- xccdf_org.ssgproject.content_rule_display_login_attempts
+++ xccdf_org.ssgproject.content_rule_display_login_attempts
@@ -1,9 +1,20 @@
# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then
-if [ -e "/etc/pam.d/postlogin" ] ; then
- PAM_FILE_PATH="/etc/pam.d/postlogin"
- if [ -f /usr/bin/authselect ]; 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 "
@@ -33,70 +44,212 @@
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
- fi
- if ! grep -qP '^\s*session\s+'"required"'\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'"required"' \2/' "$PAM_FILE_PATH"
- else
- sed -i --follow-symlinks '1i session '"required"' pam_lastlog.so' "$PAM_FILE_PATH"
- fi
- fi
- # Check the option
- if ! grep -qP '^\s*session\s+'"required"'\s+pam_lastlog.so\s*.*\sshowfailed\b' "$PAM_FILE_PATH"; then
- sed -i -E --follow-symlinks '/\s*session\s+'"required"'\s+pam_lastlog.so.*/ s/$/ showfailed/' "$PAM_FILE_PATH"
- fi
- if [ -f /usr/bin/authselect ]; then
-
- 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
- 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.*\bpam_lastlog.so\s.*\bsilent\b' "$PAM_FILE_PATH"; then
- sed -i -E --follow-symlinks 's/(.*session.*pam_lastlog.so.*)\bsilent\b=?[[: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
+ 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
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_display_login_attempts' differs.
--- xccdf_org.ssgproject.content_rule_display_login_attempts
+++ xccdf_org.ssgproject.content_rule_display_login_attempts
@@ -16,11 +16,11 @@
- low_severity
- no_reboot_needed
-- name: Ensure PAM Displays Last Logon/Access Notification - Check if /etc/pam.d/postlogin
- file is present
+- name: Ensure PAM Displays Last Logon/Access Notification - Check if system relies
+ on authselect tool
ansible.builtin.stat:
- path: /etc/pam.d/postlogin
- register: result_pam_file_present
+ path: /usr/bin/authselect
+ register: result_authselect_present
when: '"pam" in ansible_facts.packages'
tags:
- CCE-80788-3
@@ -37,8 +37,104 @@
- low_severity
- no_reboot_needed
-- name: Ensure PAM Displays Last Logon/Access Notification - Check the proper remediation
- for the system
+- 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:
+ - CCE-80788-3
+ - CJIS-5.5.2
+ - DISA-STIG-RHEL-08-020340
+ - 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:
+ - CCE-80788-3
+ - CJIS-5.5.2
+ - DISA-STIG-RHEL-08-020340
+ - 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
@@ -189,7 +285,7 @@
module line is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*session\s+required\s+pam_lastlog.so\s*.*
+ regexp: ^\s*session\s+{{ '[default=1]' | regex_escape() }}\s+pam_lastlog.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -214,7 +310,7 @@
ansible.builtin.replace:
dest: '{{ pam_file_path }}'
regexp: ^(\s*session\s+).*(\bpam_lastlog.so.*)
- replace: \1required \2
+ replace: \1[default=1] \2
register: result_pam_module_edit
when:
- result_pam_line_other_control_present.found == 1
@@ -223,8 +319,8 @@
PAM module line is included in {{ pam_file_path }}
ansible.builtin.lineinfile:
dest: '{{ pam_file_path }}'
- insertafter: BOF
- line: session required pam_lastlog.so
+ 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
@@ -248,7 +344,7 @@
PAM module option is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*session\s+required\s+pam_lastlog.so\s*.*\sshowfailed\b
+ regexp: ^\s*session\s+{{ '[default=1]' | regex_escape() }}\s+pam_lastlog.so\s*.*\sshowfailed\b
state: absent
check_mode: true
changed_when: false
@@ -259,238 +355,32 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*session\s+required\s+pam_lastlog.so.*)
+ 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 authselect changes
- are applied
- ansible.builtin.command:
- cmd: authselect apply-changes -b
- when:
- - result_authselect_present.stat.exists
- - |-
- (result_pam_showfailed_add is defined and result_pam_showfailed_add.changed)
- or (result_pam_showfailed_edit is defined and result_pam_showfailed_edit.changed)
- when:
- - '"pam" in ansible_facts.packages'
- - result_pam_file_present.stat.exists
- tags:
- - CCE-80788-3
- - CJIS-5.5.2
- - DISA-STIG-RHEL-08-020340
- - 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 /etc/pam.d/postlogin
- file is present
- ansible.builtin.stat:
- path: /etc/pam.d/postlogin
- register: result_pam_file_present
- when: '"pam" in ansible_facts.packages'
- tags:
- - CCE-80788-3
- - CJIS-5.5.2
- - DISA-STIG-RHEL-08-020340
- - 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 the proper remediation
- for the system
- 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 - Ensure the "silent"
option from "pam_lastlog.so" is not present in {{ pam_file_path }}
ansible.builtin.replace:
dest: '{{ pam_file_path }}'
- regexp: (.*session.*pam_lastlog.so.*)\bsilent\b=?[0-9a-zA-Z]*(.*)
+ regexp: (.*session.*{{ '[default=1]' | regex_escape() }}.*pam_lastlog.so.*)\bsilent\b=?[0-9a-zA-Z]*(.*)
replace: \1\2
register: result_pam_option_removal
-
- - 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.stat.exists
- - result_pam_option_removal is changed
- when:
- - '"pam" in ansible_facts.packages'
- - result_pam_file_present.stat.exists
- tags:
- - CCE-80788-3
- - CJIS-5.5.2
- - DISA-STIG-RHEL-08-020340
- - 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
+ when: '"pam" in ansible_facts.packages'
+ tags:
+ - CCE-80788-3
+ - CJIS-5.5.2
+ - DISA-STIG-RHEL-08-020340
+ - 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
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_password_auth' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_password_auth
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_password_auth
@@ -289,8 +289,8 @@
is present in {{ pam_file_path }}'
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+{{ var_password_pam_remember_control_flag.split(",")[0]
- }}\s+pam_pwhistory.so\s*.*
+ regexp: ^\s*password\s+{{ '{{ var_password_pam_remember_control_flag.split(",")[0]
+ }}' | regex_escape() }}\s+pam_pwhistory.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -737,7 +737,7 @@
is present in {{ pam_file_path }}'
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwhistory.so\s*.*
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -794,7 +794,7 @@
option is present in {{ pam_file_path }}'
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwhistory.so\s*.*\sremember\b
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*\sremember\b
state: absent
check_mode: true
changed_when: false
@@ -805,7 +805,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so.*)
+ regexp: ^(\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so.*)
line: \1 remember={{ var_password_pam_remember }}
state: present
register: result_pam_remember_add
@@ -817,7 +817,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
+ regexp: ^(\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
line: \1\2={{ var_password_pam_remember }} \3
register: result_pam_remember_edit
when:
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_system_auth' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_system_auth
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_system_auth
@@ -289,8 +289,8 @@
present in {{ pam_file_path }}'
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+{{ var_password_pam_remember_control_flag.split(",")[0]
- }}\s+pam_pwhistory.so\s*.*
+ regexp: ^\s*password\s+{{ '{{ var_password_pam_remember_control_flag.split(",")[0]
+ }}' | regex_escape() }}\s+pam_pwhistory.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -736,7 +736,7 @@
present in {{ pam_file_path }}'
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwhistory.so\s*.*
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -793,7 +793,7 @@
is present in {{ pam_file_path }}'
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwhistory.so\s*.*\sremember\b
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*\sremember\b
state: absent
check_mode: true
changed_when: false
@@ -804,7 +804,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so.*)
+ regexp: ^(\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so.*)
line: \1 remember={{ var_password_pam_remember }}
state: present
register: result_pam_remember_add
@@ -816,7 +816,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
+ regexp: ^(\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
line: \1\2={{ var_password_pam_remember }} \3
register: result_pam_remember_edit
when:
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_remember' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_remember
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_remember
@@ -275,7 +275,7 @@
pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwhistory.so\s*.*
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -706,7 +706,7 @@
pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwhistory.so\s*.*
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -763,7 +763,7 @@
in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwhistory.so\s*.*\sremember\b
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*\sremember\b
state: absent
check_mode: true
changed_when: false
@@ -774,7 +774,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so.*)
+ regexp: ^(\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so.*)
line: \1 remember={{ var_password_pam_unix_remember }}
state: present
register: result_pam_remember_add
@@ -786,7 +786,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
+ regexp: ^(\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
line: \1\2={{ var_password_pam_unix_remember }} \3
register: result_pam_remember_edit
when:
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_pwquality_password_auth' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_pwquality_password_auth
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_pwquality_password_auth
@@ -179,7 +179,7 @@
if expected PAM module line is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwquality.so\s*.*
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwquality.so\s*.*
state: absent
check_mode: true
changed_when: false
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_pwquality_system_auth' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_pwquality_system_auth
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_pwquality_system_auth
@@ -179,7 +179,7 @@
if expected PAM module line is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+requisite\s+pam_pwquality.so\s*.*
+ regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwquality.so\s*.*
state: absent
check_mode: true
changed_when: false
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_retry' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_retry
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_retry
@@ -221,7 +221,7 @@
not present in {{ pam_file_path }}
ansible.builtin.replace:
dest: '{{ pam_file_path }}'
- regexp: (.*password.*.*.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*)
+ regexp: (.*password.*{{ '.*' | regex_escape() }}.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*)
replace: \1\2
register: result_pam_option_removal
@@ -429,7 +429,7 @@
not present in {{ pam_file_path }}
ansible.builtin.replace:
dest: '{{ pam_file_path }}'
- regexp: (.*password.*.*.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*)
+ regexp: (.*password.*{{ '.*' | regex_escape() }}.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*)
replace: \1\2
register: result_pam_option_removal
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_passwordauth' differs.
--- xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_passwordauth
+++ xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_passwordauth
@@ -191,7 +191,7 @@
PAM module line is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -249,7 +249,7 @@
PAM module option is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*\ssha512\b
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*\ssha512\b
state: absent
check_mode: true
changed_when: false
@@ -260,7 +260,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+sufficient\s+pam_unix.so.*)
+ regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so.*)
line: \1 sha512
state: present
register: result_pam_sha512_add
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_systemauth' differs.
--- xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_systemauth
+++ xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_systemauth
@@ -190,7 +190,7 @@
is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -247,7 +247,7 @@
option is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*\ssha512\b
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*\ssha512\b
state: absent
check_mode: true
changed_when: false
@@ -258,7 +258,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+sufficient\s+pam_unix.so.*)
+ regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so.*)
line: \1 sha512
state: present
register: result_pam_sha512_add
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_rounds_password_auth' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_rounds_password_auth
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_rounds_password_auth
@@ -182,7 +182,7 @@
PAM module line is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -240,7 +240,7 @@
PAM module option is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*\srounds\b
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*\srounds\b
state: absent
check_mode: true
changed_when: false
@@ -251,7 +251,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+sufficient\s+pam_unix.so.*)
+ regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so.*)
line: \1 rounds={{ var_password_pam_unix_rounds }}
state: present
register: result_pam_rounds_add
@@ -263,7 +263,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+sufficient\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]+\s*(.*)
+ regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]+\s*(.*)
line: \1\2={{ var_password_pam_unix_rounds }} \3
register: result_pam_rounds_edit
when:
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_rounds_system_auth' differs.
--- xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_rounds_system_auth
+++ xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_rounds_system_auth
@@ -182,7 +182,7 @@
PAM module line is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -240,7 +240,7 @@
PAM module option is present in {{ pam_file_path }}
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
- regexp: ^\s*password\s+sufficient\s+pam_unix.so\s*.*\srounds\b
+ regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*\srounds\b
state: absent
check_mode: true
changed_when: false
@@ -251,7 +251,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+sufficient\s+pam_unix.so.*)
+ regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so.*)
line: \1 rounds={{ var_password_pam_unix_rounds }}
state: present
register: result_pam_rounds_add
@@ -263,7 +263,7 @@
ansible.builtin.lineinfile:
path: '{{ pam_file_path }}'
backrefs: true
- regexp: ^(\s*password\s+sufficient\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]+\s*(.*)
+ regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]+\s*(.*)
line: \1\2={{ var_password_pam_unix_rounds }} \3
register: result_pam_rounds_edit
when:
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_sssd_enable_smartcards' differs.
--- xccdf_org.ssgproject.content_rule_sssd_enable_smartcards
+++ xccdf_org.ssgproject.content_rule_sssd_enable_smartcards
@@ -180,7 +180,7 @@
in /etc/pam.d/smartcard-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/smartcard-auth
- regexp: ^\s*auth\s+sufficient\s+pam_sss.so\s*.*
+ regexp: ^\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -236,7 +236,7 @@
in /etc/pam.d/smartcard-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/smartcard-auth
- regexp: ^\s*auth\s+sufficient\s+pam_sss.so\s*.*\sallow_missing_name\b
+ regexp: ^\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so\s*.*\sallow_missing_name\b
state: absent
check_mode: true
changed_when: false
@@ -247,7 +247,7 @@
ansible.builtin.lineinfile:
path: /etc/pam.d/smartcard-auth
backrefs: true
- regexp: ^(\s*auth\s+sufficient\s+pam_sss.so.*)
+ regexp: ^(\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so.*)
line: \1 allow_missing_name
state: present
register: result_pam_allow_missing_name_add
@@ -258,7 +258,8 @@
in /etc/pam.d/system-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
- regexp: ^\s*auth\s+\[success=done authinfo_unavail=ignore ignore=ignore default=die\]\s+pam_sss.so\s*.*
+ regexp: ^\s*auth\s+{{ '\[success=done authinfo_unavail=ignore ignore=ignore
+ default=die\]' | regex_escape() }}\s+pam_sss.so\s*.*
state: absent
check_mode: true
changed_when: false
@@ -315,7 +316,8 @@
in /etc/pam.d/system-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
- regexp: ^\s*auth\s+\[success=done authinfo_unavail=ignore ignore=ignore default=die\]\s+pam_sss.so\s*.*\stry_cert_auth\b
+ regexp: ^\s*auth\s+{{ '\[success=done authinfo_unavail=ignore ignore=ignore
+ default=die\]' | regex_escape() }}\s+pam_sss.so\s*.*\stry_cert_auth\b
state: absent
check_mode: true
changed_when: false
@@ -326,7 +328,8 @@
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
backrefs: true
- regexp: ^(\s*auth\s+\[success=done authinfo_unavail=ignore ignore=ignore default=die\]\s+pam_sss.so.*)
+ regexp: ^(\s*auth\s+{{ '\[success=done authinfo_unavail=ignore ignore=ignore
+ default=die\]' | regex_escape() }}\s+pam_sss.so.*)
line: \1 try_cert_auth
state: present
register: result_pam_try_cert_auth_add |
@dodys , @freddieRv and @teacup-on-rockingchair , it took me some time to investigate the #9031 and come with this PR. Initially it was affecting the user experience but after some investigation much more was involved. I think the changes proposed in this PR also make sense for other distros and your feedback on this would be appreciated. Much more context and detailed information is found in #9031 Thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beside the ansible issue saw no other definately looks better 👍
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/ansible/shared.yml
Outdated
Show resolved
Hide resolved
/packit retest-failed |
Instead of using BOF (beginning of file), it was included a Jinja2 variable to make the regex more flexible among different distros. In case the regex does not match, the line is inserted at the end of the file.
Instead of using a literal control, it was included a Jinja2 variable to make the control more flexible among different distros.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice stuff 🙇
PAM files can use advanced syntax for controls, such as [default=1]. In Ansible macros, the control value is used both to assemble the desired line and to assemble the regexp. For regexp, the square brackets must be escaped.
In systems using authselect, there is a feature to properly configure the pam_lastlog.so module in order to be silent or to show the failed logins. It was created a macro to use this authselect feature whenever available. The Bash remediation was also updated to use this new macro.
The bash remediation is now capable to use the authselect feature to configure pam_lastlog.so so the test scenario scripts were aligned to this new feature. Some tests were simplified and unnecessary tests were removed.
It is aligned to the equivalent Bash macro. Remediation was also updated to use this new Ansible macro.
Systems which were already remediated with this rule before this refactoring might demand manual actions from the administrator in order to properly restore the original settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Automatus tests locally in RHEL7-RHEL9 VMs.
/packit retest-failed |
@dodys and @freddieRv could you also take a look on this PR, please? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some small details regarding ubuntu specifically
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/rule.yml
Outdated
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/rule.yml
Outdated
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/tests/correct_value.pass.sh
Outdated
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/tests/default_config.pass.sh
Outdated
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/ansible/shared.yml
Outdated
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/tests/wrong_value.fail.sh
Outdated
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/tests/wrong_value.fail.sh
Show resolved
Hide resolved
...system/accounts/accounts-pam/display_login_attempts/tests/no_space_before_showfailed.fail.sh
Outdated
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/tests/commented_line.fail.sh
Show resolved
Hide resolved
linux_os/guide/system/accounts/accounts-pam/display_login_attempts/oval/shared.xml
Show resolved
Hide resolved
Although the control is not critical for the OVAL check, it is relevant for remediation so distros can use their own preferences.
Aligned the platforms among all test scenario scripts, ensuring the tests become applicable to main products. Also ensured two pass test scripts with different control in order to confirm the control is not considered during the OVAL assessment.
Code Climate has analyzed commit 21ae1e1 and detected 0 issues on this pull request. The test coverage on the diff in this pull request is 100.0% (50% is the threshold). This pull request will bring the total coverage in the repository to 53.3% (0.0% change). View more on Code Climate. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for addressing the comments!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes LGTM. Thanks for addressing my comment @marcusburghardt
/packit retest-failed |
Thanks all for your reviews! |
Description:
The
pam_lastlog.so
module is used in the/etc/pam.d/postlogin
file (or login file depending on the distro) to displayLast login
information for certain programs. Although this module is only explicitly mentioned in thepostlogin
file, it is indirectly used by various other PAM configuration files, such as those forlogin
,ssh
,passwd
, and others. The reason for this is to ensure that theLast login
information is shown for programs likegdm
andsu
, while avoiding redundancy for programs that already display this information without needingpam_lastlog.so
. Despite the usage ofsilent
option in one line, the default configuration of/etc/pam.d/postlogin
ensures consistent display ofLast login
information for specific programs.In short we only need to check if at least one line contains
am_lastlog.so
,showfailed
and notsilent
.Rationale:
Review Hints:
The commits were organized in a sequence to facilitate the review.
The most import is actually to understand the reasons behind the changes, which are better contextualized in #9031
Finally, the automatus should work fine with to validate the technical aspects of the check and remediation