--- ############################################################################### # # Ansible Playbook for DISA STIG for Red Hat Enterprise Linux 8 # # Profile Description: # This profile contains configuration checks that align to the # DISA STIG for Red Hat Enterprise Linux 8 V1R12. # In addition to being applicable to Red Hat Enterprise Linux 8, DISA recognizes this # configuration baseline as applicable to the operating system tier of # Red Hat technologies that are based on Red Hat Enterprise Linux 8, such as: # - Red Hat Enterprise Linux Server # - Red Hat Enterprise Linux Workstation and Desktop # - Red Hat Enterprise Linux for HPC # - Red Hat Storage # - Red Hat Containers with a Red Hat Enterprise Linux 8 image # # Profile ID: xccdf_org.ssgproject.content_profile_stig # Benchmark ID: xccdf_org.ssgproject.content_benchmark_RHEL-8 # Benchmark Version: 0.1.72 # XCCDF Version: 1.2 # # This file can be generated by OpenSCAP using: # $ oscap xccdf generate fix --profile xccdf_org.ssgproject.content_profile_stig --fix-type ansible ssg-rhel8-ds.xml # # This Ansible Playbook is generated from an XCCDF profile without preliminary evaluation. # It attempts to fix every selected rule, even if the system is already compliant. # # How to apply this Ansible Playbook: # $ ansible-playbook -i "localhost," -c local playbook.yml # $ ansible-playbook -i "192.168.1.155," playbook.yml # $ ansible-playbook -i inventory.ini playbook.yml # ############################################################################### - name: Ansible Playbook for xccdf_org.ssgproject.content_profile_stig hosts: all vars: var_aide_scan_notification_email: !!str root@localhost var_system_crypto_policy: !!str FIPS sshd_approved_ciphers: !!str aes256-ctr,aes192-ctr,aes128-ctr,aes256-gcm@openssh.com,aes128-gcm@openssh.com sshd_approved_macs: !!str hmac-sha2-512,hmac-sha2-256,hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com inactivity_timeout_value: !!str 900 var_screensaver_lock_delay: !!str 5 var_sudo_timestamp_timeout: !!str 0 var_authselect_profile: !!str sssd login_banner_text: !!str ^(You[\s\n]+are[\s\n]+accessing[\s\n]+a[\s\n]+U\.S\.[\s\n]+Government[\s\n]+\(USG\)[\s\n]+Information[\s\n]+System[\s\n]+\(IS\)[\s\n]+that[\s\n]+is[\s\n]+provided[\s\n]+for[\s\n]+USG\-authorized[\s\n]+use[\s\n]+only\.[\s\n]+By[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+\(which[\s\n]+includes[\s\n]+any[\s\n]+device[\s\n]+attached[\s\n]+to[\s\n]+this[\s\n]+IS\),[\s\n]+you[\s\n]+consent[\s\n]+to[\s\n]+the[\s\n]+following[\s\n]+conditions\:(?:[\n]+|(?:\\n)+)\-The[\s\n]+USG[\s\n]+routinely[\s\n]+intercepts[\s\n]+and[\s\n]+monitors[\s\n]+communications[\s\n]+on[\s\n]+this[\s\n]+IS[\s\n]+for[\s\n]+purposes[\s\n]+including,[\s\n]+but[\s\n]+not[\s\n]+limited[\s\n]+to,[\s\n]+penetration[\s\n]+testing,[\s\n]+COMSEC[\s\n]+monitoring,[\s\n]+network[\s\n]+operations[\s\n]+and[\s\n]+defense,[\s\n]+personnel[\s\n]+misconduct[\s\n]+\(PM\),[\s\n]+law[\s\n]+enforcement[\s\n]+\(LE\),[\s\n]+and[\s\n]+counterintelligence[\s\n]+\(CI\)[\s\n]+investigations\.(?:[\n]+|(?:\\n)+)\-At[\s\n]+any[\s\n]+time,[\s\n]+the[\s\n]+USG[\s\n]+may[\s\n]+inspect[\s\n]+and[\s\n]+seize[\s\n]+data[\s\n]+stored[\s\n]+on[\s\n]+this[\s\n]+IS\.(?:[\n]+|(?:\\n)+)\-Communications[\s\n]+using,[\s\n]+or[\s\n]+data[\s\n]+stored[\s\n]+on,[\s\n]+this[\s\n]+IS[\s\n]+are[\s\n]+not[\s\n]+private,[\s\n]+are[\s\n]+subject[\s\n]+to[\s\n]+routine[\s\n]+monitoring,[\s\n]+interception,[\s\n]+and[\s\n]+search,[\s\n]+and[\s\n]+may[\s\n]+be[\s\n]+disclosed[\s\n]+or[\s\n]+used[\s\n]+for[\s\n]+any[\s\n]+USG\-authorized[\s\n]+purpose\.(?:[\n]+|(?:\\n)+)\-This[\s\n]+IS[\s\n]+includes[\s\n]+security[\s\n]+measures[\s\n]+\(e\.g\.,[\s\n]+authentication[\s\n]+and[\s\n]+access[\s\n]+controls\)[\s\n]+to[\s\n]+protect[\s\n]+USG[\s\n]+interests\-\-not[\s\n]+for[\s\n]+your[\s\n]+personal[\s\n]+benefit[\s\n]+or[\s\n]+privacy\.(?:[\n]+|(?:\\n)+)\-Notwithstanding[\s\n]+the[\s\n]+above,[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+does[\s\n]+not[\s\n]+constitute[\s\n]+consent[\s\n]+to[\s\n]+PM,[\s\n]+LE[\s\n]+or[\s\n]+CI[\s\n]+investigative[\s\n]+searching[\s\n]+or[\s\n]+monitoring[\s\n]+of[\s\n]+the[\s\n]+content[\s\n]+of[\s\n]+privileged[\s\n]+communications,[\s\n]+or[\s\n]+work[\s\n]+product,[\s\n]+related[\s\n]+to[\s\n]+personal[\s\n]+representation[\s\n]+or[\s\n]+services[\s\n]+by[\s\n]+attorneys,[\s\n]+psychotherapists,[\s\n]+or[\s\n]+clergy,[\s\n]+and[\s\n]+their[\s\n]+assistants\.[\s\n]+Such[\s\n]+communications[\s\n]+and[\s\n]+work[\s\n]+product[\s\n]+are[\s\n]+private[\s\n]+and[\s\n]+confidential\.[\s\n]+See[\s\n]+User[\s\n]+Agreement[\s\n]+for[\s\n]+details\.|I've[\s\n]+read[\s\n]+\&[\s\n]+consent[\s\n]+to[\s\n]+terms[\s\n]+in[\s\n]+IS[\s\n]+user[\s\n]+agreem't\.)$ var_password_pam_remember: !!str 5 var_password_pam_remember_control_flag: !!str requisite,required var_accounts_passwords_pam_faillock_deny: !!str 3 var_accounts_passwords_pam_faillock_dir: !!str /var/log/faillock var_accounts_passwords_pam_faillock_fail_interval: !!str 900 var_accounts_passwords_pam_faillock_unlock_time: !!str 0 var_password_pam_dcredit: !!str -1 var_password_pam_dictcheck: !!str 1 var_password_pam_difok: !!str 8 var_password_pam_lcredit: !!str -1 var_password_pam_maxclassrepeat: !!str 4 var_password_pam_maxrepeat: !!str 3 var_password_pam_minclass: !!str 4 var_password_pam_minlen: !!str 15 var_password_pam_ocredit: !!str -1 var_password_pam_retry: !!str 3 var_password_pam_ucredit: !!str -1 var_password_hashing_algorithm: !!str SHA512 var_logind_session_timeout: !!str 300 var_account_disable_post_pw_expiration: !!str 35 var_accounts_maximum_age_login_defs: !!str 60 var_accounts_minimum_age_login_defs: !!str 1 var_accounts_password_minlen_login_defs: !!str 15 var_accounts_fail_delay: !!str 4 var_accounts_max_concurrent_login_sessions: !!str 10 var_user_initialization_files_regex: !!str ^(\.bashrc|\.zshrc|\.cshrc|\.profile|\.bash_login|\.bash_profile)$ var_accounts_user_umask: !!str 077 var_auditd_disk_error_action: !!str syslog|single|halt var_auditd_disk_full_action: !!str syslog|single|halt var_auditd_action_mail_acct: !!str root var_auditd_space_left_action: !!str email var_auditd_space_left_percentage: !!str 25 var_auditd_name_format: !!str hostname|fqd|numeric rsyslog_remote_loghost_address: !!str logcollector sysctl_net_ipv6_conf_all_accept_ra_value: !!str 0 sysctl_net_ipv6_conf_all_accept_redirects_value: !!str 0 sysctl_net_ipv6_conf_all_accept_source_route_value: !!str 0 sysctl_net_ipv6_conf_all_forwarding_value: !!str 0 sysctl_net_ipv6_conf_default_accept_ra_value: !!str 0 sysctl_net_ipv6_conf_default_accept_redirects_value: !!str 0 sysctl_net_ipv6_conf_default_accept_source_route_value: !!str 0 sysctl_net_ipv4_conf_all_accept_redirects_value: !!str 0 sysctl_net_ipv4_conf_all_accept_source_route_value: !!str 0 sysctl_net_ipv4_conf_all_forwarding_value: !!str 0 sysctl_net_ipv4_conf_all_rp_filter_value: !!str 1 sysctl_net_ipv4_conf_default_accept_redirects_value: !!str 0 sysctl_net_ipv4_conf_default_accept_source_route_value: !!str 0 sysctl_net_ipv4_icmp_echo_ignore_broadcasts_value: !!str 1 var_removable_partition: !!str /dev/cdrom sysctl_kernel_kptr_restrict_value: !!str 1 var_slub_debug_options: !!str P var_selinux_policy_name: !!str targeted var_selinux_state: !!str enforcing var_time_service_set_maxpoll: !!str 16 var_tftpd_secure_directory: !!str /var/lib/tftpboot var_sshd_set_keepalive: !!str 1 sshd_idle_timeout_value: !!str 600 var_rekey_limit_size: !!str 1G var_rekey_limit_time: !!str 1h var_sssd_certificate_verification_digest_function: !!str sha1 tasks: - name: Ensure aide is installed package: name: aide state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80844-4 - CJIS-5.10.1.3 - DISA-STIG-RHEL-08-010359 - NIST-800-53-CM-6(a) - PCI-DSS-Req-11.5 - PCI-DSSv4-11.5.2 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_aide_installed - name: Build and Test AIDE Database - Ensure AIDE Is Installed ansible.builtin.package: name: '{{ item }}' state: present with_items: - aide when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80675-2 - CJIS-5.10.1.3 - DISA-STIG-RHEL-08-010359 - NIST-800-53-CM-6(a) - PCI-DSS-Req-11.5 - PCI-DSSv4-11.5.2 - aide_build_database - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Build and Test AIDE Database - Build and Test AIDE Database ansible.builtin.command: /usr/sbin/aide --init changed_when: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80675-2 - CJIS-5.10.1.3 - DISA-STIG-RHEL-08-010359 - NIST-800-53-CM-6(a) - PCI-DSS-Req-11.5 - PCI-DSSv4-11.5.2 - aide_build_database - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Build and Test AIDE Database - Check Whether the Stock AIDE Database Exists ansible.builtin.stat: path: /var/lib/aide/aide.db.new.gz register: aide_database_stat when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80675-2 - CJIS-5.10.1.3 - DISA-STIG-RHEL-08-010359 - NIST-800-53-CM-6(a) - PCI-DSS-Req-11.5 - PCI-DSSv4-11.5.2 - aide_build_database - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Build and Test AIDE Database - Stage AIDE Database ansible.builtin.copy: src: /var/lib/aide/aide.db.new.gz dest: /var/lib/aide/aide.db.gz backup: true remote_src: true when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - (aide_database_stat.stat.exists is defined and aide_database_stat.stat.exists) tags: - CCE-80675-2 - CJIS-5.10.1.3 - DISA-STIG-RHEL-08-010359 - NIST-800-53-CM-6(a) - PCI-DSS-Req-11.5 - PCI-DSSv4-11.5.2 - aide_build_database - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure aide is installed package: name: '{{ item }}' state: present with_items: - aide when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85964-5 - DISA-STIG-RHEL-08-030650 - NIST-800-53-AU-9(3) - NIST-800-53-AU-9(3).1 - aide_check_audit_tools - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set audit_tools fact set_fact: audit_tools: - /usr/sbin/auditctl - /usr/sbin/auditd - /usr/sbin/augenrules - /usr/sbin/aureport - /usr/sbin/ausearch - /usr/sbin/autrace - /usr/sbin/rsyslogd when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85964-5 - DISA-STIG-RHEL-08-030650 - NIST-800-53-AU-9(3) - NIST-800-53-AU-9(3).1 - aide_check_audit_tools - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure existing AIDE configuration for audit tools are correct lineinfile: path: /etc/aide.conf regexp: ^{{ item }}\s line: '{{ item }} p+i+n+u+g+s+b+acl+xattrs+sha512' with_items: '{{ audit_tools }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85964-5 - DISA-STIG-RHEL-08-030650 - NIST-800-53-AU-9(3) - NIST-800-53-AU-9(3).1 - aide_check_audit_tools - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure AIDE to properly protect audit tools lineinfile: path: /etc/aide.conf line: '{{ item }} p+i+n+u+g+s+b+acl+xattrs+sha512' with_items: '{{ audit_tools }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85964-5 - DISA-STIG-RHEL-08-030650 - NIST-800-53-AU-9(3) - NIST-800-53-AU-9(3).1 - aide_check_audit_tools - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure AIDE is installed package: name: '{{ item }}' state: present with_items: - aide when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82891-3 - DISA-STIG-RHEL-08-010360 - NIST-800-53-CM-3(5) - NIST-800-53-CM-6(a) - aide_scan_notification - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Notification of Post-AIDE Scan Details cron: name: run AIDE check minute: 5 hour: 4 weekday: 0 user: root job: /usr/sbin/aide --check | /bin/mail -s "$(hostname) - AIDE Integrity Check" {{ var_aide_scan_notification_email }} when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82891-3 - DISA-STIG-RHEL-08-010360 - NIST-800-53-CM-3(5) - NIST-800-53-CM-6(a) - aide_scan_notification - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather list of packages package_facts: manager: auto when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '' tags: - CCE-84220-3 - DISA-STIG-RHEL-08-040310 - NIST-800-53-CM-6(a) - NIST-800-53-SI-7 - NIST-800-53-SI-7(1) - aide_verify_acls - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Get rules groups shell: | set -o pipefail LC_ALL=C grep "^[A-Z][A-Za-z_]*" /etc/aide.conf | grep -v "^ALLXTRAHASHES" | cut -f1 -d '=' | tr -d ' ' | sort -u || true when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '''aide'' in ansible_facts.packages' register: find_rules_groups_results tags: - CCE-84220-3 - DISA-STIG-RHEL-08-040310 - NIST-800-53-CM-6(a) - NIST-800-53-SI-7 - NIST-800-53-SI-7(1) - aide_verify_acls - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Ensure the acl rule is present when aide is installed. replace: path: /etc/aide.conf regexp: (^\s*{{ item }}\s*=\s*)(?!.*acl)([^\s]*) replace: \g<1>\g<2>+acl when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '''aide'' in ansible_facts.packages' with_items: '{{ find_rules_groups_results.stdout_lines | map(''trim'') | list }}' tags: - CCE-84220-3 - DISA-STIG-RHEL-08-040310 - NIST-800-53-CM-6(a) - NIST-800-53-SI-7 - NIST-800-53-SI-7(1) - aide_verify_acls - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Gather list of packages package_facts: manager: auto when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '' tags: - CCE-83733-6 - DISA-STIG-RHEL-08-040300 - NIST-800-53-CM-6(a) - NIST-800-53-SI-7 - NIST-800-53-SI-7(1) - aide_verify_ext_attributes - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Get rules groups shell: | set -o pipefail LC_ALL=C grep "^[A-Z][A-Za-z_]*" /etc/aide.conf | grep -v "^ALLXTRAHASHES" | cut -f1 -d '=' | tr -d ' ' | sort -u || true when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '''aide'' in ansible_facts.packages' register: find_rules_groups_results tags: - CCE-83733-6 - DISA-STIG-RHEL-08-040300 - NIST-800-53-CM-6(a) - NIST-800-53-SI-7 - NIST-800-53-SI-7(1) - aide_verify_ext_attributes - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Ensure the xattrs rule is present when aide is installed. replace: path: /etc/aide.conf regexp: (^\s*{{ item }}\s*=\s*)(?!.*xattrs)([^\s]*) replace: \g<1>\g<2>+xattrs when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '''aide'' in ansible_facts.packages' with_items: '{{ find_rules_groups_results.stdout_lines | map(''trim'') | list }}' tags: - CCE-83733-6 - DISA-STIG-RHEL-08-040300 - NIST-800-53-CM-6(a) - NIST-800-53-SI-7 - NIST-800-53-SI-7(1) - aide_verify_ext_attributes - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Test for existence /sbin/auditctl stat: path: /sbin/auditctl register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /sbin/auditctl file: path: /sbin/auditctl group: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/aureport stat: path: /sbin/aureport register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /sbin/aureport file: path: /sbin/aureport group: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/ausearch stat: path: /sbin/ausearch register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /sbin/ausearch file: path: /sbin/ausearch group: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/autrace stat: path: /sbin/autrace register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /sbin/autrace file: path: /sbin/autrace group: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/auditd stat: path: /sbin/auditd register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /sbin/auditd file: path: /sbin/auditd group: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/rsyslogd stat: path: /sbin/rsyslogd register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /sbin/rsyslogd file: path: /sbin/rsyslogd group: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/augenrules stat: path: /sbin/augenrules register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /sbin/augenrules file: path: /sbin/augenrules group: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86239-1 - DISA-STIG-RHEL-08-030640 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_group_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/auditctl stat: path: /sbin/auditctl register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /sbin/auditctl file: path: /sbin/auditctl owner: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/aureport stat: path: /sbin/aureport register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /sbin/aureport file: path: /sbin/aureport owner: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/ausearch stat: path: /sbin/ausearch register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /sbin/ausearch file: path: /sbin/ausearch owner: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/autrace stat: path: /sbin/autrace register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /sbin/autrace file: path: /sbin/autrace owner: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/auditd stat: path: /sbin/auditd register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /sbin/auditd file: path: /sbin/auditd owner: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/rsyslogd stat: path: /sbin/rsyslogd register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /sbin/rsyslogd file: path: /sbin/rsyslogd owner: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/augenrules stat: path: /sbin/augenrules register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /sbin/augenrules file: path: /sbin/augenrules owner: '0' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86259-9 - DISA-STIG-RHEL-08-030630 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_ownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/auditctl stat: path: /sbin/auditctl register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-s,g-ws,o-wt on /sbin/auditctl file: path: /sbin/auditctl mode: u-s,g-ws,o-wt when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/aureport stat: path: /sbin/aureport register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-s,g-ws,o-wt on /sbin/aureport file: path: /sbin/aureport mode: u-s,g-ws,o-wt when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/ausearch stat: path: /sbin/ausearch register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-s,g-ws,o-wt on /sbin/ausearch file: path: /sbin/ausearch mode: u-s,g-ws,o-wt when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/autrace stat: path: /sbin/autrace register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-s,g-ws,o-wt on /sbin/autrace file: path: /sbin/autrace mode: u-s,g-ws,o-wt when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/auditd stat: path: /sbin/auditd register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-s,g-ws,o-wt on /sbin/auditd file: path: /sbin/auditd mode: u-s,g-ws,o-wt when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/rsyslogd stat: path: /sbin/rsyslogd register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-s,g-ws,o-wt on /sbin/rsyslogd file: path: /sbin/rsyslogd mode: u-s,g-ws,o-wt when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /sbin/augenrules stat: path: /sbin/augenrules register: file_exists when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-s,g-ws,o-wt on /sbin/augenrules file: path: /sbin/augenrules mode: u-s,g-ws,o-wt when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - file_exists.stat is defined and file_exists.stat.exists tags: - CCE-86227-6 - DISA-STIG-RHEL-08-030620 - NIST-800-53-AU-9 - configure_strategy - file_audit_tools_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Check to see the current status of FIPS mode command: /usr/bin/fips-mode-setup --check register: is_fips_enabled changed_when: false failed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and not ( lookup("env", "container") == "bwrap-osbuild" ) ) tags: - CCE-82155-3 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-6(a) - NIST-800-53-IA-7 - NIST-800-53-SC-12 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - enable_dracut_fips_module - high_severity - medium_complexity - medium_disruption - reboot_required - restrict_strategy - name: Enable FIPS mode command: /usr/bin/fips-mode-setup --enable when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and not ( lookup("env", "container") == "bwrap-osbuild" ) ) - is_fips_enabled.stdout.find('FIPS mode is enabled.') == -1 tags: - CCE-82155-3 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-6(a) - NIST-800-53-IA-7 - NIST-800-53-SC-12 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - enable_dracut_fips_module - high_severity - medium_complexity - medium_disruption - reboot_required - restrict_strategy - name: Enable Dracut FIPS Module lineinfile: path: /etc/dracut.conf.d/40-fips.conf line: add_dracutmodules+=" fips " when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and not ( lookup("env", "container") == "bwrap-osbuild" ) ) tags: - CCE-82155-3 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-6(a) - NIST-800-53-IA-7 - NIST-800-53-SC-12 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - enable_dracut_fips_module - high_severity - medium_complexity - medium_disruption - reboot_required - restrict_strategy - name: Enable FIPS Mode - Check to See the Current Status of FIPS Mode ansible.builtin.command: /usr/bin/fips-mode-setup --check register: is_fips_enabled ignore_errors: true changed_when: false when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and not ( lookup("env", "container") == "bwrap-osbuild" ) ) - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80942-6 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-3(6) - NIST-800-53-CM-6(a) - NIST-800-53-IA-7 - NIST-800-53-SC-12 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - enable_fips_mode - high_severity - medium_complexity - medium_disruption - reboot_required - restrict_strategy - name: Enable FIPS Mode - Enable FIPS Mode ansible.builtin.command: /usr/bin/fips-mode-setup --enable when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and not ( lookup("env", "container") == "bwrap-osbuild" ) ) - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - is_fips_enabled.stdout.find('FIPS mode is enabled.') == -1 tags: - CCE-80942-6 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-3(6) - NIST-800-53-CM-6(a) - NIST-800-53-IA-7 - NIST-800-53-SC-12 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - enable_fips_mode - high_severity - medium_complexity - medium_disruption - reboot_required - restrict_strategy - name: Enable FIPS Mode - Configure Crypto Policy ansible.builtin.lineinfile: path: /etc/crypto-policies/config regexp: ^(?!#)(\S+)$ line: '{{ var_system_crypto_policy }}' create: true when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and not ( lookup("env", "container") == "bwrap-osbuild" ) ) - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80942-6 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-3(6) - NIST-800-53-CM-6(a) - NIST-800-53-IA-7 - NIST-800-53-SC-12 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - enable_fips_mode - high_severity - medium_complexity - medium_disruption - reboot_required - restrict_strategy - name: Enable FIPS Mode - Verify that Crypto Policy is Set (runtime) ansible.builtin.command: /usr/bin/update-crypto-policies --set {{ var_system_crypto_policy }} when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and not ( lookup("env", "container") == "bwrap-osbuild" ) ) - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80942-6 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-3(6) - NIST-800-53-CM-6(a) - NIST-800-53-IA-7 - NIST-800-53-SC-12 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - enable_fips_mode - high_severity - medium_complexity - medium_disruption - reboot_required - restrict_strategy - name: Configure System Cryptography Policy lineinfile: path: /etc/crypto-policies/config regexp: ^(?!#)(\S+)$ line: '{{ var_system_crypto_policy }}' create: true tags: - CCE-80935-0 - DISA-STIG-RHEL-08-010020 - NIST-800-53-AC-17(2) - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - PCI-DSSv4-2.2.7 - configure_crypto_policy - high_severity - low_complexity - low_disruption - no_reboot_needed - restrict_strategy - name: Verify that Crypto Policy is Set (runtime) command: /usr/bin/update-crypto-policies --set {{ var_system_crypto_policy }} tags: - CCE-80935-0 - DISA-STIG-RHEL-08-010020 - NIST-800-53-AC-17(2) - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - PCI-DSSv4-2.2.7 - configure_crypto_policy - high_severity - low_complexity - low_disruption - no_reboot_needed - restrict_strategy - name: 'Configure GnuTLS library to use DoD-approved TLS Encryption: set_fact' set_fact: path: /etc/crypto-policies/back-ends/gnutls.config correct_value: +VERS-ALL:-VERS-DTLS0.9:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS1.0 lineinfile_reg: \+VERS-ALL:-VERS-DTLS0\.9:-VERS-SSL3\.0:-VERS-TLS1\.0:-VERS-TLS1\.1:-VERS-DTLS1\.0 tags: - CCE-84254-2 - DISA-STIG-RHEL-08-010295 - NIST-800-53-AC-17(2) - configure_gnutls_tls_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure GnuTLS library to use DoD-approved TLS Encryption: stat' stat: path: '{{ path }}' follow: true register: gnutls_file tags: - CCE-84254-2 - DISA-STIG-RHEL-08-010295 - NIST-800-53-AC-17(2) - configure_gnutls_tls_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure GnuTLS library to use DoD-approved TLS Encryption: Add' lineinfile: path: '{{ path }}' regexp: '{{ lineinfile_reg }}' line: '{{ correct_value }}' create: true when: not gnutls_file.stat.exists or gnutls_file.stat.size <= correct_value|length tags: - CCE-84254-2 - DISA-STIG-RHEL-08-010295 - NIST-800-53-AC-17(2) - configure_gnutls_tls_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Configure GnuTLS library to use DoD-approved TLS Encryption block: - name: 'Configure GnuTLS library to use DoD-approved TLS Encryption: Existing value check' lineinfile: path: '{{ path }}' create: false regexp: '{{ lineinfile_reg }}' state: absent check_mode: true changed_when: false register: gnutls - name: 'Configure GnuTLS library to use DoD-approved TLS Encryption: Update' replace: path: '{{ path }}' regexp: (\+VERS-ALL(?::-VERS-[A-Z]+\d\.\d)+) replace: '{{ correct_value }}' when: gnutls.found is defined and gnutls.found != 1 when: gnutls_file.stat.exists and gnutls_file.stat.size > correct_value|length tags: - CCE-84254-2 - DISA-STIG-RHEL-08-010295 - NIST-800-53-AC-17(2) - configure_gnutls_tls_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Configure Kerberos to use System Crypto Policy file: src: /etc/crypto-policies/back-ends/krb5.config path: /etc/krb5.conf.d/crypto-policies state: link tags: - CCE-80936-8 - DISA-STIG-RHEL-08-010020 - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - configure_kerberos_crypto_policy - configure_strategy - high_severity - low_complexity - low_disruption - reboot_required - name: Configure Libreswan to use System Crypto Policy lineinfile: path: /etc/ipsec.conf line: include /etc/crypto-policies/back-ends/libreswan.config create: true tags: - CCE-80937-6 - DISA-STIG-RHEL-08-010020 - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - PCI-DSS-Req-2.2 - configure_libreswan_crypto_policy - high_severity - low_complexity - low_disruption - no_reboot_needed - restrict_strategy - name: Configure OpenSSL library to use System Crypto Policy - Search for crypto_policy Section ansible.builtin.find: paths: /etc/pki/tls patterns: openssl.cnf contains: ^\s*\[\s*crypto_policy\s*] register: test_crypto_policy_group tags: - CCE-80938-4 - DISA-STIG-RHEL-08-010293 - NIST-800-53-AC-17(2) - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - PCI-DSS-Req-2.2 - configure_openssl_crypto_policy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Configure OpenSSL library to use System Crypto Policy - Search for crypto_policy Section Together With .include Directive ansible.builtin.find: paths: /etc/pki/tls patterns: openssl.cnf contains: ^\s*\.include\s*(?:=\s*)?/etc/crypto-policies/back-ends/opensslcnf.config$ register: test_crypto_policy_include_directive tags: - CCE-80938-4 - DISA-STIG-RHEL-08-010293 - NIST-800-53-AC-17(2) - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - PCI-DSS-Req-2.2 - configure_openssl_crypto_policy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Configure OpenSSL library to use System Crypto Policy - Add .include Line for opensslcnf.config File in crypto_policy Section ansible.builtin.lineinfile: create: true insertafter: ^\s*\[\s*crypto_policy\s*]\s* line: .include /etc/crypto-policies/back-ends/opensslcnf.config path: /etc/pki/tls/openssl.cnf when: - test_crypto_policy_group.matched > 0 - test_crypto_policy_include_directive.matched == 0 tags: - CCE-80938-4 - DISA-STIG-RHEL-08-010293 - NIST-800-53-AC-17(2) - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - PCI-DSS-Req-2.2 - configure_openssl_crypto_policy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Configure OpenSSL library to use System Crypto Policy - Add crypto_policy Section With .include for opensslcnf.config File ansible.builtin.lineinfile: create: true line: |- [crypto_policy] .include /etc/crypto-policies/back-ends/opensslcnf.config path: /etc/pki/tls/openssl.cnf when: test_crypto_policy_group.matched == 0 tags: - CCE-80938-4 - DISA-STIG-RHEL-08-010293 - NIST-800-53-AC-17(2) - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-12(2) - NIST-800-53-SC-12(3) - NIST-800-53-SC-13 - PCI-DSS-Req-2.2 - configure_openssl_crypto_policy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Configure SSH to use System Crypto Policy lineinfile: dest: /etc/sysconfig/sshd state: absent regexp: ^(?i)\s*CRYPTO_POLICY.*$ tags: - CCE-80939-2 - DISA-STIG-RHEL-08-010287 - NIST-800-53-AC-17(2) - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(6) - NIST-800-53-SC-13 - PCI-DSS-Req-2.2 - PCI-DSSv4-2.2.7 - configure_ssh_crypto_policy - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - name: 'Configure SSH Daemon to Use FIPS 140-2 Validated Ciphers: openssh.config' block: - name: Check for duplicate values lineinfile: path: /etc/crypto-policies/back-ends/openssh.config create: true regexp: ^.*Ciphers\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/crypto-policies/back-ends/openssh.config lineinfile: path: /etc/crypto-policies/back-ends/openssh.config create: true regexp: ^.*Ciphers\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/crypto-policies/back-ends/openssh.config lineinfile: path: /etc/crypto-policies/back-ends/openssh.config create: true regexp: ^.*Ciphers\s+ line: Ciphers {{ sshd_approved_ciphers }} state: present tags: - CCE-85902-5 - DISA-STIG-RHEL-08-010020 - NIST-800-53-AC-17(2) - harden_sshd_ciphers_openssh_conf_crypto_policy - high_severity - low_complexity - low_disruption - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated Ciphers: opensshserver.config: Set facts' set_fact: path: /etc/crypto-policies/back-ends/opensshserver.config correct_value: -oCiphers={{ sshd_approved_ciphers }} tags: - CCE-85897-7 - DISA-STIG-RHEL-08-010291 - NIST-800-53-AC-17(2) - harden_sshd_ciphers_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated Ciphers: opensshserver.config: Stat' stat: path: '{{ path }}' follow: true register: opensshserver_file tags: - CCE-85897-7 - DISA-STIG-RHEL-08-010291 - NIST-800-53-AC-17(2) - harden_sshd_ciphers_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated Ciphers: opensshserver.config: Create' lineinfile: path: '{{ path }}' line: CRYPTO_POLICY='{{ correct_value }}' create: true when: not opensshserver_file.stat.exists or opensshserver_file.stat.size <= correct_value|length tags: - CCE-85897-7 - DISA-STIG-RHEL-08-010291 - NIST-800-53-AC-17(2) - harden_sshd_ciphers_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated Ciphers: opensshserver.config' block: - name: Existing value check lineinfile: path: '{{ path }}' create: false regexp: '{{ correct_value }}' state: absent check_mode: true changed_when: false register: opensshserver - name: Update/Correct value replace: path: '{{ path }}' regexp: (-oCiphers=\S+) replace: '{{ correct_value }}' when: opensshserver.found is defined and opensshserver.found != 1 when: opensshserver_file.stat.exists and opensshserver_file.stat.size > correct_value|length tags: - CCE-85897-7 - DISA-STIG-RHEL-08-010291 - NIST-800-53-AC-17(2) - harden_sshd_ciphers_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Daemon to Use FIPS 140-2 Validated MACs: openssh.config' block: - name: Check for duplicate values lineinfile: path: /etc/crypto-policies/back-ends/openssh.config create: true regexp: ^.*MACs\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/crypto-policies/back-ends/openssh.config lineinfile: path: /etc/crypto-policies/back-ends/openssh.config create: true regexp: ^.*MACs\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/crypto-policies/back-ends/openssh.config lineinfile: path: /etc/crypto-policies/back-ends/openssh.config create: true regexp: ^.*MACs\s+ line: MACs {{ sshd_approved_macs }} state: present tags: - CCE-85870-4 - DISA-STIG-RHEL-08-010020 - NIST-800-53-AC-17(2) - harden_sshd_macs_openssh_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated MACs: opensshserver.config: Set facts' set_fact: path: /etc/crypto-policies/back-ends/opensshserver.config correct_value: -oMACs={{ sshd_approved_macs }} tags: - CCE-85899-3 - DISA-STIG-RHEL-08-010290 - NIST-800-53-AC-17(2) - harden_sshd_macs_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated MACs: opensshserver.config: Stat' stat: path: '{{ path }}' follow: true register: opensshserver_file tags: - CCE-85899-3 - DISA-STIG-RHEL-08-010290 - NIST-800-53-AC-17(2) - harden_sshd_macs_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated MACs: opensshserver.config: Create' lineinfile: path: '{{ path }}' line: CRYPTO_POLICY='{{ correct_value }}' create: true when: not opensshserver_file.stat.exists or opensshserver_file.stat.size <= correct_value|length tags: - CCE-85899-3 - DISA-STIG-RHEL-08-010290 - NIST-800-53-AC-17(2) - harden_sshd_macs_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: 'Configure SSH Server to Use FIPS 140-2 Validated MACs: opensshserver.config' block: - name: Existing value check lineinfile: path: '{{ path }}' create: false regexp: '{{ correct_value }}' state: absent check_mode: true changed_when: false register: opensshserver - name: Update/Correct value replace: path: '{{ path }}' regexp: (-oMACs=\S+) replace: '{{ correct_value }}' when: opensshserver.found is defined and opensshserver.found != 1 when: opensshserver_file.stat.exists and opensshserver_file.stat.size > correct_value|length tags: - CCE-85899-3 - DISA-STIG-RHEL-08-010290 - NIST-800-53-AC-17(2) - harden_sshd_macs_opensshserver_conf_crypto_policy - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86195-5 - DISA-STIG-RHEL-08-020032 - NIST-800-53-AC-23 - NIST-800-53-CM-6(a) - dconf_gnome_disable_user_list - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Disable the GNOME3 Login User List ini_file: dest: /etc/dconf/db/gdm.d/00-security-settings section: org/gnome/login-screen option: disable-user-list value: 'true' no_extra_spaces: true create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86195-5 - DISA-STIG-RHEL-08-020032 - NIST-800-53-AC-23 - NIST-800-53-CM-6(a) - dconf_gnome_disable_user_list - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME3 disablement of Login User List lineinfile: path: /etc/dconf/db/gdm.d/locks/00-security-settings-lock regexp: ^/org/gnome/login-screen/disable-user-list$ line: /org/gnome/login-screen/disable-user-list create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86195-5 - DISA-STIG-RHEL-08-020032 - NIST-800-53-AC-23 - NIST-800-53-CM-6(a) - dconf_gnome_disable_user_list - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86195-5 - DISA-STIG-RHEL-08-020032 - NIST-800-53-AC-23 - NIST-800-53-CM-6(a) - dconf_gnome_disable_user_list - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Detect if removal-action can be found on /etc/dconf/db/local.d/ find: path: /etc/dconf/db/local.d/ contains: ^\s*removal-action register: dconf_gnome_lock_screen_on_smartcard_removal_config_files when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Configure removal-action - default file ini_file: dest: /etc/dconf/db/local.d//00-security-settings section: org/gnome/settings-daemon/peripherals/smartcard option: removal-action value: '''lock-screen''' create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - dconf_gnome_lock_screen_on_smartcard_removal_config_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_config_files.matched == 0 tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Configure removal-action - existing files ini_file: dest: '{{ item.path }}' section: org/gnome/settings-daemon/peripherals/smartcard option: removal-action value: '''lock-screen''' create: true with_items: '{{ dconf_gnome_lock_screen_on_smartcard_removal_config_files.files }}' when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - dconf_gnome_lock_screen_on_smartcard_removal_config_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_config_files.matched > 0 tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Detect if lock for removal-action can be found on /etc/dconf/db/local.d/ find: path: /etc/dconf/db/local.d/locks contains: ^\s*removal-action register: dconf_gnome_lock_screen_on_smartcard_removal_lock_files when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification removal-action - default file lineinfile: path: /etc/dconf/db/local.d/locks/00-security-settings-lock regexp: ^/org/gnome/settings-daemon/peripherals/smartcard/removal-action$ line: /org/gnome/settings-daemon/peripherals/smartcard/removal-action create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - dconf_gnome_lock_screen_on_smartcard_removal_lock_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_lock_files.matched == 0 tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification removal-action - existing files lineinfile: path: '{{ item.path }}' regexp: ^/org/gnome/settings-daemon/peripherals/smartcard/removal-action$ line: /org/gnome/settings-daemon/peripherals/smartcard/removal-action create: true with_items: '{{ dconf_gnome_lock_screen_on_smartcard_removal_lock_files.files }}' when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - dconf_gnome_lock_screen_on_smartcard_removal_lock_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_lock_files.matched > 0 tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update - removal-action command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83910-0 - DISA-STIG-RHEL-08-020050 - dconf_gnome_lock_screen_on_smartcard_removal - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80823-8 - DISA-STIG-RHEL-08-010820 - NIST-800-171-3.1.1 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - PCI-DSSv4-8.3.1 - gnome_gdm_disable_automatic_login - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Disable GDM Automatic Login ini_file: dest: /etc/gdm/custom.conf section: daemon option: AutomaticLoginEnable value: 'false' no_extra_spaces: true create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80823-8 - DISA-STIG-RHEL-08-010820 - NIST-800-171-3.1.1 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - PCI-DSSv4-8.3.1 - gnome_gdm_disable_automatic_login - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80775-0 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020060 - NIST-800-171-3.1.10 - NIST-800-53-AC-11(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_idle_delay - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Set GNOME3 Screensaver Inactivity Timeout ini_file: dest: /etc/dconf/db/local.d/00-security-settings section: org/gnome/desktop/session option: idle-delay value: uint32 {{ inactivity_timeout_value }} create: true no_extra_spaces: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80775-0 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020060 - NIST-800-171-3.1.10 - NIST-800-53-AC-11(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_idle_delay - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80775-0 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020060 - NIST-800-171-3.1.10 - NIST-800-53-AC-11(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_idle_delay - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80776-8 - DISA-STIG-RHEL-08-020031 - NIST-800-171-3.1.10 - NIST-800-53-AC-11(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_delay - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Set GNOME3 Screensaver Lock Delay After Activation Period ini_file: dest: /etc/dconf/db/local.d/00-security-settings section: org/gnome/desktop/screensaver option: lock-delay value: uint32 {{ var_screensaver_lock_delay }} create: true no_extra_spaces: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80776-8 - DISA-STIG-RHEL-08-020031 - NIST-800-171-3.1.10 - NIST-800-53-AC-11(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_delay - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80776-8 - DISA-STIG-RHEL-08-020031 - NIST-800-171-3.1.10 - NIST-800-53-AC-11(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_delay - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution == 'SLES' tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Enable GNOME3 Screensaver Lock After Idle Period ini_file: dest: /etc/dconf/db/local.d/00-security-settings section: org/gnome/desktop/screensaver option: lock-enabled value: 'true' create: true no_extra_spaces: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution != 'SLES' tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME lock-enabled lineinfile: path: /etc/dconf/db/local.d/locks/00-security-settings-lock regexp: ^/org/gnome/desktop/screensaver/lock-enabled$ line: /org/gnome/desktop/screensaver/lock-enabled create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution != 'SLES' tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Enable GNOME3 Screensaver Lock After Idle Period ini_file: dest: /etc/dconf/db/local.d/00-security-settings section: org/gnome/desktop/lockdown option: disable-lock-screen value: 'false' create: true no_extra_spaces: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution == 'SLES' tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME disable-lock-screen lineinfile: path: /etc/dconf/db/local.d/locks/00-security-settings-lock regexp: ^/org/gnome/desktop/lockdown/disable-lock-screen$ line: /org/gnome/desktop/lockdown/disable-lock-screen create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution == 'SLES' tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Check GNOME3 screenserver disable-lock-screen false command: gsettings get org.gnome.desktop.lockdown disable-lock-screen register: cmd_out when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution == 'SLES' tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Update GNOME3 screenserver disable-lock-screen false command: gsettings set org.gnome.desktop.lockdown disable-lock-screen false when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution == 'SLES' tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80777-6 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020030 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_screensaver_lock_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-87261-4 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020082 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - dconf_gnome_screensaver_lock_locked - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME Screensaver lock-enabled lineinfile: path: /etc/dconf/db/local.d/locks/00-security-settings-lock regexp: ^/org/gnome/desktop/screensaver/lock-enabled$ line: /org/gnome/desktop/screensaver/lock-enabled create: true when: '"gdm" in ansible_facts.packages' tags: - CCE-87261-4 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020082 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - dconf_gnome_screensaver_lock_locked - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: '"gdm" in ansible_facts.packages' tags: - CCE-87261-4 - CJIS-5.5.5 - DISA-STIG-RHEL-08-020082 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - dconf_gnome_screensaver_lock_locked - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80780-0 - DISA-STIG-RHEL-08-020080 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - dconf_gnome_screensaver_user_locks - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME lock-delay lineinfile: path: /etc/dconf/db/local.d/locks/00-security-settings-lock regexp: ^/org/gnome/desktop/screensaver/lock-delay$ line: /org/gnome/desktop/screensaver/lock-delay create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80780-0 - DISA-STIG-RHEL-08-020080 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - dconf_gnome_screensaver_user_locks - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80780-0 - DISA-STIG-RHEL-08-020080 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - dconf_gnome_screensaver_user_locks - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80781-8 - DISA-STIG-RHEL-08-020081 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_session_idle_user_locks - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME Session idle-delay lineinfile: path: /etc/dconf/db/local.d/locks/00-security-settings-lock regexp: ^/org/gnome/desktop/session/idle-delay$ line: /org/gnome/desktop/session/idle-delay create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80781-8 - DISA-STIG-RHEL-08-020081 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_session_idle_user_locks - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80781-8 - DISA-STIG-RHEL-08-020081 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - dconf_gnome_session_idle_user_locks - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-84028-0 - DISA-STIG-RHEL-08-040171 - NIST-800-171-3.1.2 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - dconf_gnome_disable_ctrlaltdel_reboot - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Disable Ctrl-Alt-Del Reboot Key Sequence in GNOME3 ini_file: dest: /etc/dconf/db/local.d/00-security-settings section: org/gnome/settings-daemon/plugins/media-keys option: logout value: '''''' create: true no_extra_spaces: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84028-0 - DISA-STIG-RHEL-08-040171 - NIST-800-171-3.1.2 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - dconf_gnome_disable_ctrlaltdel_reboot - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME disablement of Ctrl-Alt-Del lineinfile: path: /etc/dconf/db/local.d/locks/00-security-settings-lock regexp: ^/org/gnome/settings-daemon/plugins/media-keys/logout$ line: /org/gnome/settings-daemon/plugins/media-keys/logout create: true when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84028-0 - DISA-STIG-RHEL-08-040171 - NIST-800-171-3.1.2 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - dconf_gnome_disable_ctrlaltdel_reboot - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: - '"gdm" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84028-0 - DISA-STIG-RHEL-08-040171 - NIST-800-171-3.1.2 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - dconf_gnome_disable_ctrlaltdel_reboot - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Find /etc/sudoers.d/ files ansible.builtin.find: paths: - /etc/sudoers.d/ register: sudoers tags: - CCE-82202-3 - DISA-STIG-RHEL-08-010381 - NIST-800-53-CM-6(a) - NIST-800-53-IA-11 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_remove_no_authenticate - name: Remove lines containing !authenticate from sudoers files ansible.builtin.replace: regexp: (^(?!#).*[\s]+\!authenticate.*$) replace: '# \g<1>' path: '{{ item.path }}' validate: /usr/sbin/visudo -cf %s with_items: - path: /etc/sudoers - '{{ sudoers.files }}' tags: - CCE-82202-3 - DISA-STIG-RHEL-08-010381 - NIST-800-53-CM-6(a) - NIST-800-53-IA-11 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_remove_no_authenticate - name: Find /etc/sudoers.d/ files ansible.builtin.find: paths: - /etc/sudoers.d/ register: sudoers tags: - CCE-82197-5 - DISA-STIG-RHEL-08-010380 - NIST-800-53-CM-6(a) - NIST-800-53-IA-11 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_remove_nopasswd - name: Remove lines containing NOPASSWD from sudoers files ansible.builtin.replace: regexp: (^(?!#).*[\s]+NOPASSWD[\s]*\:.*$) replace: '# \g<1>' path: '{{ item.path }}' validate: /usr/sbin/visudo -cf %s with_items: - path: /etc/sudoers - '{{ sudoers.files }}' tags: - CCE-82197-5 - DISA-STIG-RHEL-08-010380 - NIST-800-53-CM-6(a) - NIST-800-53-IA-11 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_remove_nopasswd - name: Gather the package facts package_facts: manager: auto tags: - CCE-87838-9 - DISA-STIG-RHEL-08-010384 - NIST-800-53-IA-11 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_require_reauthentication - name: Require Re-Authentication When Using the sudo Command - Find /etc/sudoers.d/* files containing 'Defaults timestamp_timeout' ansible.builtin.find: path: /etc/sudoers.d patterns: '*' contains: ^[\s]*Defaults\s.*\btimestamp_timeout[\s]*=.* register: sudoers_d_defaults_timestamp_timeout when: '"sudo" in ansible_facts.packages' tags: - CCE-87838-9 - DISA-STIG-RHEL-08-010384 - NIST-800-53-IA-11 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_require_reauthentication - name: Require Re-Authentication When Using the sudo Command - Remove 'Defaults timestamp_timeout' from /etc/sudoers.d/* files ansible.builtin.lineinfile: path: '{{ item.path }}' regexp: ^[\s]*Defaults\s.*\btimestamp_timeout[\s]*=.* state: absent with_items: '{{ sudoers_d_defaults_timestamp_timeout.files }}' when: '"sudo" in ansible_facts.packages' tags: - CCE-87838-9 - DISA-STIG-RHEL-08-010384 - NIST-800-53-IA-11 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_require_reauthentication - name: Require Re-Authentication When Using the sudo Command - Ensure timestamp_timeout has the appropriate value in /etc/sudoers ansible.builtin.lineinfile: path: /etc/sudoers regexp: ^[\s]*Defaults\s(.*)\btimestamp_timeout[\s]*=[\s]*[-]?\w+\b(.*)$ line: Defaults \1timestamp_timeout={{ var_sudo_timestamp_timeout }}\2 validate: /usr/sbin/visudo -cf %s backrefs: true register: edit_sudoers_timestamp_timeout_option when: '"sudo" in ansible_facts.packages' tags: - CCE-87838-9 - DISA-STIG-RHEL-08-010384 - NIST-800-53-IA-11 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_require_reauthentication - name: Require Re-Authentication When Using the sudo Command - Enable timestamp_timeout option with correct value in /etc/sudoers ansible.builtin.lineinfile: path: /etc/sudoers line: Defaults timestamp_timeout={{ var_sudo_timestamp_timeout }} validate: /usr/sbin/visudo -cf %s when: - '"sudo" in ansible_facts.packages' - | edit_sudoers_timestamp_timeout_option is defined and not edit_sudoers_timestamp_timeout_option.changed tags: - CCE-87838-9 - DISA-STIG-RHEL-08-010384 - NIST-800-53-IA-11 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_require_reauthentication - name: Require Re-Authentication When Using the sudo Command - Remove timestamp_timeout wrong values in /etc/sudoers ansible.builtin.lineinfile: path: /etc/sudoers regexp: ^[\s]*Defaults\s.*\btimestamp_timeout[\s]*=[\s]*(?!{{ var_sudo_timestamp_timeout }}\b)[-]?\w+\b.*$ state: absent validate: /usr/sbin/visudo -cf %s when: '"sudo" in ansible_facts.packages' tags: - CCE-87838-9 - DISA-STIG-RHEL-08-010384 - NIST-800-53-IA-11 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudo_require_reauthentication - name: Check for duplicate values lineinfile: path: /etc/sudoers create: false regexp: ^#includedir.*$ state: absent check_mode: true changed_when: false register: dupes tags: - CCE-86377-9 - DISA-STIG-RHEL-08-010379 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sudoers_default_includedir - name: Deduplicate values from /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^#includedir.*$ state: absent when: dupes.found is defined and dupes.found > 1 tags: - CCE-86377-9 - DISA-STIG-RHEL-08-010379 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sudoers_default_includedir - name: Insert correct line into /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^#includedir.*$ line: '#includedir /etc/sudoers.d' state: present tags: - CCE-86377-9 - DISA-STIG-RHEL-08-010379 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sudoers_default_includedir - name: Ensure sudoers doesn't include other non-default file lineinfile: path: /etc/sudoers create: false regexp: ^[#@]include[\s]+.*$ state: absent tags: - CCE-86377-9 - DISA-STIG-RHEL-08-010379 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sudoers_default_includedir - name: Ensure sudoers doesn't have non-default includedir lineinfile: path: /etc/sudoers create: false regexp: ^@includedir[\s]+.*$ state: absent tags: - CCE-86377-9 - DISA-STIG-RHEL-08-010379 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sudoers_default_includedir - name: Find out if /etc/sudoers.d/* files contain file or directory includes find: path: /etc/sudoers.d patterns: '*' contains: ^[#@]include(dir)?\s.*$ register: sudoers_d_includes tags: - CCE-86377-9 - DISA-STIG-RHEL-08-010379 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sudoers_default_includedir - name: Remove found occurrences of file and directory includes from /etc/sudoers.d/* files lineinfile: path: '{{ item.path }}' regexp: ^[#@]include(dir)?\s.*$ state: absent with_items: '{{ sudoers_d_includes.files }}' tags: - CCE-86377-9 - DISA-STIG-RHEL-08-010379 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sudoers_default_includedir - name: Gather the package facts package_facts: manager: auto tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Find out if /etc/sudoers.d/* files contain Defaults targetpw to be deduplicated find: path: /etc/sudoers.d patterns: '*' contains: ^Defaults targetpw$ register: sudoers_d_defaults when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Remove found occurrences of Defaults targetpw from /etc/sudoers.d/* files lineinfile: path: '{{ item.path }}' regexp: ^Defaults targetpw$ state: absent with_items: '{{ sudoers_d_defaults.files }}' when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Find out if /etc/sudoers.d/* files contain Defaults rootpw to be deduplicated find: path: /etc/sudoers.d patterns: '*' contains: ^Defaults rootpw$ register: sudoers_d_defaults when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Remove found occurrences of Defaults rootpw from /etc/sudoers.d/* files lineinfile: path: '{{ item.path }}' regexp: ^Defaults rootpw$ state: absent with_items: '{{ sudoers_d_defaults.files }}' when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Find out if /etc/sudoers.d/* files contain Defaults runaspw to be deduplicated find: path: /etc/sudoers.d patterns: '*' contains: ^Defaults runaspw$ register: sudoers_d_defaults when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Remove found occurrences of Defaults runaspw from /etc/sudoers.d/* files lineinfile: path: '{{ item.path }}' regexp: ^Defaults runaspw$ state: absent with_items: '{{ sudoers_d_defaults.files }}' when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Remove any ocurrences of Defaults targetpw in /etc/sudoers lineinfile: path: /etc/sudoers regexp: ^Defaults targetpw$ validate: /usr/sbin/visudo -cf %s state: absent register: sudoers_file_defaults when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Remove any ocurrences of Defaults rootpw in /etc/sudoers lineinfile: path: /etc/sudoers regexp: ^Defaults rootpw$ validate: /usr/sbin/visudo -cf %s state: absent register: sudoers_file_defaults when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Remove any ocurrences of Defaults runaspw in /etc/sudoers lineinfile: path: /etc/sudoers regexp: ^Defaults runaspw$ validate: /usr/sbin/visudo -cf %s state: absent register: sudoers_file_defaults when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Check for duplicate values lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !targetpw$ state: absent check_mode: true changed_when: false register: dupes when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Deduplicate values from /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !targetpw$ state: absent when: - '"sudo" in ansible_facts.packages' - dupes.found is defined and dupes.found > 1 tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Insert correct line into /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !targetpw$ line: Defaults !targetpw state: present when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Check for duplicate values lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !rootpw$ state: absent check_mode: true changed_when: false register: dupes when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Deduplicate values from /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !rootpw$ state: absent when: - '"sudo" in ansible_facts.packages' - dupes.found is defined and dupes.found > 1 tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Insert correct line into /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !rootpw$ line: Defaults !rootpw state: present when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Check for duplicate values lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !runaspw$ state: absent check_mode: true changed_when: false register: dupes when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Deduplicate values from /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !runaspw$ state: absent when: - '"sudo" in ansible_facts.packages' - dupes.found is defined and dupes.found > 1 tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Insert correct line into /etc/sudoers lineinfile: path: /etc/sudoers create: false regexp: ^Defaults !runaspw$ line: Defaults !runaspw state: present when: '"sudo" in ansible_facts.packages' tags: - CCE-83422-6 - DISA-STIG-RHEL-08-010383 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sudoers_validate_passwd - name: Ensure rng-tools is installed package: name: rng-tools state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82968-9 - DISA-STIG-RHEL-08-010472 - enable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_rng-tools_installed - name: Ensure abrt-addon-ccpp is removed package: name: abrt-addon-ccpp state: absent tags: - CCE-82919-2 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_abrt-addon-ccpp_removed - name: Ensure abrt-addon-kerneloops is removed package: name: abrt-addon-kerneloops state: absent tags: - CCE-82926-7 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_abrt-addon-kerneloops_removed - name: Ensure abrt-cli is removed package: name: abrt-cli state: absent tags: - CCE-82907-7 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_abrt-cli_removed - name: Ensure abrt-plugin-sosreport is removed package: name: abrt-plugin-sosreport state: absent tags: - CCE-82910-1 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_abrt-plugin-sosreport_removed - name: Ensure gssproxy is removed package: name: gssproxy state: absent tags: - CCE-82943-2 - DISA-STIG-RHEL-08-040370 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_gssproxy_removed - name: Ensure iprutils is removed package: name: iprutils state: absent tags: - CCE-82946-5 - DISA-STIG-RHEL-08-040380 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_iprutils_removed - name: Ensure krb5-workstation is removed package: name: krb5-workstation state: absent tags: - CCE-82931-7 - DISA-STIG-RHEL-08-010162 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_krb5-workstation_removed - name: Ensure libreport-plugin-logger is removed package: name: libreport-plugin-logger state: absent tags: - CCE-89201-8 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_libreport-plugin-logger_removed - name: Ensure libreport-plugin-rhtsupport is removed package: name: libreport-plugin-rhtsupport state: absent tags: - CCE-88955-0 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_libreport-plugin-rhtsupport_removed - name: Ensure python3-abrt-addon is removed package: name: python3-abrt-addon state: absent tags: - CCE-86084-1 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_python3-abrt-addon_removed - name: Ensure tuned is removed package: name: tuned state: absent tags: - CCE-82904-4 - DISA-STIG-RHEL-08-040390 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_tuned_removed - name: Gather the package facts package_facts: manager: auto tags: - CCE-82476-3 - DISA-STIG-RHEL-08-010440 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-6(a) - NIST-800-53-SI-2(6) - clean_components_post_updating - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Ensure yum Removes Previous Package Versions - Ensure YUM Removes Previous Package Versions ansible.builtin.lineinfile: dest: /etc/yum.conf regexp: ^#?clean_requirements_on_remove line: clean_requirements_on_remove=1 insertafter: \[main\] create: true when: '"yum" in ansible_facts.packages' tags: - CCE-82476-3 - DISA-STIG-RHEL-08-010440 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-6(a) - NIST-800-53-SI-2(6) - clean_components_post_updating - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80790-9 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010370 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SA-12 - NIST-800-53-SA-12(10) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - configure_strategy - ensure_gpgcheck_globally_activated - high_severity - low_complexity - medium_disruption - no_reboot_needed - name: Ensure GPG check is globally activated ini_file: dest: /etc/yum.conf section: main option: gpgcheck value: 1 no_extra_spaces: true create: false when: '"yum" in ansible_facts.packages' tags: - CCE-80790-9 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010370 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SA-12 - NIST-800-53-SA-12(10) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - configure_strategy - ensure_gpgcheck_globally_activated - high_severity - low_complexity - medium_disruption - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80791-7 - DISA-STIG-RHEL-08-010371 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SA-12 - NIST-800-53-SA-12(10) - ensure_gpgcheck_local_packages - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Ensure GPG check Enabled for Local Packages (yum) block: - name: Check stats of yum stat: path: /etc/yum.conf register: pkg - name: Check if config file of yum is a symlink ansible.builtin.set_fact: pkg_config_file_symlink: '{{ pkg.stat.lnk_target if pkg.stat.lnk_target is match("^/.*") else "/etc/yum.conf" | dirname ~ "/" ~ pkg.stat.lnk_target }}' when: pkg.stat.lnk_target is defined - name: Ensure GPG check Enabled for Local Packages (yum) ini_file: dest: '{{ pkg_config_file_symlink | default("/etc/yum.conf") }}' section: main option: localpkg_gpgcheck value: 1 no_extra_spaces: true create: true when: '"yum" in ansible_facts.packages' tags: - CCE-80791-7 - DISA-STIG-RHEL-08-010371 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SA-12 - NIST-800-53-SA-12(10) - ensure_gpgcheck_local_packages - high_severity - low_complexity - medium_disruption - no_reboot_needed - unknown_strategy - name: Grep for yum repo section names shell: | set -o pipefail grep -HEr '^\[.+\]' -r /etc/yum.repos.d/ register: repo_grep_results failed_when: repo_grep_results.rc not in [0, 1] changed_when: false tags: - CCE-80792-5 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010370 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SA-12 - NIST-800-53-SA-12(10) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - enable_strategy - ensure_gpgcheck_never_disabled - high_severity - low_complexity - medium_disruption - no_reboot_needed - name: Set gpgcheck=1 for each yum repo ini_file: path: '{{ item[0] }}' section: '{{ item[1] }}' option: gpgcheck value: '1' no_extra_spaces: true loop: '{{ repo_grep_results.stdout |regex_findall( ''(.+\.repo):\[(.+)\]\n?'' ) if repo_grep_results is not skipped else []}}' when: repo_grep_results is not skipped tags: - CCE-80792-5 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010370 - NIST-800-171-3.4.8 - NIST-800-53-CM-11(a) - NIST-800-53-CM-11(b) - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SA-12 - NIST-800-53-SA-12(10) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - enable_strategy - ensure_gpgcheck_never_disabled - high_severity - low_complexity - medium_disruption - no_reboot_needed - name: Read permission of GPG key directory stat: path: /etc/pki/rpm-gpg/ register: gpg_key_directory_permission check_mode: false tags: - CCE-80795-8 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010019 - NIST-800-171-3.4.8 - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - ensure_redhat_gpgkey_installed - high_severity - medium_complexity - medium_disruption - no_reboot_needed - restrict_strategy - name: Read signatures in GPG key command: gpg --show-keys --with-fingerprint --with-colons "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" changed_when: false register: gpg_fingerprints check_mode: false tags: - CCE-80795-8 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010019 - NIST-800-171-3.4.8 - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - ensure_redhat_gpgkey_installed - high_severity - medium_complexity - medium_disruption - no_reboot_needed - restrict_strategy - name: Set Fact - Installed GPG Fingerprints set_fact: gpg_installed_fingerprints: |- {{ gpg_fingerprints.stdout | regex_findall('^pub.* (?:^fpr[:]*)([0-9A-Fa-f]*)', '\1') | list }} tags: - CCE-80795-8 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010019 - NIST-800-171-3.4.8 - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - ensure_redhat_gpgkey_installed - high_severity - medium_complexity - medium_disruption - no_reboot_needed - restrict_strategy - name: Set Fact - Valid fingerprints set_fact: gpg_valid_fingerprints: - 567E347AD0044ADE55BA8A5F199E2F91FD431D51 - 6A6AA7C97C8890AEC6AEBFE2F76F66C3D4082792 tags: - CCE-80795-8 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010019 - NIST-800-171-3.4.8 - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - ensure_redhat_gpgkey_installed - high_severity - medium_complexity - medium_disruption - no_reboot_needed - restrict_strategy - name: Import RedHat GPG key rpm_key: state: present key: /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release when: - gpg_key_directory_permission.stat.mode <= '0755' - (gpg_installed_fingerprints | difference(gpg_valid_fingerprints)) | length == 0 - gpg_installed_fingerprints | length > 0 - ansible_distribution == "RedHat" tags: - CCE-80795-8 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010019 - NIST-800-171-3.4.8 - NIST-800-53-CM-5(3) - NIST-800-53-CM-6(a) - NIST-800-53-SC-12 - NIST-800-53-SC-12(3) - NIST-800-53-SI-7 - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - ensure_redhat_gpgkey_installed - high_severity - medium_complexity - medium_disruption - no_reboot_needed - restrict_strategy - name: Security patches are up to date package: name: '*' state: latest tags: - CCE-80865-9 - CJIS-5.10.4.1 - DISA-STIG-RHEL-08-010010 - NIST-800-53-CM-6(a) - NIST-800-53-SI-2(5) - NIST-800-53-SI-2(c) - PCI-DSS-Req-6.2 - PCI-DSSv4-6.3.3 - high_disruption - low_complexity - medium_severity - patch_strategy - reboot_required - security_patches_up_to_date - skip_ansible_lint - name: Enable authselect - Select authselect profile ansible.builtin.command: cmd: authselect select "{{ var_authselect_profile }}" register: result_authselect_select failed_when: false tags: - CCE-88248-0 - NIST-800-53-AC-3 - configure_strategy - enable_authselect - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Enable authselect - Verify if PAM has been altered ansible.builtin.command: cmd: rpm -qV pam register: result_altered_authselect failed_when: false when: result_authselect_select.rc != 0 tags: - CCE-88248-0 - NIST-800-53-AC-3 - configure_strategy - enable_authselect - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Enable authselect - Informative message based on the authselect integrity check ansible.builtin.assert: that: - result_altered_authselect is skipped or result_altered_authselect.rc == 0 fail_msg: - Files in the 'pam' package have been altered, so the authselect configuration won't be forced. tags: - CCE-88248-0 - NIST-800-53-AC-3 - configure_strategy - enable_authselect - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Enable authselect - Force authselect profile select ansible.builtin.command: cmd: authselect select --force "{{ var_authselect_profile }}" when: - result_authselect_select.rc != 0 - result_altered_authselect is skipped or result_altered_authselect.rc == 0 tags: - CCE-88248-0 - NIST-800-53-AC-3 - configure_strategy - enable_authselect - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Modify the System Login Banner - Ensure Correct Banner copy: dest: /etc/issue content: '{{ login_banner_text | regex_replace("^\^(.*)\$$", "\1") | regex_replace("^\((.*\.)\|.*\)$", "\1") | regex_replace("\[\\s\\n\]\+"," ") | regex_replace("\(\?:\[\\n\]\+\|\(\?:\\\\n\)\+\)", "\n") | regex_replace("\\", "") | wordwrap() }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80763-6 - DISA-STIG-RHEL-08-010060 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - banner_etc_issue - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80768-5 - DISA-STIG-RHEL-08-010049 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(b) - NIST-800-53-AC-8(c) - dconf_gnome_banner_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Enable GNOME3 Login Warning Banner ini_file: dest: /etc/dconf/db/gdm.d/00-security-settings section: org/gnome/login-screen option: banner-message-enable value: 'true' create: true no_extra_spaces: true when: '"gdm" in ansible_facts.packages' tags: - CCE-80768-5 - DISA-STIG-RHEL-08-010049 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(b) - NIST-800-53-AC-8(c) - dconf_gnome_banner_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of GNOME banner-message-enabled lineinfile: path: /etc/dconf/db/gdm.d/locks/00-security-settings-lock regexp: ^/org/gnome/login-screen/banner-message-enable$ line: /org/gnome/login-screen/banner-message-enable create: true when: '"gdm" in ansible_facts.packages' tags: - CCE-80768-5 - DISA-STIG-RHEL-08-010049 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(b) - NIST-800-53-AC-8(c) - dconf_gnome_banner_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: '"gdm" in ansible_facts.packages' tags: - CCE-80768-5 - DISA-STIG-RHEL-08-010049 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(b) - NIST-800-53-AC-8(c) - dconf_gnome_banner_enabled - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80770-1 - DISA-STIG-RHEL-08-010050 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - dconf_gnome_login_banner_text - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Set the GNOME3 Login Warning Banner Text file: path: /etc/dconf/db/{{ item }} owner: root group: root mode: 493 state: directory with_items: - gdm.d - gdm.d/locks when: '"gdm" in ansible_facts.packages' tags: - CCE-80770-1 - DISA-STIG-RHEL-08-010050 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - dconf_gnome_login_banner_text - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Set the GNOME3 Login Warning Banner Text file: path: /etc/dconf/db/gdm.d/{{ item }} owner: root group: root mode: 420 state: touch with_items: - 00-security-settings - locks/00-security-settings-lock when: '"gdm" in ansible_facts.packages' tags: - CCE-80770-1 - DISA-STIG-RHEL-08-010050 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - dconf_gnome_login_banner_text - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Set the GNOME3 Login Warning Banner Text ini_file: dest: /etc/dconf/db/gdm.d/00-security-settings section: org/gnome/login-screen option: banner-message-text value: '''{{ login_banner_text | regex_replace("^\^(.*)\$$", "\1") | regex_replace("^\((.*\.)\|.*\)$", "\1") | regex_replace("\[\\s\\n\]\+"," ") | regex_replace("\(\?:\[\\n\]\+\|\(\?:\\\\n\)\+\)", "(n)*") | regex_replace("\\", "") | regex_replace("\(n\)\*", "\\n") }}''' create: true no_extra_spaces: true when: '"gdm" in ansible_facts.packages' tags: - CCE-80770-1 - DISA-STIG-RHEL-08-010050 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - dconf_gnome_login_banner_text - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Prevent user modification of the GNOME3 Login Warning Banner Text lineinfile: path: /etc/dconf/db/gdm.d/locks/00-security-settings-lock regexp: ^/org/gnome/login-screen/banner-message-text$ line: /org/gnome/login-screen/banner-message-text create: true state: present when: '"gdm" in ansible_facts.packages' tags: - CCE-80770-1 - DISA-STIG-RHEL-08-010050 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - dconf_gnome_login_banner_text - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Dconf Update command: dconf update when: '"gdm" in ansible_facts.packages' tags: - CCE-80770-1 - DISA-STIG-RHEL-08-010050 - NIST-800-171-3.1.9 - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - dconf_gnome_login_banner_text - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86319-1 - DISA-STIG-RHEL-08-010385 - NIST-800-53-IA-11 - disallow_bypass_password_sudo - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check for pam_succeed_if entry ansible.builtin.lineinfile: path: /etc/pam.d/sudo create: false regexp: pam_succeed_if state: absent when: '"pam" in ansible_facts.packages' tags: - CCE-86319-1 - DISA-STIG-RHEL-08-010385 - NIST-800-53-IA-11 - disallow_bypass_password_sudo - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto 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 system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_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 - 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 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: - 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: Gather the package facts package_facts: manager: auto tags: - CCE-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: password-auth - 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: - CCE-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: password-auth - 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-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: password-auth - Enable pam_pwhistory.so using authselect feature' block: - name: 'Limit Password Reuse: password-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - Get authselect current features' 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: 'Limit Password Reuse: password-auth - Ensure "with-pwhistory" feature is enabled using authselect tool' ansible.builtin.command: cmd: authselect enable-feature with-pwhistory register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-pwhistory") - name: 'Limit Password Reuse: password-auth - Ensure authselect changes are applied' ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists - result_authselect_available_features.stdout is search("with-pwhistory") tags: - CCE-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: password-auth - Enable pam_pwhistory.so in appropriate PAM files' block: - name: 'Limit Password Reuse: password-auth - Define the PAM file to be edited as a local fact' ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: 'Limit Password Reuse: password-auth - Check if system relies on authselect tool' ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: 'Limit Password Reuse: password-auth - Ensure authselect custom profile is used if authselect is present' block: - name: 'Limit Password Reuse: password-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - Check if expected PAM module line 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] }}' | regex_escape() }}\s+pam_pwhistory.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: 'Limit Password Reuse: password-auth - Include or update the PAM module line in {{ pam_file_path }}' block: - name: 'Limit Password Reuse: password-auth - Check if required PAM module line is present in {{ pam_file_path }} with different control' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_pwhistory.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: 'Limit Password Reuse: password-auth - Ensure the correct control for the required PAM module line in {{ pam_file_path }}' ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_pwhistory.so.*) replace: \1{{ var_password_pam_remember_control_flag.split(",")[0] }} \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: 'Limit Password Reuse: password-auth - Ensure the required PAM module line is included in {{ pam_file_path }}' ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' insertafter: ^password.*requisite.*pam_pwquality\.so line: password {{ var_password_pam_remember_control_flag.split(",")[0] }} pam_pwhistory.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: 'Limit Password Reuse: password-auth - 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 when: - '"pam" in ansible_facts.packages' - | (result_authselect_available_features.stdout is defined and result_authselect_available_features.stdout is not search("with-pwhistory")) or result_authselect_available_features is not defined tags: - CCE-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: password-auth - Check the presence of /etc/security/pwhistory.conf file' ansible.builtin.stat: path: /etc/security/pwhistory.conf register: result_pwhistory_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: password-auth - pam_pwhistory.so parameters are configured in /etc/security/pwhistory.conf file' block: - name: 'Limit Password Reuse: password-auth - Ensure the pam_pwhistory.so remember parameter in /etc/security/pwhistory.conf' ansible.builtin.lineinfile: path: /etc/security/pwhistory.conf regexp: ^\s*remember\s*= line: remember = {{ var_password_pam_remember }} state: present - name: 'Limit Password Reuse: password-auth - Ensure the pam_pwhistory.so remember parameter is removed from PAM files' block: - name: 'Limit Password Reuse: password-auth - Check if /etc/pam.d/password-auth file is present' ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present - name: 'Limit Password Reuse: password-auth - Check the proper remediation for the system' block: - name: 'Limit Password Reuse: password-auth - Define the PAM file to be edited as a local fact' ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: 'Limit Password Reuse: password-auth - Check if system relies on authselect tool' ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: 'Limit Password Reuse: password-auth - Ensure authselect custom profile is used if authselect is present' block: - name: 'Limit Password Reuse: password-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - Ensure the "remember" option from "pam_pwhistory.so" is not present in {{ pam_file_path }}' ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*password.*pam_pwhistory.so.*)\bremember\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: 'Limit Password Reuse: password-auth - 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: - result_pam_file_present.stat.exists when: - '"pam" in ansible_facts.packages' - result_pwhistory_conf_check.stat.exists tags: - CCE-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: password-auth - pam_pwhistory.so parameters are configured in PAM files' block: - name: 'Limit Password Reuse: password-auth - Define the PAM file to be edited as a local fact' ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: 'Limit Password Reuse: password-auth - Check if system relies on authselect tool' ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: 'Limit Password Reuse: password-auth - Ensure authselect custom profile is used if authselect is present' block: - name: 'Limit Password Reuse: password-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - Check if expected PAM module line is present in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: 'Limit Password Reuse: password-auth - Include or update the PAM module line in {{ pam_file_path }}' block: - name: 'Limit Password Reuse: password-auth - Check if required PAM module line is present in {{ pam_file_path }} with different control' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_pwhistory.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: 'Limit Password Reuse: password-auth - Ensure the correct control for the required PAM module line in {{ pam_file_path }}' ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_pwhistory.so.*) replace: \1requisite \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: 'Limit Password Reuse: password-auth - Ensure the required PAM module line is included in {{ pam_file_path }}' ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' line: password requisite pam_pwhistory.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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - Check if the required PAM module option is present in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*\sremember\b state: absent check_mode: true changed_when: false register: result_pam_module_remember_option_present - name: 'Limit Password Reuse: password-auth - Ensure the "remember" PAM option for "pam_pwhistory.so" is included in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' backrefs: true 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 when: - result_pam_module_remember_option_present.found == 0 - name: 'Limit Password Reuse: password-auth - Ensure the required value for "remember" PAM option from "pam_pwhistory.so" in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' backrefs: true 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: - result_pam_module_remember_option_present.found > 0 - name: 'Limit Password Reuse: password-auth - Ensure authselect changes are applied' ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_present.stat.exists - (result_pam_remember_add is defined and result_pam_remember_add.changed) or (result_pam_remember_edit is defined and result_pam_remember_edit.changed) when: - '"pam" in ansible_facts.packages' - not result_pwhistory_conf_check.stat.exists tags: - CCE-83478-8 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020220 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: system-auth - 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: - CCE-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: system-auth - 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-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: system-auth - Enable pam_pwhistory.so using authselect feature' block: - name: 'Limit Password Reuse: system-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - Get authselect current features' 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: 'Limit Password Reuse: system-auth - Ensure "with-pwhistory" feature is enabled using authselect tool' ansible.builtin.command: cmd: authselect enable-feature with-pwhistory register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-pwhistory") - name: 'Limit Password Reuse: system-auth - Ensure authselect changes are applied' ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists - result_authselect_available_features.stdout is search("with-pwhistory") tags: - CCE-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: system-auth - Enable pam_pwhistory.so in appropriate PAM files' block: - name: 'Limit Password Reuse: system-auth - Define the PAM file to be edited as a local fact' ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: 'Limit Password Reuse: system-auth - Check if system relies on authselect tool' ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: 'Limit Password Reuse: system-auth - Ensure authselect custom profile is used if authselect is present' block: - name: 'Limit Password Reuse: system-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - Check if expected PAM module line 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] }}' | regex_escape() }}\s+pam_pwhistory.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: 'Limit Password Reuse: system-auth - Include or update the PAM module line in {{ pam_file_path }}' block: - name: 'Limit Password Reuse: system-auth - Check if required PAM module line is present in {{ pam_file_path }} with different control' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_pwhistory.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: 'Limit Password Reuse: system-auth - Ensure the correct control for the required PAM module line in {{ pam_file_path }}' ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_pwhistory.so.*) replace: \1{{ var_password_pam_remember_control_flag.split(",")[0] }} \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: 'Limit Password Reuse: system-auth - Ensure the required PAM module line is included in {{ pam_file_path }}' ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' insertafter: ^password.*requisite.*pam_pwquality\.so line: password {{ var_password_pam_remember_control_flag.split(",")[0] }} pam_pwhistory.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: 'Limit Password Reuse: system-auth - 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 when: - '"pam" in ansible_facts.packages' - | (result_authselect_available_features.stdout is defined and result_authselect_available_features.stdout is not search("with-pwhistory")) or result_authselect_available_features is not defined tags: - CCE-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: system-auth - Check the presence of /etc/security/pwhistory.conf file' ansible.builtin.stat: path: /etc/security/pwhistory.conf register: result_pwhistory_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: system-auth - pam_pwhistory.so parameters are configured in /etc/security/pwhistory.conf file' block: - name: 'Limit Password Reuse: system-auth - Ensure the pam_pwhistory.so remember parameter in /etc/security/pwhistory.conf' ansible.builtin.lineinfile: path: /etc/security/pwhistory.conf regexp: ^\s*remember\s*= line: remember = {{ var_password_pam_remember }} state: present - name: 'Limit Password Reuse: system-auth - Ensure the pam_pwhistory.so remember parameter is removed from PAM files' block: - name: 'Limit Password Reuse: system-auth - Check if /etc/pam.d/system-auth file is present' ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present - name: 'Limit Password Reuse: system-auth - Check the proper remediation for the system' block: - name: 'Limit Password Reuse: system-auth - Define the PAM file to be edited as a local fact' ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: 'Limit Password Reuse: system-auth - Check if system relies on authselect tool' ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: 'Limit Password Reuse: system-auth - Ensure authselect custom profile is used if authselect is present' block: - name: 'Limit Password Reuse: system-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - Ensure the "remember" option from "pam_pwhistory.so" is not present in {{ pam_file_path }}' ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*password.*pam_pwhistory.so.*)\bremember\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: 'Limit Password Reuse: system-auth - 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: - result_pam_file_present.stat.exists when: - '"pam" in ansible_facts.packages' - result_pwhistory_conf_check.stat.exists tags: - CCE-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: 'Limit Password Reuse: system-auth - pam_pwhistory.so parameters are configured in PAM files' block: - name: 'Limit Password Reuse: system-auth - Define the PAM file to be edited as a local fact' ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: 'Limit Password Reuse: system-auth - Check if system relies on authselect tool' ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: 'Limit Password Reuse: system-auth - Ensure authselect custom profile is used if authselect is present' block: - name: 'Limit Password Reuse: system-auth - Check integrity of authselect current profile' ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - Check if expected PAM module line is present in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: 'Limit Password Reuse: system-auth - Include or update the PAM module line in {{ pam_file_path }}' block: - name: 'Limit Password Reuse: system-auth - Check if required PAM module line is present in {{ pam_file_path }} with different control' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_pwhistory.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: 'Limit Password Reuse: system-auth - Ensure the correct control for the required PAM module line in {{ pam_file_path }}' ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_pwhistory.so.*) replace: \1requisite \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: 'Limit Password Reuse: system-auth - Ensure the required PAM module line is included in {{ pam_file_path }}' ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' line: password requisite pam_pwhistory.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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - Check if the required PAM module option is present in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwhistory.so\s*.*\sremember\b state: absent check_mode: true changed_when: false register: result_pam_module_remember_option_present - name: 'Limit Password Reuse: system-auth - Ensure the "remember" PAM option for "pam_pwhistory.so" is included in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' backrefs: true 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 when: - result_pam_module_remember_option_present.found == 0 - name: 'Limit Password Reuse: system-auth - Ensure the required value for "remember" PAM option from "pam_pwhistory.so" in {{ pam_file_path }}' ansible.builtin.lineinfile: path: '{{ pam_file_path }}' backrefs: true 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: - result_pam_module_remember_option_present.found > 0 - name: 'Limit Password Reuse: system-auth - Ensure authselect changes are applied' ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_present.stat.exists - (result_pam_remember_add is defined and result_pam_remember_add.changed) or (result_pam_remember_edit is defined and result_pam_remember_edit.changed) when: - '"pam" in ansible_facts.packages' - not result_pwhistory_conf_check.stat.exists tags: - CCE-83480-4 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020221 - NIST-800-171-3.5.8 - NIST-800-53-IA-5(1)(e) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.5 - PCI-DSSv4-8.3.7 - accounts_password_pam_pwhistory_remember_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Account Lockouts Must Be Logged - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present when: ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.2', '>=') tags: - CCE-86099-9 - DISA-STIG-RHEL-08-020021 - NIST-800-53-AC-7 (a) - accounts_passwords_pam_faillock_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Account Lockouts Must Be Logged - Remediation where authselect tool is present block: - name: Account Lockouts Must Be Logged - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - Get authselect current features 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: Account Lockouts Must Be Logged - Ensure "with-faillock" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-faillock register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-faillock") - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.2', '>=') - result_authselect_present.stat.exists tags: - CCE-86099-9 - DISA-STIG-RHEL-08-020021 - NIST-800-53-AC-7 (a) - accounts_passwords_pam_faillock_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Account Lockouts Must Be Logged - Remediation where authselect tool is not present block: - name: Account Lockouts Must Be Logged - Check if pam_faillock.so is already enabled ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail) state: absent check_mode: true changed_when: false register: result_pam_faillock_is_enabled - name: Account Lockouts Must Be Logged - Enable pam_faillock.so preauth editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so preauth insertbefore: ^auth.*sufficient.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Account Lockouts Must Be Logged - Enable pam_faillock.so authfail editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so authfail insertbefore: ^auth.*required.*pam_deny\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Account Lockouts Must Be Logged - Enable pam_faillock.so account section editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: account required pam_faillock.so insertbefore: ^account.*required.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 when: - ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.2', '>=') - not result_authselect_present.stat.exists tags: - CCE-86099-9 - DISA-STIG-RHEL-08-020021 - NIST-800-53-AC-7 (a) - accounts_passwords_pam_faillock_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Account Lockouts Must Be Logged - Check the presence of /etc/security/faillock.conf file ansible.builtin.stat: path: /etc/security/faillock.conf register: result_faillock_conf_check when: ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.2', '>=') tags: - CCE-86099-9 - DISA-STIG-RHEL-08-020021 - NIST-800-53-AC-7 (a) - accounts_passwords_pam_faillock_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter in /etc/security/faillock.conf ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: ^\s*audit line: audit state: present when: - ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.2', '>=') - result_faillock_conf_check.stat.exists tags: - CCE-86099-9 - DISA-STIG-RHEL-08-020021 - NIST-800-53-AC-7 (a) - accounts_passwords_pam_faillock_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter not in PAM files block: - name: Account Lockouts Must Be Logged - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present - name: Account Lockouts Must Be Logged - Check the proper remediation for the system block: - name: Account Lockouts Must Be Logged - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Account Lockouts Must Be Logged - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Account Lockouts Must Be Logged - Ensure authselect custom profile is used if authselect is present block: - name: Account Lockouts Must Be Logged - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - Ensure the "audit" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\baudit\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Account Lockouts Must Be Logged - 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: - result_pam_file_present.stat.exists - name: Account Lockouts Must Be Logged - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present - name: Account Lockouts Must Be Logged - Check the proper remediation for the system block: - name: Account Lockouts Must Be Logged - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Account Lockouts Must Be Logged - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Account Lockouts Must Be Logged - Ensure authselect custom profile is used if authselect is present block: - name: Account Lockouts Must Be Logged - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - 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: Account Lockouts Must Be Logged - Ensure the "audit" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\baudit\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Account Lockouts Must Be Logged - 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: - result_pam_file_present.stat.exists when: - ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.2', '>=') - result_faillock_conf_check.stat.exists tags: - CCE-86099-9 - DISA-STIG-RHEL-08-020021 - NIST-800-53-AC-7 (a) - accounts_passwords_pam_faillock_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter in PAM files block: - name: Account Lockouts Must Be Logged - Check if pam_faillock.so audit parameter is already enabled in pam files ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail).*audit state: absent check_mode: true changed_when: false register: result_pam_faillock_audit_parameter_is_present - name: Account Lockouts Must Be Logged - Ensure the inclusion of pam_faillock.so preauth audit parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*) line: \1required\3 audit state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_audit_parameter_is_present.found == 0 when: - ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.2', '>=') - not result_faillock_conf_check.stat.exists tags: - CCE-86099-9 - DISA-STIG-RHEL-08-020021 - NIST-800-53-AC-7 (a) - accounts_passwords_pam_faillock_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Lock Accounts After Failed Password Attempts - 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: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Lock Accounts After Failed Password Attempts - Remediation where authselect tool is present block: - name: Lock Accounts After Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - Get authselect current features 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: Lock Accounts After Failed Password Attempts - Ensure "with-faillock" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-faillock register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-faillock") - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists tags: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Lock Accounts After Failed Password Attempts - Remediation where authselect tool is not present block: - name: Lock Accounts After Failed Password Attempts - Check if pam_faillock.so is already enabled ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail) state: absent check_mode: true changed_when: false register: result_pam_faillock_is_enabled - name: Lock Accounts After Failed Password Attempts - Enable pam_faillock.so preauth editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so preauth insertbefore: ^auth.*sufficient.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Lock Accounts After Failed Password Attempts - Enable pam_faillock.so authfail editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so authfail insertbefore: ^auth.*required.*pam_deny\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Lock Accounts After Failed Password Attempts - Enable pam_faillock.so account section editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: account required pam_faillock.so insertbefore: ^account.*required.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 when: - '"pam" in ansible_facts.packages' - not result_authselect_present.stat.exists tags: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Lock Accounts After Failed Password Attempts - Check the presence of /etc/security/faillock.conf file ansible.builtin.stat: path: /etc/security/faillock.conf register: result_faillock_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Lock Accounts After Failed Password Attempts - Ensure the pam_faillock.so deny parameter in /etc/security/faillock.conf ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: ^\s*deny\s*= line: deny = {{ var_accounts_passwords_pam_faillock_deny }} state: present when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Lock Accounts After Failed Password Attempts - Ensure the pam_faillock.so deny parameter not in PAM files block: - name: Lock Accounts After Failed Password Attempts - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present - name: Lock Accounts After Failed Password Attempts - Check the proper remediation for the system block: - name: Lock Accounts After Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Lock Accounts After Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Lock Accounts After Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Lock Accounts After Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - Ensure the "deny" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bdeny\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Lock Accounts After Failed Password Attempts - 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: - result_pam_file_present.stat.exists - name: Lock Accounts After Failed Password Attempts - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present - name: Lock Accounts After Failed Password Attempts - Check the proper remediation for the system block: - name: Lock Accounts After Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Lock Accounts After Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Lock Accounts After Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Lock Accounts After Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - 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: Lock Accounts After Failed Password Attempts - Ensure the "deny" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bdeny\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Lock Accounts After Failed Password Attempts - 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: - result_pam_file_present.stat.exists when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Lock Accounts After Failed Password Attempts - Ensure the pam_faillock.so deny parameter in PAM files block: - name: Lock Accounts After Failed Password Attempts - Check if pam_faillock.so deny parameter is already enabled in pam files ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail).*deny state: absent check_mode: true changed_when: false register: result_pam_faillock_deny_parameter_is_present - name: Lock Accounts After Failed Password Attempts - Ensure the inclusion of pam_faillock.so preauth deny parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*) line: \1required\3 deny={{ var_accounts_passwords_pam_faillock_deny }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_deny_parameter_is_present.found == 0 - name: Lock Accounts After Failed Password Attempts - Ensure the inclusion of pam_faillock.so authfail deny parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*) line: \1required\3 deny={{ var_accounts_passwords_pam_faillock_deny }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_deny_parameter_is_present.found == 0 - name: Lock Accounts After Failed Password Attempts - Ensure the desired value for pam_faillock.so preauth deny parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(deny)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_deny }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_deny_parameter_is_present.found > 0 - name: Lock Accounts After Failed Password Attempts - Ensure the desired value for pam_faillock.so authfail deny parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(deny)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_deny }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_deny_parameter_is_present.found > 0 when: - '"pam" in ansible_facts.packages' - not result_faillock_conf_check.stat.exists tags: - CCE-80667-9 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020011 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.6 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the root Account for Failed Password Attempts - 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: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the root Account for Failed Password Attempts - Remediation where authselect tool is present block: - name: Configure the root Account for Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - Get authselect current features 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: Configure the root Account for Failed Password Attempts - Ensure "with-faillock" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-faillock register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-faillock") - name: Configure the root Account for Failed Password Attempts - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists tags: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the root Account for Failed Password Attempts - Remediation where authselect tool is not present block: - name: Configure the root Account for Failed Password Attempts - Check if pam_faillock.so is already enabled ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail) state: absent check_mode: true changed_when: false register: result_pam_faillock_is_enabled - name: Configure the root Account for Failed Password Attempts - Enable pam_faillock.so preauth editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so preauth insertbefore: ^auth.*sufficient.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Configure the root Account for Failed Password Attempts - Enable pam_faillock.so authfail editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so authfail insertbefore: ^auth.*required.*pam_deny\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Configure the root Account for Failed Password Attempts - Enable pam_faillock.so account section editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: account required pam_faillock.so insertbefore: ^account.*required.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 when: - '"pam" in ansible_facts.packages' - not result_authselect_present.stat.exists tags: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the root Account for Failed Password Attempts - Check the presence of /etc/security/faillock.conf file ansible.builtin.stat: path: /etc/security/faillock.conf register: result_faillock_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the root Account for Failed Password Attempts - Ensure the pam_faillock.so even_deny_root parameter in /etc/security/faillock.conf ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: ^\s*even_deny_root line: even_deny_root state: present when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the root Account for Failed Password Attempts - Ensure the pam_faillock.so even_deny_root parameter not in PAM files block: - name: Configure the root Account for Failed Password Attempts - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present - name: Configure the root Account for Failed Password Attempts - Check the proper remediation for the system block: - name: Configure the root Account for Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Configure the root Account for Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Configure the root Account for Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Configure the root Account for Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - Ensure the "even_deny_root" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\beven_deny_root\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Configure the root Account for Failed Password Attempts - 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: - result_pam_file_present.stat.exists - name: Configure the root Account for Failed Password Attempts - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present - name: Configure the root Account for Failed Password Attempts - Check the proper remediation for the system block: - name: Configure the root Account for Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Configure the root Account for Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Configure the root Account for Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Configure the root Account for Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - 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: Configure the root Account for Failed Password Attempts - Ensure the "even_deny_root" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\beven_deny_root\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Configure the root Account for Failed Password Attempts - 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: - result_pam_file_present.stat.exists when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the root Account for Failed Password Attempts - Ensure the pam_faillock.so even_deny_root parameter in PAM files block: - name: Configure the root Account for Failed Password Attempts - Check if pam_faillock.so even_deny_root parameter is already enabled in pam files ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail).*even_deny_root state: absent check_mode: true changed_when: false register: result_pam_faillock_even_deny_root_parameter_is_present - name: Configure the root Account for Failed Password Attempts - Ensure the inclusion of pam_faillock.so preauth even_deny_root parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*) line: \1required\3 even_deny_root state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_even_deny_root_parameter_is_present.found == 0 - name: Configure the root Account for Failed Password Attempts - Ensure the inclusion of pam_faillock.so authfail even_deny_root parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*) line: \1required\3 even_deny_root state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_even_deny_root_parameter_is_present.found == 0 when: - '"pam" in ansible_facts.packages' - not result_faillock_conf_check.stat.exists tags: - CCE-80668-7 - DISA-STIG-RHEL-08-020023 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(c) - accounts_passwords_pam_faillock_deny_root - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - 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: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Remediation where authselect tool is present block: - name: Lock Accounts Must Persist - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - Get authselect current features 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: Lock Accounts Must Persist - Ensure "with-faillock" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-faillock register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-faillock") - name: Lock Accounts Must Persist - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Remediation where authselect tool is not present block: - name: Lock Accounts Must Persist - Check if pam_faillock.so is already enabled ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail) state: absent check_mode: true changed_when: false register: result_pam_faillock_is_enabled - name: Lock Accounts Must Persist - Enable pam_faillock.so preauth editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so preauth insertbefore: ^auth.*sufficient.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Lock Accounts Must Persist - Enable pam_faillock.so authfail editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so authfail insertbefore: ^auth.*required.*pam_deny\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Lock Accounts Must Persist - Enable pam_faillock.so account section editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: account required pam_faillock.so insertbefore: ^account.*required.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 when: - '"pam" in ansible_facts.packages' - not result_authselect_present.stat.exists tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Check the presence of /etc/security/faillock.conf file ansible.builtin.stat: path: /etc/security/faillock.conf register: result_faillock_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Ensure the pam_faillock.so dir parameter in /etc/security/faillock.conf ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: ^\s*dir\s*= line: dir = {{ var_accounts_passwords_pam_faillock_dir }} state: present when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Ensure the pam_faillock.so dir parameter not in PAM files block: - name: Lock Accounts Must Persist - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present - name: Lock Accounts Must Persist - Check the proper remediation for the system block: - name: Lock Accounts Must Persist - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Lock Accounts Must Persist - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Lock Accounts Must Persist - Ensure authselect custom profile is used if authselect is present block: - name: Lock Accounts Must Persist - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - Ensure the "dir" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bdir\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Lock Accounts Must Persist - 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: - result_pam_file_present.stat.exists - name: Lock Accounts Must Persist - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present - name: Lock Accounts Must Persist - Check the proper remediation for the system block: - name: Lock Accounts Must Persist - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Lock Accounts Must Persist - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Lock Accounts Must Persist - Ensure authselect custom profile is used if authselect is present block: - name: Lock Accounts Must Persist - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - 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: Lock Accounts Must Persist - Ensure the "dir" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bdir\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Lock Accounts Must Persist - 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: - result_pam_file_present.stat.exists when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Ensure the pam_faillock.so dir parameter in PAM files block: - name: Lock Accounts Must Persist - Check if pam_faillock.so dir parameter is already enabled in pam files ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail).*dir state: absent check_mode: true changed_when: false register: result_pam_faillock_dir_parameter_is_present - name: Lock Accounts Must Persist - Ensure the inclusion of pam_faillock.so preauth dir parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*) line: \1required\3 dir={{ var_accounts_passwords_pam_faillock_dir }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_dir_parameter_is_present.found == 0 - name: Lock Accounts Must Persist - Ensure the inclusion of pam_faillock.so authfail dir parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*) line: \1required\3 dir={{ var_accounts_passwords_pam_faillock_dir }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_dir_parameter_is_present.found == 0 - name: Lock Accounts Must Persist - Ensure the desired value for pam_faillock.so preauth dir parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(dir)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_dir }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_dir_parameter_is_present.found > 0 - name: Lock Accounts Must Persist - Ensure the desired value for pam_faillock.so authfail dir parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(dir)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_dir }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_dir_parameter_is_present.found > 0 when: - '"pam" in ansible_facts.packages' - not result_faillock_conf_check.stat.exists tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Ensure necessary SELinux packages are installed ansible.builtin.package: name: '{{ item }}' state: present with_items: - python3-libselinux - python3-policycoreutils - policycoreutils-python-utils when: '"pam" in ansible_facts.packages' tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Create the tally directory if it does not exist ansible.builtin.file: path: '{{ var_accounts_passwords_pam_faillock_dir }}' state: directory setype: faillog_t when: '"pam" in ansible_facts.packages' tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Ensure SELinux file context is permanently set ansible.builtin.command: cmd: semanage fcontext -a -t faillog_t "{{ var_accounts_passwords_pam_faillock_dir }}(/.*)?" register: result_accounts_passwords_pam_faillock_dir_semanage ignore_errors: true changed_when: - result_accounts_passwords_pam_faillock_dir_semanage.rc == 0 when: '"pam" in ansible_facts.packages' tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Lock Accounts Must Persist - Ensure SELinux file context is applied ansible.builtin.command: cmd: restorecon -R "{{ var_accounts_passwords_pam_faillock_dir }}" register: result_accounts_passwords_pam_faillock_dir_restorecon when: '"pam" in ansible_facts.packages' tags: - CCE-86067-6 - DISA-STIG-RHEL-08-020016 - DISA-STIG-RHEL-08-020017 - NIST-800-53-AC-7(a) - NIST-800-53-AC-7(b) - NIST-800-53-AC-7.1(ii) - accounts_passwords_pam_faillock_dir - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Interval For Counting Failed Password Attempts - 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: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Interval For Counting Failed Password Attempts - Remediation where authselect tool is present block: - name: Set Interval For Counting Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - Get authselect current features 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: Set Interval For Counting Failed Password Attempts - Ensure "with-faillock" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-faillock register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-faillock") - name: Set Interval For Counting Failed Password Attempts - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists tags: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Interval For Counting Failed Password Attempts - Remediation where authselect tool is not present block: - name: Set Interval For Counting Failed Password Attempts - Check if pam_faillock.so is already enabled ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail) state: absent check_mode: true changed_when: false register: result_pam_faillock_is_enabled - name: Set Interval For Counting Failed Password Attempts - Enable pam_faillock.so preauth editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so preauth insertbefore: ^auth.*sufficient.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Set Interval For Counting Failed Password Attempts - Enable pam_faillock.so authfail editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so authfail insertbefore: ^auth.*required.*pam_deny\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Set Interval For Counting Failed Password Attempts - Enable pam_faillock.so account section editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: account required pam_faillock.so insertbefore: ^account.*required.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 when: - '"pam" in ansible_facts.packages' - not result_authselect_present.stat.exists tags: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Interval For Counting Failed Password Attempts - Check the presence of /etc/security/faillock.conf file ansible.builtin.stat: path: /etc/security/faillock.conf register: result_faillock_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Interval For Counting Failed Password Attempts - Ensure the pam_faillock.so fail_interval parameter in /etc/security/faillock.conf ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: ^\s*fail_interval\s*= line: fail_interval = {{ var_accounts_passwords_pam_faillock_fail_interval }} state: present when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Interval For Counting Failed Password Attempts - Ensure the pam_faillock.so fail_interval parameter not in PAM files block: - name: Set Interval For Counting Failed Password Attempts - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present - name: Set Interval For Counting Failed Password Attempts - Check the proper remediation for the system block: - name: Set Interval For Counting Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Set Interval For Counting Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Set Interval For Counting Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Set Interval For Counting Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - Ensure the "fail_interval" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bfail_interval\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Set Interval For Counting Failed Password Attempts - 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: - result_pam_file_present.stat.exists - name: Set Interval For Counting Failed Password Attempts - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present - name: Set Interval For Counting Failed Password Attempts - Check the proper remediation for the system block: - name: Set Interval For Counting Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Set Interval For Counting Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Set Interval For Counting Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Set Interval For Counting Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - 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: Set Interval For Counting Failed Password Attempts - Ensure the "fail_interval" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bfail_interval\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Set Interval For Counting Failed Password Attempts - 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: - result_pam_file_present.stat.exists when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Interval For Counting Failed Password Attempts - Ensure the pam_faillock.so fail_interval parameter in PAM files block: - name: Set Interval For Counting Failed Password Attempts - Check if pam_faillock.so fail_interval parameter is already enabled in pam files ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail).*fail_interval state: absent check_mode: true changed_when: false register: result_pam_faillock_fail_interval_parameter_is_present - name: Set Interval For Counting Failed Password Attempts - Ensure the inclusion of pam_faillock.so preauth fail_interval parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*) line: \1required\3 fail_interval={{ var_accounts_passwords_pam_faillock_fail_interval }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_fail_interval_parameter_is_present.found == 0 - name: Set Interval For Counting Failed Password Attempts - Ensure the inclusion of pam_faillock.so authfail fail_interval parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*) line: \1required\3 fail_interval={{ var_accounts_passwords_pam_faillock_fail_interval }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_fail_interval_parameter_is_present.found == 0 - name: Set Interval For Counting Failed Password Attempts - Ensure the desired value for pam_faillock.so preauth fail_interval parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(fail_interval)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_fail_interval }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_fail_interval_parameter_is_present.found > 0 - name: Set Interval For Counting Failed Password Attempts - Ensure the desired value for pam_faillock.so authfail fail_interval parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(fail_interval)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_fail_interval }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_fail_interval_parameter_is_present.found > 0 when: - '"pam" in ansible_facts.packages' - not result_faillock_conf_check.stat.exists tags: - CCE-80669-5 - DISA-STIG-RHEL-08-020012 - DISA-STIG-RHEL-08-020013 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - accounts_passwords_pam_faillock_interval - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-87096-4 - DISA-STIG-RHEL-08-020018 - DISA-STIG-RHEL-08-020019 - accounts_passwords_pam_faillock_silent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - 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: - CCE-87096-4 - DISA-STIG-RHEL-08-020018 - DISA-STIG-RHEL-08-020019 - accounts_passwords_pam_faillock_silent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Remediation where authselect tool is present block: - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - 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: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Get authselect current features 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: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure "with-faillock" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-faillock register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-faillock") - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists tags: - CCE-87096-4 - DISA-STIG-RHEL-08-020018 - DISA-STIG-RHEL-08-020019 - accounts_passwords_pam_faillock_silent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Remediation where authselect tool is not present block: - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Check if pam_faillock.so is already enabled ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail) state: absent check_mode: true changed_when: false register: result_pam_faillock_is_enabled - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Enable pam_faillock.so preauth editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so preauth insertbefore: ^auth.*sufficient.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Enable pam_faillock.so authfail editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so authfail insertbefore: ^auth.*required.*pam_deny\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Enable pam_faillock.so account section editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: account required pam_faillock.so insertbefore: ^account.*required.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 when: - '"pam" in ansible_facts.packages' - not result_authselect_present.stat.exists tags: - CCE-87096-4 - DISA-STIG-RHEL-08-020018 - DISA-STIG-RHEL-08-020019 - accounts_passwords_pam_faillock_silent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Check the presence of /etc/security/faillock.conf file ansible.builtin.stat: path: /etc/security/faillock.conf register: result_faillock_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-87096-4 - DISA-STIG-RHEL-08-020018 - DISA-STIG-RHEL-08-020019 - accounts_passwords_pam_faillock_silent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure the pam_faillock.so silent parameter in /etc/security/faillock.conf ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: ^\s*silent line: silent state: present when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-87096-4 - DISA-STIG-RHEL-08-020018 - DISA-STIG-RHEL-08-020019 - accounts_passwords_pam_faillock_silent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure the pam_faillock.so silent parameter in PAM files block: - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure the inclusion of pam_faillock.so preauth silent parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth(:?(?!silent).)*) line: \1required\3 silent state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - '"pam" in ansible_facts.packages' - not result_faillock_conf_check.stat.exists tags: - CCE-87096-4 - DISA-STIG-RHEL-08-020018 - DISA-STIG-RHEL-08-020019 - accounts_passwords_pam_faillock_silent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Lockout Time for Failed Password Attempts - 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: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Lockout Time for Failed Password Attempts - Remediation where authselect tool is present block: - name: Set Lockout Time for Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - Get authselect current features 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: Set Lockout Time for Failed Password Attempts - Ensure "with-faillock" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-faillock register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-faillock") - name: Set Lockout Time for Failed Password Attempts - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"pam" in ansible_facts.packages' - result_authselect_present.stat.exists tags: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Lockout Time for Failed Password Attempts - Remediation where authselect tool is not present block: - name: Set Lockout Time for Failed Password Attempts - Check if pam_faillock.so is already enabled ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail) state: absent check_mode: true changed_when: false register: result_pam_faillock_is_enabled - name: Set Lockout Time for Failed Password Attempts - Enable pam_faillock.so preauth editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so preauth insertbefore: ^auth.*sufficient.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Set Lockout Time for Failed Password Attempts - Enable pam_faillock.so authfail editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: auth required pam_faillock.so authfail insertbefore: ^auth.*required.*pam_deny\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 - name: Set Lockout Time for Failed Password Attempts - Enable pam_faillock.so account section editing PAM files ansible.builtin.lineinfile: path: '{{ item }}' line: account required pam_faillock.so insertbefore: ^account.*required.*pam_unix\.so.* state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_is_enabled.found == 0 when: - '"pam" in ansible_facts.packages' - not result_authselect_present.stat.exists tags: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Lockout Time for Failed Password Attempts - Check the presence of /etc/security/faillock.conf file ansible.builtin.stat: path: /etc/security/faillock.conf register: result_faillock_conf_check when: '"pam" in ansible_facts.packages' tags: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Lockout Time for Failed Password Attempts - Ensure the pam_faillock.so unlock_time parameter in /etc/security/faillock.conf ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: ^\s*unlock_time\s*= line: unlock_time = {{ var_accounts_passwords_pam_faillock_unlock_time }} state: present when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Lockout Time for Failed Password Attempts - Ensure the pam_faillock.so unlock_time parameter not in PAM files block: - name: Set Lockout Time for Failed Password Attempts - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present - name: Set Lockout Time for Failed Password Attempts - Check the proper remediation for the system block: - name: Set Lockout Time for Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Set Lockout Time for Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Set Lockout Time for Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Set Lockout Time for Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - Ensure the "unlock_time" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bunlock_time\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Set Lockout Time for Failed Password Attempts - 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: - result_pam_file_present.stat.exists - name: Set Lockout Time for Failed Password Attempts - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present - name: Set Lockout Time for Failed Password Attempts - Check the proper remediation for the system block: - name: Set Lockout Time for Failed Password Attempts - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Set Lockout Time for Failed Password Attempts - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Set Lockout Time for Failed Password Attempts - Ensure authselect custom profile is used if authselect is present block: - name: Set Lockout Time for Failed Password Attempts - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - 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: Set Lockout Time for Failed Password Attempts - Ensure the "unlock_time" option from "pam_faillock.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*auth.*pam_faillock.so.*)\bunlock_time\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Set Lockout Time for Failed Password Attempts - 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: - result_pam_file_present.stat.exists when: - '"pam" in ansible_facts.packages' - result_faillock_conf_check.stat.exists tags: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Lockout Time for Failed Password Attempts - Ensure the pam_faillock.so unlock_time parameter in PAM files block: - name: Set Lockout Time for Failed Password Attempts - Check if pam_faillock.so unlock_time parameter is already enabled in pam files ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: .*auth.*pam_faillock\.so (preauth|authfail).*unlock_time state: absent check_mode: true changed_when: false register: result_pam_faillock_unlock_time_parameter_is_present - name: Set Lockout Time for Failed Password Attempts - Ensure the inclusion of pam_faillock.so preauth unlock_time parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*) line: \1required\3 unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_unlock_time_parameter_is_present.found == 0 - name: Set Lockout Time for Failed Password Attempts - Ensure the inclusion of pam_faillock.so authfail unlock_time parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*) line: \1required\3 unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time }} state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_unlock_time_parameter_is_present.found == 0 - name: Set Lockout Time for Failed Password Attempts - Ensure the desired value for pam_faillock.so preauth unlock_time parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(unlock_time)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_unlock_time }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_unlock_time_parameter_is_present.found > 0 - name: Set Lockout Time for Failed Password Attempts - Ensure the desired value for pam_faillock.so authfail unlock_time parameter in auth section ansible.builtin.lineinfile: path: '{{ item }}' backrefs: true regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(unlock_time)=[0-9]+(.*) line: \1required\3\4={{ var_accounts_passwords_pam_faillock_unlock_time }}\5 state: present loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - result_pam_faillock_unlock_time_parameter_is_present.found > 0 when: - '"pam" in ansible_facts.packages' - not result_faillock_conf_check.stat.exists tags: - CCE-80670-3 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020014 - DISA-STIG-RHEL-08-020015 - NIST-800-171-3.1.8 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.1.7 - PCI-DSSv4-8.3.4 - accounts_passwords_pam_faillock_unlock_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80653-9 - DISA-STIG-RHEL-08-020130 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.6 - accounts_password_pam_dcredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Ensure PAM variable dcredit is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*dcredit line: dcredit = {{ var_password_pam_dcredit }} when: '"pam" in ansible_facts.packages' tags: - CCE-80653-9 - DISA-STIG-RHEL-08-020130 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.6 - accounts_password_pam_dcredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86233-4 - DISA-STIG-RHEL-08-020300 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_dictcheck - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary Words - Ensure PAM variable dictcheck is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*dictcheck line: dictcheck = {{ var_password_pam_dictcheck }} when: '"pam" in ansible_facts.packages' tags: - CCE-86233-4 - DISA-STIG-RHEL-08-020300 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_dictcheck - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80654-7 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020170 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(b) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_difok - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters - Ensure PAM variable difok is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*difok line: difok = {{ var_password_pam_difok }} when: '"pam" in ansible_facts.packages' tags: - CCE-80654-7 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020170 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(b) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_difok - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80655-4 - DISA-STIG-RHEL-08-020120 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.6 - accounts_password_pam_lcredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters - Ensure PAM variable lcredit is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*lcredit line: lcredit = {{ var_password_pam_lcredit }} when: '"pam" in ansible_facts.packages' tags: - CCE-80655-4 - DISA-STIG-RHEL-08-020120 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.6 - accounts_password_pam_lcredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-81034-1 - DISA-STIG-RHEL-08-020140 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_maxclassrepeat - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating Characters from Same Character Class - Ensure PAM variable maxclassrepeat is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*maxclassrepeat line: maxclassrepeat = {{ var_password_pam_maxclassrepeat }} when: '"pam" in ansible_facts.packages' tags: - CCE-81034-1 - DISA-STIG-RHEL-08-020140 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_maxclassrepeat - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82066-2 - DISA-STIG-RHEL-08-020150 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_maxrepeat - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Password Maximum Consecutive Repeating Characters - Ensure PAM variable maxrepeat is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*maxrepeat line: maxrepeat = {{ var_password_pam_maxrepeat }} when: '"pam" in ansible_facts.packages' tags: - CCE-82066-2 - DISA-STIG-RHEL-08-020150 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_maxrepeat - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82046-4 - DISA-STIG-RHEL-08-020160 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_minclass - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories - Ensure PAM variable minclass is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*minclass line: minclass = {{ var_password_pam_minclass }} when: '"pam" in ansible_facts.packages' tags: - CCE-82046-4 - DISA-STIG-RHEL-08-020160 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_minclass - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80656-2 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020230 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.6 - accounts_password_pam_minlen - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure PAM variable minlen is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*minlen line: minlen = {{ var_password_pam_minlen }} when: '"pam" in ansible_facts.packages' tags: - CCE-80656-2 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020230 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.6 - accounts_password_pam_minlen - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80663-8 - DISA-STIG-RHEL-08-020280 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_ocredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters - Ensure PAM variable ocredit is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*ocredit line: ocredit = {{ var_password_pam_ocredit }} when: '"pam" in ansible_facts.packages' tags: - CCE-80663-8 - DISA-STIG-RHEL-08-020280 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - accounts_password_pam_ocredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-85877-9 - DISA-STIG-RHEL-08-020100 - accounts_password_pam_pwquality_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM password complexity module is enabled in password-auth - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present when: '"pam" in ansible_facts.packages' tags: - CCE-85877-9 - DISA-STIG-RHEL-08-020100 - accounts_password_pam_pwquality_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM password complexity module is enabled in password-auth - Check the proper remediation for the system block: - name: Ensure PAM password complexity module is enabled in password-auth - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Ensure PAM password complexity module is enabled in password-auth - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Ensure PAM password complexity module is enabled in password-auth - Ensure authselect custom profile is used if authselect is present block: - name: Ensure PAM password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - Check if expected PAM module line is present in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwquality.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: Ensure PAM password complexity module is enabled in password-auth - Include or update the PAM module line in {{ pam_file_path }} block: - name: Ensure PAM password complexity module is enabled in password-auth - Check if required PAM module line is present in {{ pam_file_path }} with different control ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_pwquality.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: Ensure PAM password complexity module is enabled in password-auth - Ensure the correct control for the required PAM module line in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_pwquality.so.*) replace: \1requisite \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: Ensure PAM password complexity module is enabled in password-auth - Ensure the required PAM module line is included in {{ pam_file_path }} ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' insertafter: ^account.*required.*pam_permit\.so line: password requisite pam_pwquality.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 password complexity module is enabled in password-auth - 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 password complexity module is enabled in password-auth - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_present.stat.exists - |- (result_pam__add is defined and result_pam__add.changed) or (result_pam__edit is defined and result_pam__edit.changed) when: - '"pam" in ansible_facts.packages' - result_pam_file_present.stat.exists tags: - CCE-85877-9 - DISA-STIG-RHEL-08-020100 - accounts_password_pam_pwquality_password_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-85872-0 - DISA-STIG-RHEL-08-020101 - accounts_password_pam_pwquality_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM password complexity module is enabled in system-auth - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present when: '"pam" in ansible_facts.packages' tags: - CCE-85872-0 - DISA-STIG-RHEL-08-020101 - accounts_password_pam_pwquality_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM password complexity module is enabled in system-auth - Check the proper remediation for the system block: - name: Ensure PAM password complexity module is enabled in system-auth - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Ensure PAM password complexity module is enabled in system-auth - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Ensure PAM password complexity module is enabled in system-auth - Ensure authselect custom profile is used if authselect is present block: - name: Ensure PAM password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - Check if expected PAM module line is present in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'requisite' | regex_escape() }}\s+pam_pwquality.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: Ensure PAM password complexity module is enabled in system-auth - Include or update the PAM module line in {{ pam_file_path }} block: - name: Ensure PAM password complexity module is enabled in system-auth - Check if required PAM module line is present in {{ pam_file_path }} with different control ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_pwquality.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: Ensure PAM password complexity module is enabled in system-auth - Ensure the correct control for the required PAM module line in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_pwquality.so.*) replace: \1requisite \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: Ensure PAM password complexity module is enabled in system-auth - Ensure the required PAM module line is included in {{ pam_file_path }} ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' insertafter: ^account.*required.*pam_permit\.so line: password requisite pam_pwquality.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 password complexity module is enabled in system-auth - 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 password complexity module is enabled in system-auth - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_present.stat.exists - |- (result_pam__add is defined and result_pam__add.changed) or (result_pam__edit is defined and result_pam__edit.changed) when: - '"pam" in ansible_facts.packages' - result_pam_file_present.stat.exists tags: - CCE-85872-0 - DISA-STIG-RHEL-08-020101 - accounts_password_pam_pwquality_system_auth - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80664-6 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020104 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - accounts_password_pam_retry - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM variable retry is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^\s*retry line: retry = {{ var_password_pam_retry }} when: '"pam" in ansible_facts.packages' tags: - CCE-80664-6 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020104 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - accounts_password_pam_retry - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present when: '"pam" in ansible_facts.packages' tags: - CCE-80664-6 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020104 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - accounts_password_pam_retry - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Check the proper remediation for the system block: - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Ensure authselect custom profile is used if authselect is present block: - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Ensure the "retry" option from "pam_pwquality.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*password.*{{ '.*' | regex_escape() }}.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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-80664-6 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020104 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - accounts_password_pam_retry - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present when: '"pam" in ansible_facts.packages' tags: - CCE-80664-6 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020104 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - accounts_password_pam_retry - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Check the proper remediation for the system block: - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Ensure authselect custom profile is used if authselect is present block: - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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 Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - Ensure the "retry" option from "pam_pwquality.so" is not present in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: (.*password.*{{ '.*' | regex_escape() }}.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*) replace: \1\2 register: result_pam_option_removal - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session - 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-80664-6 - CJIS-5.5.3 - DISA-STIG-RHEL-08-020104 - NIST-800-53-AC-7(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(4) - accounts_password_pam_retry - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80665-3 - DISA-STIG-RHEL-08-020110 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - accounts_password_pam_ucredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters - Ensure PAM variable ucredit is set accordingly ansible.builtin.lineinfile: create: true dest: /etc/security/pwquality.conf regexp: ^#?\s*ucredit line: ucredit = {{ var_password_pam_ucredit }} when: '"pam" in ansible_facts.packages' tags: - CCE-80665-3 - DISA-STIG-RHEL-08-020110 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(4) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - accounts_password_pam_ucredit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80892-3 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010110 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - PCI-DSSv4-8.3.2 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - set_password_hashing_algorithm_logindefs - name: Set Password Hashing Algorithm in /etc/login.defs lineinfile: dest: /etc/login.defs regexp: ^#?ENCRYPT_METHOD line: ENCRYPT_METHOD {{ var_password_hashing_algorithm }} state: present create: true when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-80892-3 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010110 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - PCI-DSSv4-8.3.2 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - set_password_hashing_algorithm_logindefs - name: Gather the package facts package_facts: manager: auto tags: - CCE-85945-4 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010160 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - set_password_hashing_algorithm_passwordauth - name: Set PAM's Password Hashing Algorithm - password-auth - Check if /etc/pam.d/password-auth file is present ansible.builtin.stat: path: /etc/pam.d/password-auth register: result_pam_file_present when: '"pam" in ansible_facts.packages' tags: - CCE-85945-4 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010160 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - set_password_hashing_algorithm_passwordauth - name: Set PAM's Password Hashing Algorithm - password-auth - Check the proper remediation for the system block: - name: Set PAM's Password Hashing Algorithm - password-auth - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/password-auth - name: Set PAM's Password Hashing Algorithm - password-auth - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Set PAM's Password Hashing Algorithm - password-auth - Ensure authselect custom profile is used if authselect is present block: - name: Set PAM's Password Hashing Algorithm - password-auth - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - Check if expected PAM module line is present in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: Set PAM's Password Hashing Algorithm - password-auth - Include or update the PAM module line in {{ pam_file_path }} block: - name: Set PAM's Password Hashing Algorithm - password-auth - Check if required PAM module line is present in {{ pam_file_path }} with different control ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_unix.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: Set PAM's Password Hashing Algorithm - password-auth - Ensure the correct control for the required PAM module line in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_unix.so.*) replace: \1sufficient \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: Set PAM's Password Hashing Algorithm - password-auth - Ensure the required PAM module line is included in {{ pam_file_path }} ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' line: password sufficient pam_unix.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: Set PAM's Password Hashing Algorithm - password-auth - 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: Set PAM's Password Hashing Algorithm - password-auth - Check if the required PAM module option is present in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*\ssha512\b state: absent check_mode: true changed_when: false register: result_pam_module_sha512_option_present - name: Set PAM's Password Hashing Algorithm - password-auth - Ensure the "sha512" PAM option for "pam_unix.so" is included in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' backrefs: true regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so.*) line: \1 sha512 state: present register: result_pam_sha512_add when: - result_pam_module_sha512_option_present.found == 0 - name: Set PAM's Password Hashing Algorithm - password-auth - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_present.stat.exists - |- (result_pam_sha512_add is defined and result_pam_sha512_add.changed) or (result_pam_sha512_edit is defined and result_pam_sha512_edit.changed) when: - '"pam" in ansible_facts.packages' - result_pam_file_present.stat.exists tags: - CCE-85945-4 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010160 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - set_password_hashing_algorithm_passwordauth - name: Gather the package facts package_facts: manager: auto tags: - CCE-80893-1 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010159 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - PCI-DSSv4-8.3.2 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - set_password_hashing_algorithm_systemauth - name: Set PAM's Password Hashing Algorithm - Check if /etc/pam.d/system-auth file is present ansible.builtin.stat: path: /etc/pam.d/system-auth register: result_pam_file_present when: '"pam" in ansible_facts.packages' tags: - CCE-80893-1 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010159 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - PCI-DSSv4-8.3.2 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - set_password_hashing_algorithm_systemauth - name: Set PAM's Password Hashing Algorithm - Check the proper remediation for the system block: - name: Set PAM's Password Hashing Algorithm - Define the PAM file to be edited as a local fact ansible.builtin.set_fact: pam_file_path: /etc/pam.d/system-auth - name: Set PAM's Password Hashing Algorithm - Check if system relies on authselect tool ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present - name: Set PAM's Password Hashing Algorithm - Ensure authselect custom profile is used if authselect is present block: - name: Set PAM's Password Hashing Algorithm - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - Check if expected PAM module line is present in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: Set PAM's Password Hashing Algorithm - Include or update the PAM module line in {{ pam_file_path }} block: - name: Set PAM's Password Hashing Algorithm - Check if required PAM module line is present in {{ pam_file_path }} with different control ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+.*\s+pam_unix.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: Set PAM's Password Hashing Algorithm - Ensure the correct control for the required PAM module line in {{ pam_file_path }} ansible.builtin.replace: dest: '{{ pam_file_path }}' regexp: ^(\s*password\s+).*(\bpam_unix.so.*) replace: \1sufficient \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: Set PAM's Password Hashing Algorithm - Ensure the required PAM module line is included in {{ pam_file_path }} ansible.builtin.lineinfile: dest: '{{ pam_file_path }}' line: password sufficient pam_unix.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: Set PAM's Password Hashing Algorithm - 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: Set PAM's Password Hashing Algorithm - Check if the required PAM module option is present in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' regexp: ^\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so\s*.*\ssha512\b state: absent check_mode: true changed_when: false register: result_pam_module_sha512_option_present - name: Set PAM's Password Hashing Algorithm - Ensure the "sha512" PAM option for "pam_unix.so" is included in {{ pam_file_path }} ansible.builtin.lineinfile: path: '{{ pam_file_path }}' backrefs: true regexp: ^(\s*password\s+{{ 'sufficient' | regex_escape() }}\s+pam_unix.so.*) line: \1 sha512 state: present register: result_pam_sha512_add when: - result_pam_module_sha512_option_present.found == 0 - name: Set PAM's Password Hashing Algorithm - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_present.stat.exists - |- (result_pam_sha512_add is defined and result_pam_sha512_add.changed) or (result_pam_sha512_edit is defined and result_pam_sha512_edit.changed) when: - '"pam" in ansible_facts.packages' - result_pam_file_present.stat.exists tags: - CCE-80893-1 - CJIS-5.6.2.2 - DISA-STIG-RHEL-08-010159 - NIST-800-171-3.13.11 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.1 - PCI-DSSv4-8.3.2 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - set_password_hashing_algorithm_systemauth - name: Set Password Hashing Rounds in /etc/login.defs - Ensure SHA_CRYPT_MIN_ROUNDS has Minimum Value of 5000 ansible.builtin.replace: path: /etc/login.defs regexp: (^\s*SHA_CRYPT_MIN_ROUNDS\s+)(?!(?:[5-9]\d{3,}|\d{5,}))\S*(\s*$) replace: \g<1>5000\g<2> backup: false tags: - CCE-89707-4 - DISA-STIG-RHEL-08-010130 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - set_password_hashing_min_rounds_logindefs - name: Set Password Hashing Rounds in /etc/login.defs - Ensure SHA_CRYPT_MAX_ROUNDS has Minimum Value of 5000 ansible.builtin.replace: path: /etc/login.defs regexp: (^\s*SHA_CRYPT_MAX_ROUNDS\s+)(?!(?:[5-9]\d{3,}|\d{5,}))\S*(\s*$) replace: \g<1>5000\g<2> backup: false tags: - CCE-89707-4 - DISA-STIG-RHEL-08-010130 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - set_password_hashing_min_rounds_logindefs - name: Block Disable service debug-shell block: - name: Disable service debug-shell block: - name: Disable service debug-shell systemd: name: debug-shell.service enabled: 'no' state: stopped masked: 'yes' rescue: - name: Intentionally ignored previous 'Disable service debug-shell' failure, service was already disabled meta: noop when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80876-6 - DISA-STIG-RHEL-08-040180 - NIST-800-171-3.4.5 - NIST-800-53-CM-6 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_debug-shell_disabled - name: Unit Socket Exists - debug-shell.socket command: systemctl -q list-unit-files debug-shell.socket register: socket_file_exists changed_when: false failed_when: socket_file_exists.rc not in [0, 1] check_mode: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80876-6 - DISA-STIG-RHEL-08-040180 - NIST-800-171-3.4.5 - NIST-800-53-CM-6 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_debug-shell_disabled - name: Disable socket debug-shell systemd: name: debug-shell.socket enabled: 'no' state: stopped masked: 'yes' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - socket_file_exists.stdout_lines is search("debug-shell.socket",multiline=True) tags: - CCE-80876-6 - DISA-STIG-RHEL-08-040180 - NIST-800-171-3.4.5 - NIST-800-53-CM-6 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_debug-shell_disabled - name: Gather the package facts package_facts: manager: auto tags: - CCE-80784-2 - DISA-STIG-RHEL-08-040172 - NIST-800-171-3.4.5 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(a) - disable_ctrlaltdel_burstaction - disable_strategy - high_severity - low_complexity - low_disruption - no_reboot_needed - name: Disable Ctrl-Alt-Del Burst Action lineinfile: dest: /etc/systemd/system.conf state: present regexp: ^CtrlAltDelBurstAction line: CtrlAltDelBurstAction=none create: true when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"systemd" in ansible_facts.packages' tags: - CCE-80784-2 - DISA-STIG-RHEL-08-040172 - NIST-800-171-3.4.5 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(a) - disable_ctrlaltdel_burstaction - disable_strategy - high_severity - low_complexity - low_disruption - no_reboot_needed - name: Disable Ctrl-Alt-Del Reboot Activation systemd: name: ctrl-alt-del.target force: true masked: true state: stopped when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80785-9 - DISA-STIG-RHEL-08-040170 - NIST-800-171-3.4.5 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - disable_ctrlaltdel_reboot - disable_strategy - high_severity - low_complexity - low_disruption - no_reboot_needed - name: Set 'StopIdleSessionSec' to '{{ var_logind_session_timeout }}' in the [Login] section of '/etc/systemd/logind.conf' ini_file: path: /etc/systemd/logind.conf section: Login option: StopIdleSessionSec value: '{{ var_logind_session_timeout }}' create: true mode: 420 when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.7', '>=') and ansible_distribution == 'RedHat' and ansible_distribution_version is version('9.0', '!=') ) or ansible_distribution == 'OracleLinux' and ansible_distribution_version is version('8.7', '>=') tags: - CCE-90784-0 - CJIS-5.5.6 - DISA-STIG-RHEL-08-020035 - NIST-800-171-3.1.11 - NIST-800-53-AC-12 - NIST-800-53-AC-17(a) - NIST-800-53-AC-17(a) - NIST-800-53-AC-2(5) - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(a) - NIST-800-53-SC-10 - PCI-DSS-Req-8.1.8 - logind_session_timeout - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Require emergency mode password lineinfile: create: true dest: /usr/lib/systemd/system/emergency.service regexp: ^#?ExecStart= line: ExecStart=-/usr/lib/systemd/systemd-sulogin-shell emergency when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82186-8 - DISA-STIG-RHEL-08-010152 - NIST-800-171-3.1.1 - NIST-800-171-3.4.5 - NIST-800-53-AC-3 - NIST-800-53-CM-6(a) - NIST-800-53-IA-2 - low_complexity - low_disruption - medium_severity - no_reboot_needed - require_emergency_target_auth - restrict_strategy - name: Require single user mode password lineinfile: create: true dest: /usr/lib/systemd/system/rescue.service regexp: ^#?ExecStart= line: ExecStart=-/usr/lib/systemd/systemd-sulogin-shell rescue when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80855-0 - DISA-STIG-RHEL-08-010151 - NIST-800-171-3.1.1 - NIST-800-171-3.4.5 - NIST-800-53-AC-3 - NIST-800-53-CM-6(a) - NIST-800-53-IA-2 - low_complexity - low_disruption - medium_severity - no_reboot_needed - require_singleuser_auth - restrict_strategy - name: Ensure tmux is installed package: name: tmux state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80644-8 - DISA-STIG-RHEL-08-020039 - NIST-800-171-3.1.10 - NIST-800-53-CM-6(a) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_tmux_installed - name: Gather the package facts package_facts: manager: auto tags: - CCE-90782-4 - DISA-STIG-RHEL-08-020041 - configure_bashrc_tmux - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: 'Support session locking with tmux (not enforcing): Determine if the Tmux launch script is present in /etc/bashrc' ansible.builtin.find: paths: /etc patterns: bashrc contains: .*case "$name" in \(sshd|login\) tmux ;; esac.* register: tmux_in_bashrc when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' tags: - CCE-90782-4 - DISA-STIG-RHEL-08-020041 - configure_bashrc_tmux - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: 'Support session locking with tmux (not enforcing): Determine if the Tmux launch script is present in /etc/profile.d/*.sh' ansible.builtin.find: paths: /etc/profile.d patterns: '*.sh' contains: .*case "$name" in \(sshd|login\) tmux ;; esac.* register: tmux_in_profile_d when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' tags: - CCE-90782-4 - DISA-STIG-RHEL-08-020041 - configure_bashrc_tmux - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: 'Support session locking with tmux (not enforcing): Insert the correct script into /etc/profile.d/tmux.sh' ansible.builtin.blockinfile: path: /etc/profile.d/tmux.sh block: | if [ "$PS1" ]; then parent=$(ps -o ppid= -p $$) name=$(ps -o comm= -p $parent) case "$name" in (sshd|login) tmux ;; esac fi create: true when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' - tmux_in_bashrc is defined and tmux_in_bashrc.matched == 0 - tmux_in_profile_d is defined and tmux_in_profile_d.matched == 0 tags: - CCE-90782-4 - DISA-STIG-RHEL-08-020041 - configure_bashrc_tmux - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-82199-1 - DISA-STIG-RHEL-08-020070 - configure_tmux_lock_after_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure tmux to lock session after inactivity block: - name: Check for duplicate values lineinfile: path: /etc/tmux.conf create: true regexp: ^\s*set -g lock-after-time\s+ mode: '0644' state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/tmux.conf lineinfile: path: /etc/tmux.conf create: true regexp: ^\s*set -g lock-after-time\s+ mode: '0644' state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/tmux.conf lineinfile: path: /etc/tmux.conf create: true regexp: ^\s*set -g lock-after-time\s+ mode: '0644' line: set -g lock-after-time 900 state: present when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' tags: - CCE-82199-1 - DISA-STIG-RHEL-08-020070 - configure_tmux_lock_after_time - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80940-0 - DISA-STIG-RHEL-08-020040 - NIST-800-53-AC-11(a) - NIST-800-53-AC-11(b) - NIST-800-53-CM-6(a) - configure_tmux_lock_command - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure the tmux Lock Command block: - name: Check for duplicate values lineinfile: path: /etc/tmux.conf create: true regexp: ^\s*set -g lock-command\s+ mode: '0644' state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/tmux.conf lineinfile: path: /etc/tmux.conf create: true regexp: ^\s*set -g lock-command\s+ mode: '0644' state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/tmux.conf lineinfile: path: /etc/tmux.conf create: true regexp: ^\s*set -g lock-command\s+ mode: '0644' line: set -g lock-command vlock state: present when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' tags: - CCE-80940-0 - DISA-STIG-RHEL-08-020040 - NIST-800-53-AC-11(a) - NIST-800-53-AC-11(b) - NIST-800-53-CM-6(a) - configure_tmux_lock_command - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86135-1 - DISA-STIG-RHEL-08-020040 - configure_strategy - configure_tmux_lock_keybinding - low_complexity - low_disruption - low_severity - no_reboot_needed - name: Check for duplicate values lineinfile: path: /etc/tmux.conf create: true regexp: \s*bind\s+\w\s+lock-session.*$ mode: '0644' state: absent check_mode: true changed_when: false register: dupes when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' tags: - CCE-86135-1 - DISA-STIG-RHEL-08-020040 - configure_strategy - configure_tmux_lock_keybinding - low_complexity - low_disruption - low_severity - no_reboot_needed - name: Deduplicate values from /etc/tmux.conf lineinfile: path: /etc/tmux.conf create: true regexp: \s*bind\s+\w\s+lock-session.*$ mode: '0644' state: absent when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' - dupes.found is defined and dupes.found > 1 tags: - CCE-86135-1 - DISA-STIG-RHEL-08-020040 - configure_strategy - configure_tmux_lock_keybinding - low_complexity - low_disruption - low_severity - no_reboot_needed - name: Insert correct line into /etc/tmux.conf lineinfile: path: /etc/tmux.conf create: true regexp: \s*bind\s+\w\s+lock-session.*$ mode: '0644' line: bind X lock-session state: present when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"tmux" in ansible_facts.packages' tags: - CCE-86135-1 - DISA-STIG-RHEL-08-020040 - configure_strategy - configure_tmux_lock_keybinding - low_complexity - low_disruption - low_severity - no_reboot_needed - name: Ensure opensc is installed package: name: opensc state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80846-9 - DISA-STIG-RHEL-08-010410 - NIST-800-53-CM-6(a) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_opensc_installed - name: Ensure openssl-pkcs11 is installed package: name: openssl-pkcs11 state: present when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture != "s390x" tags: - CCE-84029-8 - DISA-STIG-RHEL-08-010390 - NIST-800-53-CM-6(a) - PCI-DSS-Req-8.3 - enable_strategy - install_smartcard_packages - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80954-1 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020260 - NIST-800-171-3.5.6 - NIST-800-53-AC-2(3) - NIST-800-53-CM-6(a) - NIST-800-53-IA-4(e) - PCI-DSS-Req-8.1.4 - PCI-DSSv4-8.2.6 - account_disable_post_pw_expiration - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Account Expiration Following Inactivity lineinfile: create: true dest: /etc/default/useradd regexp: ^INACTIVE line: INACTIVE={{ var_account_disable_post_pw_expiration }} when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-80954-1 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020260 - NIST-800-171-3.5.6 - NIST-800-53-AC-2(3) - NIST-800-53-CM-6(a) - NIST-800-53-IA-4(e) - PCI-DSS-Req-8.1.4 - PCI-DSSv4-8.2.6 - account_disable_post_pw_expiration - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80647-1 - CJIS-5.6.2.1 - DISA-STIG-RHEL-08-020200 - NIST-800-171-3.5.6 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.4 - PCI-DSSv4-8.3.9 - accounts_maximum_age_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Password Maximum Age lineinfile: create: true dest: /etc/login.defs regexp: ^#?PASS_MAX_DAYS line: PASS_MAX_DAYS {{ var_accounts_maximum_age_login_defs }} when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-80647-1 - CJIS-5.6.2.1 - DISA-STIG-RHEL-08-020200 - NIST-800-171-3.5.6 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - PCI-DSS-Req-8.2.4 - PCI-DSSv4-8.3.9 - accounts_maximum_age_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80648-9 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020190 - NIST-800-171-3.5.8 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - accounts_minimum_age_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Password Minimum Age lineinfile: create: true dest: /etc/login.defs regexp: ^#?PASS_MIN_DAYS line: PASS_MIN_DAYS {{ var_accounts_minimum_age_login_defs }} when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-80648-9 - CJIS-5.6.2.1.1 - DISA-STIG-RHEL-08-020190 - NIST-800-171-3.5.8 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - accounts_minimum_age_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80652-1 - CJIS-5.6.2.1 - DISA-STIG-RHEL-08-020231 - NIST-800-171-3.5.7 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(f) - accounts_password_minlen_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set Password Minimum Length in login.defs lineinfile: dest: /etc/login.defs regexp: ^PASS_MIN_LEN *[0-9]* state: present line: PASS_MIN_LEN {{ var_accounts_password_minlen_login_defs }} create: true when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-80652-1 - CJIS-5.6.2.1 - DISA-STIG-RHEL-08-020231 - NIST-800-171-3.5.7 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(f) - accounts_password_minlen_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Collect users with not correct maximum time period between password changes ansible.builtin.command: cmd: awk -F':' '(/^[^:]+:[^!*]/ && ($5 > {{ var_accounts_maximum_age_login_defs }} || $5 == "")) {print $1}' /etc/shadow register: user_names tags: - CCE-82473-0 - DISA-STIG-RHEL-08-020210 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - PCI-DSSv4-8.3.9 - accounts_password_set_max_life_existing - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Change the maximum time period between password changes ansible.builtin.user: user: '{{ item }}' password_expire_max: '{{ var_accounts_maximum_age_login_defs }}' with_items: '{{ user_names.stdout_lines }}' when: user_names.stdout_lines | length > 0 tags: - CCE-82473-0 - DISA-STIG-RHEL-08-020210 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - PCI-DSSv4-8.3.9 - accounts_password_set_max_life_existing - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Collect users with not correct minimum time period between password changes command: | awk -F':' '(/^[^:]+:[^!*]/ && ($4 < {{ var_accounts_minimum_age_login_defs }} || $4 == "")) {print $1}' /etc/shadow register: user_names tags: - CCE-82472-2 - DISA-STIG-RHEL-08-020180 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - accounts_password_set_min_life_existing - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Change the minimum time period between password changes command: | chage -m {{ var_accounts_minimum_age_login_defs }} {{ item }} with_items: '{{ user_names.stdout_lines }}' when: user_names.stdout_lines | length > 0 tags: - CCE-82472-2 - DISA-STIG-RHEL-08-020180 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(d) - NIST-800-53-IA-5(f) - accounts_password_set_min_life_existing - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Prevent Login to Accounts With Empty Password - Check if system relies on authselect ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80841-0 - CJIS-5.5.2 - DISA-STIG-RHEL-08-020331 - DISA-STIG-RHEL-08-020332 - NIST-800-171-3.1.1 - NIST-800-171-3.1.5 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.1 - configure_strategy - high_severity - low_complexity - medium_disruption - no_empty_passwords - no_reboot_needed - name: Prevent Login to Accounts With Empty Password - Remediate using authselect block: - name: Prevent Login to Accounts With Empty Password - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Prevent Login to Accounts With Empty Password - 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: Prevent Login to Accounts With Empty Password - Get authselect current features 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: Prevent Login to Accounts With Empty Password - Ensure "without-nullok" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature without-nullok register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("without-nullok") - name: Prevent Login to Accounts With Empty Password - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - result_authselect_present.stat.exists tags: - CCE-80841-0 - CJIS-5.5.2 - DISA-STIG-RHEL-08-020331 - DISA-STIG-RHEL-08-020332 - NIST-800-171-3.1.1 - NIST-800-171-3.1.5 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.1 - configure_strategy - high_severity - low_complexity - medium_disruption - no_empty_passwords - no_reboot_needed - name: Prevent Login to Accounts With Empty Password - Remediate directly editing PAM files ansible.builtin.replace: dest: '{{ item }}' regexp: nullok loop: - /etc/pam.d/system-auth - /etc/pam.d/password-auth when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not result_authselect_present.stat.exists tags: - CCE-80841-0 - CJIS-5.5.2 - DISA-STIG-RHEL-08-020331 - DISA-STIG-RHEL-08-020332 - NIST-800-171-3.1.1 - NIST-800-171-3.1.5 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1)(a) - NIST-800-53-IA-5(c) - PCI-DSS-Req-8.2.3 - PCI-DSSv4-8.3.1 - configure_strategy - high_severity - low_complexity - medium_disruption - no_empty_passwords - no_reboot_needed - name: Collect users with no password command: | awk -F: '!$2 {print $1}' /etc/shadow register: users_nopasswd when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85953-8 - DISA-STIG-RHEL-08-010121 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - PCI-DSSv4-2.2.2 - high_severity - low_complexity - low_disruption - no_empty_passwords_etc_shadow - no_reboot_needed - restrict_strategy - name: Lock users with no password command: | passwd -l {{ item }} with_items: '{{ users_nopasswd.stdout_lines }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - users_nopasswd.stdout_lines | length > 0 tags: - CCE-85953-8 - DISA-STIG-RHEL-08-010121 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - PCI-DSSv4-2.2.2 - high_severity - low_complexity - low_disruption - no_empty_passwords_etc_shadow - no_reboot_needed - restrict_strategy - name: Get all /etc/passwd file entries getent: database: passwd split: ':' tags: - CCE-80649-7 - DISA-STIG-RHEL-08-040200 - NIST-800-171-3.1.1 - NIST-800-171-3.1.5 - NIST-800-53-AC-6(5) - NIST-800-53-IA-2 - NIST-800-53-IA-4(b) - PCI-DSS-Req-8.5 - PCI-DSSv4-8.2.1 - accounts_no_uid_except_zero - high_severity - low_complexity - low_disruption - no_reboot_needed - restrict_strategy - name: Lock the password of the user accounts other than root with uid 0 command: passwd -l {{ item.key }} loop: '{{ getent_passwd | dict2items | rejectattr(''key'', ''search'', ''root'') | list }}' when: item.value.1 == '0' tags: - CCE-80649-7 - DISA-STIG-RHEL-08-040200 - NIST-800-171-3.1.1 - NIST-800-171-3.1.5 - NIST-800-53-AC-6(5) - NIST-800-53-IA-2 - NIST-800-53-IA-4(b) - PCI-DSS-Req-8.5 - PCI-DSSv4-8.2.1 - accounts_no_uid_except_zero - high_severity - low_complexity - low_disruption - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-83789-8 - DISA-STIG-RHEL-08-010760 - accounts_have_homedir_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure new users receive home directories block: - name: Check for duplicate values lineinfile: path: /etc/login.defs create: true regexp: ^\s*CREATE_HOME\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/login.defs lineinfile: path: /etc/login.defs create: true regexp: ^\s*CREATE_HOME\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/login.defs lineinfile: path: /etc/login.defs create: true regexp: ^\s*CREATE_HOME\s+ line: CREATE_HOME yes state: present when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-83789-8 - DISA-STIG-RHEL-08-010760 - accounts_have_homedir_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-84037-1 - DISA-STIG-RHEL-08-020310 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - accounts_logon_fail_delay - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set accounts logon fail delay lineinfile: dest: /etc/login.defs regexp: ^FAIL_DELAY line: FAIL_DELAY {{ var_accounts_fail_delay }} create: true when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-84037-1 - DISA-STIG-RHEL-08-020310 - NIST-800-53-AC-7(b) - NIST-800-53-CM-6(a) - accounts_logon_fail_delay - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80955-8 - CJIS-5.5.2.2 - DISA-STIG-RHEL-08-020024 - NIST-800-53-AC-10 - NIST-800-53-CM-6(a) - accounts_max_concurrent_login_sessions - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Find /etc/security/limits.d files containing maxlogins configuration find: paths: /etc/security/limits.d contains: ^[\s]*\*[\s]+(?:(?:hard)|(?:-))[\s]+maxlogins patterns: '*.conf' register: maxlogins when: '"pam" in ansible_facts.packages' tags: - CCE-80955-8 - CJIS-5.5.2.2 - DISA-STIG-RHEL-08-020024 - NIST-800-53-AC-10 - NIST-800-53-CM-6(a) - accounts_max_concurrent_login_sessions - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Limit the Number of Concurrent Login Sessions Allowed Per User in files from limits.d replace: dest: '{{ item.path }}' regexp: ^#?\*.*maxlogins.* replace: '* hard maxlogins {{ var_accounts_max_concurrent_login_sessions }}' with_items: - '{{ maxlogins.files }}' when: '"pam" in ansible_facts.packages' tags: - CCE-80955-8 - CJIS-5.5.2.2 - DISA-STIG-RHEL-08-020024 - NIST-800-53-AC-10 - NIST-800-53-CM-6(a) - accounts_max_concurrent_login_sessions - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Limit the Number of Concurrent Login Sessions Allowed Per User lineinfile: state: present dest: /etc/security/limits.conf insertbefore: ^# End of file regexp: ^#?\*.*maxlogins line: '* hard maxlogins {{ var_accounts_max_concurrent_login_sessions }}' create: true when: - '"pam" in ansible_facts.packages' - maxlogins.matched == 0 tags: - CCE-80955-8 - CJIS-5.5.2.2 - DISA-STIG-RHEL-08-020024 - NIST-800-53-AC-10 - NIST-800-53-CM-6(a) - accounts_max_concurrent_login_sessions - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Get all local users from /etc/passwd ansible.builtin.getent: database: passwd split: ':' tags: - CCE-84036-3 - DISA-STIG-RHEL-08-010720 - accounts_user_interactive_home_directory_defined - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Create local_users variable from the getent output ansible.builtin.set_fact: local_users: '{{ ansible_facts.getent_passwd|dict2items }}' tags: - CCE-84036-3 - DISA-STIG-RHEL-08-010720 - accounts_user_interactive_home_directory_defined - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure interactive users have an exclusive home directory defined ansible.builtin.user: name: '{{ item.key }}' home: /home/{{ item.key }} create_home: false loop: '{{ local_users }}' when: - item.value[2]|int >= 1000 - item.value[2]|int != 65534 - not item.value[4] | regex_search('^\/\w*\/\w{1,}') tags: - CCE-84036-3 - DISA-STIG-RHEL-08-010720 - accounts_user_interactive_home_directory_defined - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Get all local users from /etc/passwd ansible.builtin.getent: database: passwd split: ':' tags: - CCE-83424-2 - DISA-STIG-RHEL-08-010750 - accounts_user_interactive_home_directory_exists - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Create local_users variable from the getent output ansible.builtin.set_fact: local_users: '{{ ansible_facts.getent_passwd|dict2items }}' tags: - CCE-83424-2 - DISA-STIG-RHEL-08-010750 - accounts_user_interactive_home_directory_exists - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure interactive users have a home directory exists ansible.builtin.user: name: '{{ item.key }}' create_home: true loop: '{{ local_users }}' when: - item.value[2]|int >= 1000 - item.value[2]|int != 65534 tags: - CCE-83424-2 - DISA-STIG-RHEL-08-010750 - accounts_user_interactive_home_directory_exists - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Get all local users from /etc/passwd ansible.builtin.getent: database: passwd split: ':' tags: - CCE-86534-5 - DISA-STIG-RHEL-08-010741 - accounts_users_home_files_groupownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Create local_users variable from the getent output ansible.builtin.set_fact: local_users: '{{ ansible_facts.getent_passwd|dict2items }}' tags: - CCE-86534-5 - DISA-STIG-RHEL-08-010741 - accounts_users_home_files_groupownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Test for existence of home directories to avoid creating them, but only fixing ownership ansible.builtin.stat: path: '{{ item.value[4] }}' register: path_exists loop: '{{ local_users }}' when: - item.value[1]|int >= 1000 - item.value[1]|int != 65534 tags: - CCE-86534-5 - DISA-STIG-RHEL-08-010741 - accounts_users_home_files_groupownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure interactive local users are the owners of their respective home directories ansible.builtin.file: path: '{{ item.0.value[4] }}' group: '{{ item.0.value[2] }}' recurse: true loop: '{{ local_users|zip(path_exists.results)|list }}' when: item.1.stat is defined and item.1.stat.exists tags: - CCE-86534-5 - DISA-STIG-RHEL-08-010741 - accounts_users_home_files_groupownership - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Get all local users from /etc/passwd ansible.builtin.getent: database: passwd split: ':' tags: - CCE-85888-6 - DISA-STIG-RHEL-08-010731 - accounts_users_home_files_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Create local_users variable from the getent output ansible.builtin.set_fact: local_users: '{{ ansible_facts.getent_passwd|dict2items }}' tags: - CCE-85888-6 - DISA-STIG-RHEL-08-010731 - accounts_users_home_files_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Test for existence home directories to avoid creating them. ansible.builtin.stat: path: '{{ item.value[4] }}' register: path_exists loop: '{{ local_users }}' when: - item.value[1]|int >= 1000 - item.value[1]|int != 65534 tags: - CCE-85888-6 - DISA-STIG-RHEL-08-010731 - accounts_users_home_files_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure interactive local users have proper permissions on their respective home directories ansible.builtin.file: path: '{{ item.0.value[4] }}' mode: u-s,g-w-s,o=- follow: false recurse: true loop: '{{ local_users|zip(path_exists.results)|list }}' when: item.1.stat is defined and item.1.stat.exists tags: - CCE-85888-6 - DISA-STIG-RHEL-08-010731 - accounts_users_home_files_permissions - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Get all local users from /etc/passwd ansible.builtin.getent: database: passwd split: ':' tags: - CCE-83434-1 - DISA-STIG-RHEL-08-010740 - file_groupownership_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Create local_users variable from the getent output ansible.builtin.set_fact: local_users: '{{ ansible_facts.getent_passwd|dict2items }}' tags: - CCE-83434-1 - DISA-STIG-RHEL-08-010740 - file_groupownership_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Test for existence of home directories to avoid creating them, but only fixing group ownership ansible.builtin.stat: path: '{{ item.value[4] }}' register: path_exists loop: '{{ local_users }}' when: - item.value[1]|int >= 1000 - item.value[1]|int != 65534 tags: - CCE-83434-1 - DISA-STIG-RHEL-08-010740 - file_groupownership_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure interactive local users are the group-owners of their respective home directories ansible.builtin.file: path: '{{ item.0.value[4] }}' group: '{{ item.0.value[2] }}' loop: '{{ local_users|zip(path_exists.results)|list }}' when: item.1.stat is defined and item.1.stat.exists tags: - CCE-83434-1 - DISA-STIG-RHEL-08-010740 - file_groupownership_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive - Gather User Info ansible.builtin.getent: database: passwd tags: - CCE-84043-9 - DISA-STIG-RHEL-08-010770 - file_permission_user_init_files - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive - Find Init Files ansible.builtin.find: paths: '{{ item.value[4] }}' pattern: '{{ var_user_initialization_files_regex }}' hidden: true use_regex: true with_dict: '{{ ansible_facts.getent_passwd }}' when: - item.value[4] != "/sbin/nologin" - item.key not in ["nobody", "nfsnobody"] - item.value[1] | int >= 1000 register: found_init_files tags: - CCE-84043-9 - DISA-STIG-RHEL-08-010770 - file_permission_user_init_files - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive - Fix Init Files Permissions ansible.builtin.file: path: '{{ item.1.path }}' mode: u-s,g-wxs,o= loop: '{{ q(''ansible.builtin.subelements'', found_init_files.results, ''files'', {''skip_missing'': True}) }}' tags: - CCE-84043-9 - DISA-STIG-RHEL-08-010770 - file_permission_user_init_files - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Get all local users from /etc/passwd ansible.builtin.getent: database: passwd split: ':' tags: - CCE-84038-9 - DISA-STIG-RHEL-08-010730 - file_permissions_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Create local_users variable from the getent output ansible.builtin.set_fact: local_users: '{{ ansible_facts.getent_passwd|dict2items }}' tags: - CCE-84038-9 - DISA-STIG-RHEL-08-010730 - file_permissions_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Test for existence home directories to avoid creating them. ansible.builtin.stat: path: '{{ item.value[4] }}' register: path_exists loop: '{{ local_users }}' when: - item.value[1]|int >= 1000 - item.value[1]|int != 65534 tags: - CCE-84038-9 - DISA-STIG-RHEL-08-010730 - file_permissions_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure interactive local users have proper permissions on their respective home directories ansible.builtin.file: path: '{{ item.0.value[4] }}' mode: u-s,g-w-s,o=- follow: false recurse: false loop: '{{ local_users|zip(path_exists.results)|list }}' when: item.1.stat is defined and item.1.stat.exists tags: - CCE-84038-9 - DISA-STIG-RHEL-08-010730 - file_permissions_home_directories - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-81036-6 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_bashrc - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check if umask in /etc/bashrc is already set ansible.builtin.lineinfile: path: /etc/bashrc regexp: ^(\s*)umask\s+.* state: absent check_mode: true changed_when: false register: umask_replace when: '"bash" in ansible_facts.packages' tags: - CCE-81036-6 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_bashrc - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Replace user umask in /etc/bashrc ansible.builtin.replace: path: /etc/bashrc regexp: ^(\s*)umask(\s+).* replace: \g<1>umask\g<2>{{ var_accounts_user_umask }} when: - '"bash" in ansible_facts.packages' - umask_replace.found > 0 tags: - CCE-81036-6 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_bashrc - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure the Default umask is Appended Correctly ansible.builtin.lineinfile: create: true path: /etc/bashrc line: umask {{ var_accounts_user_umask }} when: - '"bash" in ansible_facts.packages' - umask_replace.found == 0 tags: - CCE-81036-6 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_bashrc - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check if umask in /etc/csh.cshrc is already set ansible.builtin.lineinfile: path: /etc/csh.cshrc regexp: ^(\s*)umask\s+.* state: absent check_mode: true changed_when: false register: umask_replace tags: - CCE-81037-4 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_csh_cshrc - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Replace user umask in /etc/csh.cshrc ansible.builtin.replace: path: /etc/csh.cshrc regexp: ^(\s*)umask(\s+).* replace: \g<1>umask\g<2>{{ var_accounts_user_umask }} when: umask_replace.found > 0 tags: - CCE-81037-4 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_csh_cshrc - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure the Default umask is Appended Correctly ansible.builtin.lineinfile: create: true path: /etc/csh.cshrc line: umask {{ var_accounts_user_umask }} when: umask_replace.found == 0 tags: - CCE-81037-4 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_csh_cshrc - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82888-9 - DISA-STIG-RHEL-08-020351 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check if UMASK is already set ansible.builtin.lineinfile: path: /etc/login.defs regexp: ^(\s*)UMASK\s+.* state: absent check_mode: true changed_when: false register: result_umask_is_set when: '"shadow-utils" in ansible_facts.packages' tags: - CCE-82888-9 - DISA-STIG-RHEL-08-020351 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Replace user UMASK in /etc/login.defs ansible.builtin.replace: path: /etc/login.defs regexp: ^(\s*)UMASK(\s+).* replace: \g<1>UMASK\g<2>{{ var_accounts_user_umask }} when: - '"shadow-utils" in ansible_facts.packages' - result_umask_is_set.found > 0 tags: - CCE-82888-9 - DISA-STIG-RHEL-08-020351 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure the Default UMASK is Appended Correctly ansible.builtin.lineinfile: create: true path: /etc/login.defs line: UMASK {{ var_accounts_user_umask }} when: - '"shadow-utils" in ansible_facts.packages' - result_umask_is_set.found == 0 tags: - CCE-82888-9 - DISA-STIG-RHEL-08-020351 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_login_defs - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure the Default Umask is Set Correctly in /etc/profile - Locate Profile Configuration Files Where umask Is Defined ansible.builtin.find: paths: - /etc/profile.d patterns: - sh.local - '*.sh' contains: ^[\s]*umask\s+\d+ register: result_profile_d_files tags: - CCE-81035-8 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_profile - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure the Default Umask is Set Correctly in /etc/profile - Replace Existing umask Value in Files From /etc/profile.d ansible.builtin.replace: path: '{{ item.path }}' regexp: ^(\s*)umask\s+\d+ replace: \1umask {{ var_accounts_user_umask }} loop: '{{ result_profile_d_files.files }}' register: result_umask_replaced_profile_d when: result_profile_d_files.matched tags: - CCE-81035-8 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_profile - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure the Default Umask is Set Correctly in /etc/profile - Ensure umask Is Set in /etc/profile if Not Already Set Elsewhere ansible.builtin.lineinfile: create: true mode: 420 path: /etc/profile line: umask {{ var_accounts_user_umask }} when: not result_profile_d_files.matched tags: - CCE-81035-8 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_profile - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure the Default Umask is Set Correctly in /etc/profile - Ensure umask Value For All Existing umask Definition in /etc/profile ansible.builtin.replace: path: /etc/profile regexp: ^(\s*)umask\s+\d+ replace: \1umask {{ var_accounts_user_umask }} register: result_umask_replaced_profile tags: - CCE-81035-8 - DISA-STIG-RHEL-08-020353 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - accounts_umask_etc_profile - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure interactive local users are the owners of their respective initialization files ansible.builtin.shell: cmd: |- for dir in $(awk -F':' '{ if ($3 >= 1000 && $3 != 65534) print $6}' /etc/passwd); do for file in $(find $dir -maxdepth 1 -type f -name ".*"); do if [ "$(basename $file)" != ".bash_history" ]; then sed -i 's/^\(\s*umask\s*\)/#\1/g' $file fi done done tags: - CCE-84044-7 - DISA-STIG-RHEL-08-020352 - accounts_umask_interactive_users - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure audit is installed package: name: audit state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81043-2 - DISA-STIG-RHEL-08-030180 - NIST-800-53-AC-7(a) - NIST-800-53-AU-12(2) - NIST-800-53-AU-14 - NIST-800-53-AU-2(a) - NIST-800-53-AU-7(1) - NIST-800-53-AU-7(2) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.1 - PCI-DSSv4-10.2.1 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_audit_installed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80872-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030181 - NIST-800-171-3.3.1 - NIST-800-171-3.3.2 - NIST-800-171-3.3.6 - NIST-800-53-AC-2(g) - NIST-800-53-AC-6(9) - NIST-800-53-AU-10 - NIST-800-53-AU-12(c) - NIST-800-53-AU-14(1) - NIST-800-53-AU-2(d) - NIST-800-53-AU-3 - NIST-800-53-CM-6(a) - NIST-800-53-SI-4(23) - PCI-DSS-Req-10.1 - PCI-DSSv4-10.2.1 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_auditd_enabled - name: Enable service auditd block: - name: Gather the package facts package_facts: manager: auto - name: Enable service auditd systemd: name: auditd enabled: 'yes' state: started masked: 'no' when: - '"audit" in ansible_facts.packages' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"audit" in ansible_facts.packages' tags: - CCE-80872-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030181 - NIST-800-171-3.3.1 - NIST-800-171-3.3.2 - NIST-800-171-3.3.6 - NIST-800-53-AC-2(g) - NIST-800-53-AC-6(9) - NIST-800-53-AU-10 - NIST-800-53-AU-12(c) - NIST-800-53-AU-14(1) - NIST-800-53-AU-2(d) - NIST-800-53-AU-3 - NIST-800-53-CM-6(a) - NIST-800-53-SI-4(23) - PCI-DSS-Req-10.1 - PCI-DSSv4-10.2.1 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_auditd_enabled - name: Gather the package facts package_facts: manager: auto tags: - CCE-80825-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030601 - NIST-800-171-3.3.1 - NIST-800-53-AC-17(1) - NIST-800-53-AU-10 - NIST-800-53-AU-14(1) - NIST-800-53-CM-6(a) - NIST-800-53-IR-5(1) - PCI-DSS-Req-10.3 - PCI-DSSv4-10.7.3 - grub2_audit_argument - low_disruption - low_severity - medium_complexity - reboot_required - restrict_strategy - name: Update grub defaults and the bootloader menu command: /sbin/grubby --update-kernel=ALL --args="audit=1" when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"grub2-common" in ansible_facts.packages' tags: - CCE-80825-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030601 - NIST-800-171-3.3.1 - NIST-800-53-AC-17(1) - NIST-800-53-AU-10 - NIST-800-53-AU-14(1) - NIST-800-53-CM-6(a) - NIST-800-53-IR-5(1) - PCI-DSS-Req-10.3 - PCI-DSSv4-10.7.3 - grub2_audit_argument - low_disruption - low_severity - medium_complexity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80943-4 - DISA-STIG-RHEL-08-030602 - NIST-800-53-CM-6(a) - PCI-DSSv4-10.7.2 - grub2_audit_backlog_limit_argument - low_disruption - low_severity - medium_complexity - reboot_required - restrict_strategy - name: Update grub defaults and the bootloader menu command: /sbin/grubby --update-kernel=ALL --args="audit_backlog_limit=8192" when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"grub2-common" in ansible_facts.packages' tags: - CCE-80943-4 - DISA-STIG-RHEL-08-030602 - NIST-800-53-CM-6(a) - PCI-DSSv4-10.7.2 - grub2_audit_backlog_limit_argument - low_disruption - low_severity - medium_complexity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80708-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030121 - NIST-800-171-3.3.1 - NIST-800-171-3.4.3 - NIST-800-53-AC-6(9) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.2 - PCI-DSSv4-10.3.2 - audit_rules_immutable - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Collect all files from /etc/audit/rules.d with .rules extension find: paths: /etc/audit/rules.d/ patterns: '*.rules' register: find_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80708-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030121 - NIST-800-171-3.3.1 - NIST-800-171-3.4.3 - NIST-800-53-AC-6(9) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.2 - PCI-DSSv4-10.3.2 - audit_rules_immutable - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Remove the -e option from all Audit config files lineinfile: path: '{{ item }}' regexp: ^\s*(?:-e)\s+.*$ state: absent loop: '{{ find_rules_d.files | map(attribute=''path'') | list + [''/etc/audit/audit.rules''] }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80708-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030121 - NIST-800-171-3.3.1 - NIST-800-171-3.4.3 - NIST-800-53-AC-6(9) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.2 - PCI-DSSv4-10.3.2 - audit_rules_immutable - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add Audit -e option into /etc/audit/rules.d/immutable.rules and /etc/audit/audit.rules lineinfile: path: '{{ item }}' create: true line: -e 2 mode: o-rwx loop: - /etc/audit/audit.rules - /etc/audit/rules.d/immutable.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80708-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030121 - NIST-800-171-3.3.1 - NIST-800-171-3.4.3 - NIST-800-53-AC-6(9) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.2 - PCI-DSSv4-10.3.2 - audit_rules_immutable - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-90783-2 - DISA-STIG-RHEL-08-030122 - audit_rules_immutable_login_uids - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: 'Configure immutable Audit login UIDs: Determine if rules are loaded by auditctl' ansible.builtin.find: paths: /usr/lib/systemd/system patterns: auditd.service contains: ^\s*ExecStartPost=-/sbin/auditctl register: auditctl_used when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-90783-2 - DISA-STIG-RHEL-08-030122 - audit_rules_immutable_login_uids - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: 'Configure immutable Audit login UIDs: Configure immutable login UIDs in /etc/audit/audit.rules' ansible.builtin.lineinfile: path: /etc/audit/audit.rules line: --loginuid-immutable regexp: ^\s*--loginuid-immutable\s*$ create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - auditctl_used is defined and auditctl_used.matched >= 1 tags: - CCE-90783-2 - DISA-STIG-RHEL-08-030122 - audit_rules_immutable_login_uids - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: 'Configure immutable Audit login UIDs: In case Augen-rules is used' block: - name: 'Configure immutable Audit login UIDs: Detect if immutable login UIDs are already defined in /etc/audit/rules.d/*.rules' ansible.builtin.find: paths: /etc/audit/rules.d patterns: '*.rules' contains: ^\s*--loginuid-immutable\s*$ register: immutable_found_in_rules_d - name: 'Configure immutable Audit login UIDs: set immutable login UIDS in /etc/audit/rules.d/immutable.rules' ansible.builtin.lineinfile: path: /etc/audit/rules.d/immutable.rules line: --loginuid-immutable regexp: ^\s*--loginuid-immutable\s*$ create: true when: immutable_found_in_rules_d is defined and immutable_found_in_rules_d.matched == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - auditctl_used is defined and auditctl_used.matched == 0 tags: - CCE-90783-2 - DISA-STIG-RHEL-08-030122 - audit_rules_immutable_login_uids - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80722-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030302 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_media_export - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit mount tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80722-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030302 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_media_export - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for mount for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - mount syscall_grouping: [] - name: Check existence of mount in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - mount syscall_grouping: [] - name: Check existence of mount in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80722-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030302 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_media_export - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for mount for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - mount syscall_grouping: [] - name: Check existence of mount in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - mount syscall_grouping: [] - name: Check existence of mount in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80722-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030302 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_media_export - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check if watch rule for /etc/sudoers already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/etc/sudoers\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key actions find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)actions$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Use /etc/audit/rules.d/actions.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/actions.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Add watch rule for /etc/sudoers in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /etc/sudoers -p wa -k actions create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check if watch rule for /etc/sudoers already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/etc/sudoers\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Add watch rule for /etc/sudoers in /etc/audit/audit.rules lineinfile: line: -w /etc/sudoers -p wa -k actions state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-90175-1 - DISA-STIG-RHEL-08-030171 - audit_rules_sudoers - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check if watch rule for /etc/sudoers.d/ already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/etc/sudoers.d/\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key actions find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)actions$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Use /etc/audit/rules.d/actions.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/actions.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Add watch rule for /etc/sudoers.d/ in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /etc/sudoers.d/ -p wa -k actions create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Check if watch rule for /etc/sudoers.d/ already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/etc/sudoers.d/\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Add watch rule for /etc/sudoers.d/ in /etc/audit/audit.rules lineinfile: line: -w /etc/sudoers.d/ -p wa -k actions state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-89497-2 - DISA-STIG-RHEL-08-030172 - audit_rules_sudoers_d - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-83556-1 - DISA-STIG-RHEL-08-030000 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(3) - NIST-800-53-AU-7(a) - NIST-800-53-AU-7(b) - NIST-800-53-AU-8(b) - NIST-800-53-CM-5(1) - PCI-DSSv4-10.2.1.2 - audit_rules_suid_privilege_function - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Service facts ansible.builtin.service_facts: null when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83556-1 - DISA-STIG-RHEL-08-030000 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(3) - NIST-800-53-AU-7(a) - NIST-800-53-AU-7(b) - NIST-800-53-AU-8(b) - NIST-800-53-CM-5(1) - PCI-DSSv4-10.2.1.2 - audit_rules_suid_privilege_function - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set suid_audit_rules fact ansible.builtin.set_fact: suid_audit_rules: - rule: -a always,exit -F arch=b32 -S execve -C gid!=egid -F egid=0 -k setgid regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32[\s]+-S[\s]+execve[\s]+-C[\s]+gid!=egid[\s]+-F[\s]+egid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$ - rule: -a always,exit -F arch=b64 -S execve -C gid!=egid -F egid=0 -k setgid regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64[\s]+-S[\s]+execve[\s]+-C[\s]+gid!=egid[\s]+-F[\s]+egid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$ - rule: -a always,exit -F arch=b32 -S execve -C uid!=euid -F euid=0 -k setuid regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32[\s]+-S[\s]+execve[\s]+-C[\s]+uid!=euid[\s]+-F[\s]+euid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$ - rule: -a always,exit -F arch=b64 -S execve -C uid!=euid -F euid=0 -k setuid regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64[\s]+-S[\s]+execve[\s]+-C[\s]+uid!=euid[\s]+-F[\s]+euid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$ when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83556-1 - DISA-STIG-RHEL-08-030000 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(3) - NIST-800-53-AU-7(a) - NIST-800-53-AU-7(b) - NIST-800-53-AU-8(b) - NIST-800-53-CM-5(1) - PCI-DSSv4-10.2.1.2 - audit_rules_suid_privilege_function - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Update /etc/audit/rules.d/privileged.rules to audit privileged functions ansible.builtin.lineinfile: path: /etc/audit/rules.d/privileged.rules line: '{{ item.rule }}' regexp: '{{ item.regex }}' create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ('"auditd.service" in ansible_facts.services' or '"augenrules.service" in ansible_facts.services') register: augenrules_audit_rules_privilege_function_update_result with_items: '{{ suid_audit_rules }}' tags: - CCE-83556-1 - DISA-STIG-RHEL-08-030000 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(3) - NIST-800-53-AU-7(a) - NIST-800-53-AU-7(b) - NIST-800-53-AU-8(b) - NIST-800-53-CM-5(1) - PCI-DSSv4-10.2.1.2 - audit_rules_suid_privilege_function - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Update Update /etc/audit/audit.rules to audit privileged functions ansible.builtin.lineinfile: path: /etc/audit/audit.rules line: '{{ item.rule }}' regexp: '{{ item.regex }}' create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ('"auditd.service" in ansible_facts.services' or '"augenrules.service" in ansible_facts.services') register: auditctl_audit_rules_privilege_function_update_result with_items: '{{ suid_audit_rules }}' tags: - CCE-83556-1 - DISA-STIG-RHEL-08-030000 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(3) - NIST-800-53-AU-7(a) - NIST-800-53-AU-7(b) - NIST-800-53-AU-8(b) - NIST-800-53-CM-5(1) - PCI-DSSv4-10.2.1.2 - audit_rules_suid_privilege_function - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Restart Auditd ansible.builtin.command: /usr/sbin/service auditd restart when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - (augenrules_audit_rules_privilege_function_update_result.changed or auditctl_audit_rules_privilege_function_update_result.changed) - ansible_facts.services["auditd.service"].state == "running" tags: - CCE-83556-1 - DISA-STIG-RHEL-08-030000 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(3) - NIST-800-53-AU-7(a) - NIST-800-53-AU-7(b) - NIST-800-53-AU-8(b) - NIST-800-53-CM-5(1) - PCI-DSSv4-10.2.1.2 - audit_rules_suid_privilege_function - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/group already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/etc/group\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/audit_rules_usergroup_modification.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/group in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /etc/group -p wa -k audit_rules_usergroup_modification create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/group already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/etc/group\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/group in /etc/audit/audit.rules lineinfile: line: -w /etc/group -p wa -k audit_rules_usergroup_modification state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-80758-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030170 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_group - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/gshadow already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/etc/gshadow\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/audit_rules_usergroup_modification.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/gshadow in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /etc/gshadow -p wa -k audit_rules_usergroup_modification create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/gshadow already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/etc/gshadow\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/gshadow in /etc/audit/audit.rules lineinfile: line: -w /etc/gshadow -p wa -k audit_rules_usergroup_modification state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-80759-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030160 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_gshadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/security/opasswd already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/etc/security/opasswd\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/audit_rules_usergroup_modification.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/security/opasswd in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/security/opasswd already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/etc/security/opasswd\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/security/opasswd in /etc/audit/audit.rules lineinfile: line: -w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-80760-2 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030140 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_opasswd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/passwd already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/etc/passwd\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/audit_rules_usergroup_modification.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/passwd in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /etc/passwd -p wa -k audit_rules_usergroup_modification create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/passwd already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/etc/passwd\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/passwd in /etc/audit/audit.rules lineinfile: line: -w /etc/passwd -p wa -k audit_rules_usergroup_modification state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-80761-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030150 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_passwd - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/shadow already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/etc/shadow\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/audit_rules_usergroup_modification.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/shadow in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /etc/shadow -p wa -k audit_rules_usergroup_modification create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /etc/shadow already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/etc/shadow\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /etc/shadow in /etc/audit/audit.rules lineinfile: line: -w /etc/shadow -p wa -k audit_rules_usergroup_modification state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-80762-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030130 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.5 - PCI-DSSv4-10.2.1.5 - audit_rules_usergroup_modification_shadow - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-88225-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030110 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.1 - configure_strategy - directory_group_ownership_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: System Audit Directories Must Be Group Owned By Root - Register Audit Configuration Text ansible.builtin.slurp: src: /etc/audit/auditd.conf register: auditd_config_slurp when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-88225-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030110 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.1 - configure_strategy - directory_group_ownership_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: System Audit Directories Must Be Group Owned By Root - Set Permissions Custom Location ansible.builtin.file: group: |- {{ auditd_config_slurp['content'] | b64decode | regex_findall(' log_group\s*=\s*(.+)') | default(['root',], boolean=True) | first }} path: |- {{ auditd_config_slurp['content'] | b64decode | regex_findall(' log_file\s*=\s*(.+)') | default(['/var/log/audit/audit.log',], boolean=True) | first | dirname }} when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-88225-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030110 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.1 - configure_strategy - directory_group_ownership_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-88226-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030100 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.1 - configure_strategy - directory_ownership_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: System Audit Directories Must Be Owned By Root - Register Audit Configuration Text ansible.builtin.slurp: src: /etc/audit/auditd.conf register: auditd_config_slurp when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-88226-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030100 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.1 - configure_strategy - directory_ownership_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: System Audit Directories Must Be Owned By Root - Set Permissions Custom Location ansible.builtin.file: owner: root path: |- {{ auditd_config_slurp['content'] | b64decode | regex_findall(' log_file\s*=\s*(.+)') | default(['/var/log/audit/audit.log',], boolean=True) | first | dirname }} when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-88226-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030100 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.1 - configure_strategy - directory_ownership_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80819-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030070 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5 - PCI-DSSv4-10.3.1 - file_permissions_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Get audit log files command: grep -iw ^log_file /etc/audit/auditd.conf failed_when: false register: log_file_exists when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80819-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030070 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5 - PCI-DSSv4-10.3.1 - file_permissions_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Parse log file line command: awk -F '=' '/^log_file/ {print $2}' /etc/audit/auditd.conf register: log_file_line when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - log_file_exists is not skipped and (log_file_exists.stdout | length > 0) tags: - CCE-80819-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030070 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5 - PCI-DSSv4-10.3.1 - file_permissions_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set default log_file if not set set_fact: log_file: /var/log/audit/audit.log when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - (log_file_exists is skipped) or (log_file_exists is undefined) or (log_file_exists.stdout | length == 0) tags: - CCE-80819-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030070 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5 - PCI-DSSv4-10.3.1 - file_permissions_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set log_file from log_file_line if not set already set_fact: log_file: '{{ log_file_line.stdout | trim }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - (log_file_exists is not skipped) and (log_file_line.stdout is defined) and (log_file_line.stdout | length > 0) tags: - CCE-80819-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030070 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5 - PCI-DSSv4-10.3.1 - file_permissions_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Apply mode to log file file: path: '{{ log_file }}' mode: 384 failed_when: false when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80819-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030070 - NIST-800-171-3.3.1 - NIST-800-53-AC-6(1) - NIST-800-53-AU-9(4) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5 - PCI-DSSv4-10.3.1 - file_permissions_var_log_audit - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80685-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit chmod tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80685-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for chmod for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - chmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of chmod in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - chmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of chmod in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80685-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for chmod for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - chmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of chmod in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - chmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of chmod in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80685-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80686-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit chown tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80686-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for chown for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - chown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of chown in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - chown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of chown in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80686-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for chown for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - chown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of chown in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - chown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of chown in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80686-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_chown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80687-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit fchmod tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80687-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchmod for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmod in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmod in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80687-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchmod for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmod in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchmod syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmod in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80687-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmod - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80688-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmodat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit fchmodat tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80688-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmodat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchmodat for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchmodat syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmodat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchmodat syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmodat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80688-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmodat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchmodat for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchmodat syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmodat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchmodat syscall_grouping: - chmod - fchmod - fchmodat - name: Check existence of fchmodat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80688-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030490 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchmodat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80689-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit fchown tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80689-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchown for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchown in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchown in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80689-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchown for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchown in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchown in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80689-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80690-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchownat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit fchownat tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80690-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchownat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchownat for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchownat syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchownat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchownat syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchownat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80690-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchownat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fchownat for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fchownat syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchownat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fchownat syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of fchownat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80690-1 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fchownat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80691-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit fremovexattr tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80691-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fremovexattr for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80691-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fremovexattr for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80691-9 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80692-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit fsetxattr tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80692-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fsetxattr for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80692-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for fsetxattr for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - fsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of fsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80692-7 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_fsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80693-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit lchown tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80693-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for lchown for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - lchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of lchown in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of lchown in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80693-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for lchown for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - lchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of lchown in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lchown syscall_grouping: - chown - fchown - fchownat - lchown - name: Check existence of lchown in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80693-5 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030480 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lchown - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80694-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit lremovexattr tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80694-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for lremovexattr for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80694-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for lremovexattr for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lremovexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lremovexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80694-3 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lremovexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80695-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit lsetxattr tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80695-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for lsetxattr for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80695-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for lsetxattr for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - lsetxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of lsetxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80695-0 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_lsetxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80696-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_removexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit removexattr tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80696-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_removexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for removexattr for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80696-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_removexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for removexattr for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - removexattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of removexattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80696-8 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_removexattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80697-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_setxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit setxattr tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80697-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_setxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for setxattr for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80697-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_setxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for setxattr for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - setxattr syscall_grouping: - fremovexattr - lremovexattr - removexattr - fsetxattr - lsetxattr - setxattr - name: Check existence of setxattr in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F key=perm_mod create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80697-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030200 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.5.5 - PCI-DSSv4-10.3.4 - audit_rules_dac_modification_setxattr - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-89446-9 - DISA-STIG-RHEL-08-030570 - audit_rules_execution_chacl - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/chacl block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-89446-9 - DISA-STIG-RHEL-08-030570 - audit_rules_execution_chacl - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-88437-9 - DISA-STIG-RHEL-08-030330 - audit_rules_execution_setfacl - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/setfacl block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-88437-9 - DISA-STIG-RHEL-08-030330 - audit_rules_execution_setfacl - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80698-4 - DISA-STIG-RHEL-08-030260 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_chcon - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/chcon block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80698-4 - DISA-STIG-RHEL-08-030260 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_chcon - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80700-8 - DISA-STIG-RHEL-08-030313 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_semanage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/semanage block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80700-8 - DISA-STIG-RHEL-08-030313 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_semanage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82280-9 - DISA-STIG-RHEL-08-030314 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_setfiles - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/setfiles block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82280-9 - DISA-STIG-RHEL-08-030314 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_setfiles - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80701-6 - DISA-STIG-RHEL-08-030316 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_setsebool - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/setsebool block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80701-6 - DISA-STIG-RHEL-08-030316 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_execution_setsebool - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80703-2 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rename - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit rename tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80703-2 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rename - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for rename for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - rename syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rename in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - rename syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rename in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80703-2 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rename - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for rename for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - rename syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rename in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - rename syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rename in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80703-2 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rename - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80704-0 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_renameat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit renameat tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80704-0 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_renameat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for renameat for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - renameat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of renameat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - renameat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of renameat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80704-0 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_renameat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for renameat for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - renameat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of renameat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - renameat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of renameat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80704-0 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_renameat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80705-7 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rmdir - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit rmdir tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80705-7 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rmdir - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for rmdir for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - rmdir syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rmdir in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - rmdir syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rmdir in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80705-7 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rmdir - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for rmdir for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - rmdir syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rmdir in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - rmdir syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of rmdir in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80705-7 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_rmdir - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80706-5 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlink - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit unlink tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80706-5 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlink - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for unlink for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - unlink syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlink in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - unlink syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlink in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80706-5 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlink - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for unlink for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - unlink syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlink in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - unlink syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlink in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80706-5 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlink - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80707-3 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlinkat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit unlinkat tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80707-3 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlinkat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for unlinkat for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - unlinkat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlinkat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - unlinkat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlinkat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80707-3 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlinkat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for unlinkat for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - unlinkat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlinkat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules set_fact: audit_file="/etc/audit/rules.d/delete.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - unlinkat syscall_grouping: - unlink - unlinkat - rename - renameat - rmdir - name: Check existence of unlinkat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=delete create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80707-3 - DISA-STIG-RHEL-08-030361 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - PCI-DSSv4-10.2.1.7 - audit_rules_file_deletion_events_unlinkat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80751-1 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_creat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit creat tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80751-1 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_creat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for creat EACCES for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80751-1 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_creat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for creat EACCES for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80751-1 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_creat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for creat EPERM for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80751-1 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_creat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for creat EPERM for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - creat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of creat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80751-1 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_creat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80752-9 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_ftruncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit ftruncate tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80752-9 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_ftruncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for ftruncate EACCES for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80752-9 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_ftruncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for ftruncate EACCES for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80752-9 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_ftruncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for ftruncate EPERM for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80752-9 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_ftruncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for ftruncate EPERM for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - ftruncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of ftruncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80752-9 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_ftruncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80753-7 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit open tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80753-7 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open EACCES for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80753-7 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open EACCES for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80753-7 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open EPERM for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) tags: - CCE-80753-7 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open EPERM for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not ( ansible_architecture == "aarch64" ) - audit_arch == "b64" tags: - CCE-80753-7 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80755-2 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open_by_handle_at - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit open_by_handle_at tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80755-2 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open_by_handle_at - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open_by_handle_at EACCES for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80755-2 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open_by_handle_at - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open_by_handle_at EACCES for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80755-2 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open_by_handle_at - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open_by_handle_at EPERM for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80755-2 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open_by_handle_at - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for open_by_handle_at EPERM for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - open_by_handle_at syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of open_by_handle_at in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80755-2 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_open_by_handle_at - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80754-5 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_openat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit openat tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80754-5 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_openat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for openat EACCES for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80754-5 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_openat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for openat EACCES for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80754-5 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_openat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for openat EPERM for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80754-5 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_openat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for openat EPERM for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - openat syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of openat in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80754-5 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_openat - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80756-0 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_truncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Set architecture for audit truncate tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80756-0 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_truncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for truncate EACCES for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80756-0 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_truncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for truncate EACCES for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80756-0 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_truncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for truncate EPERM for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80756-0 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_truncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Perform remediation of Audit rules for truncate EPERM for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules set_fact: audit_file="/etc/audit/rules.d/access.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - truncate syscall_grouping: - creat - ftruncate - truncate - open - openat - open_by_handle_at - name: Check existence of truncate in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80756-0 - DISA-STIG-RHEL-08-030420 - NIST-800-171-3.1.7 - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.1 - PCI-DSS-Req-10.2.4 - audit_rules_unsuccessful_file_modification_truncate - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80711-5 - DISA-STIG-RHEL-08-030390 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_delete - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set architecture for audit delete_module tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80711-5 - DISA-STIG-RHEL-08-030390 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_delete - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Perform remediation of Audit rules for delete_module for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - delete_module syscall_grouping: [] - name: Check existence of delete_module in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/module-change.rules set_fact: audit_file="/etc/audit/rules.d/module-change.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - delete_module syscall_grouping: [] - name: Check existence of delete_module in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80711-5 - DISA-STIG-RHEL-08-030390 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_delete - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Perform remediation of Audit rules for delete_module for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - delete_module syscall_grouping: [] - name: Check existence of delete_module in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/module-change.rules set_fact: audit_file="/etc/audit/rules.d/module-change.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - delete_module syscall_grouping: [] - name: Check existence of delete_module in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80711-5 - DISA-STIG-RHEL-08-030390 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_delete - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80712-3 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_finit - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set architecture for audit finit_module tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80712-3 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_finit - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Perform remediation of Audit rules for finit_module for x86 platform block: - name: Declare list of syscalls set_fact: syscalls: - finit_module syscall_grouping: - init_module - finit_module - name: Check existence of finit_module in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/module-change.rules set_fact: audit_file="/etc/audit/rules.d/module-change.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - finit_module syscall_grouping: - init_module - finit_module - name: Check existence of finit_module in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80712-3 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_finit - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Perform remediation of Audit rules for finit_module for x86_64 platform block: - name: Declare list of syscalls set_fact: syscalls: - finit_module syscall_grouping: - init_module - finit_module - name: Check existence of finit_module in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/module-change.rules set_fact: audit_file="/etc/audit/rules.d/module-change.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - finit_module syscall_grouping: - init_module - finit_module - name: Check existence of finit_module in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80712-3 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_finit - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80713-1 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_init - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set architecture for audit init_module tasks set_fact: audit_arch: b64 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64" tags: - CCE-80713-1 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_init - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Perform remediation of Audit rules for init_module for 32bit platform block: - name: Declare list of syscalls set_fact: syscalls: - init_module syscall_grouping: - init_module - finit_module - name: Check existence of init_module in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/module-change.rules set_fact: audit_file="/etc/audit/rules.d/module-change.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - init_module syscall_grouping: - init_module - finit_module - name: Check existence of init_module in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80713-1 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_init - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Perform remediation of Audit rules for init_module for 64bit platform block: - name: Declare list of syscalls set_fact: syscalls: - init_module syscall_grouping: - init_module - finit_module - name: Check existence of init_module in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/module-change.rules set_fact: audit_file="/etc/audit/rules.d/module-change.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: - init_module syscall_grouping: - init_module - finit_module - name: Check existence of init_module in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000 -F auid!=unset -F key=module-change create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - audit_arch == "b64" tags: - CCE-80713-1 - DISA-STIG-RHEL-08-030360 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.7 - audit_rules_kernel_module_loading_init - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for {{ var_accounts_passwords_pam_faillock_dir }} already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+{{ var_accounts_passwords_pam_faillock_dir }}\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key logins find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)logins$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use /etc/audit/rules.d/logins.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/logins.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for {{ var_accounts_passwords_pam_faillock_dir }} in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w {{ var_accounts_passwords_pam_faillock_dir }} -p wa -k logins create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for {{ var_accounts_passwords_pam_faillock_dir }} already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+{{ var_accounts_passwords_pam_faillock_dir }}\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for {{ var_accounts_passwords_pam_faillock_dir }} in /etc/audit/audit.rules lineinfile: line: -w {{ var_accounts_passwords_pam_faillock_dir }} -p wa -k logins state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-80718-0 - DISA-STIG-RHEL-08-030590 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_faillock - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /var/log/lastlog already exists in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: ^\s*-w\s+/var/log/lastlog\s+-p\s+wa(\s|$)+ patterns: '*.rules' register: find_existing_watch_rules_d when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Search /etc/audit/rules.d for other rules with specified key logins find: paths: /etc/audit/rules.d contains: ^.*(?:-F key=|-k\s+)logins$ patterns: '*.rules' register: find_watch_key when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use /etc/audit/rules.d/logins.rules as the recipient for the rule set_fact: all_files: - /etc/audit/rules.d/logins.rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Use matched file as the recipient for the rule set_fact: all_files: - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /var/log/lastlog in /etc/audit/rules.d/ lineinfile: path: '{{ all_files[0] }}' line: -w /var/log/lastlog -p wa -k logins create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched == 0 tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Check if watch rule for /var/log/lastlog already exists in /etc/audit/audit.rules find: paths: /etc/audit/ contains: ^\s*-w\s+/var/log/lastlog\s+-p\s+wa(\s|$)+ patterns: audit.rules register: find_existing_watch_audit_rules when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Add watch rule for /var/log/lastlog in /etc/audit/audit.rules lineinfile: line: -w /var/log/lastlog -p wa -k logins state: present dest: /etc/audit/audit.rules create: true mode: '0640' when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched == 0 tags: - CCE-80719-8 - DISA-STIG-RHEL-08-030600 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.2.3 - PCI-DSSv4-10.2.1.3 - audit_rules_login_events_lastlog - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80725-5 - DISA-STIG-RHEL-08-030250 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_chage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/chage block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80725-5 - DISA-STIG-RHEL-08-030250 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_chage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80726-3 - DISA-STIG-RHEL-08-030410 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_chsh - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/chsh block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80726-3 - DISA-STIG-RHEL-08-030410 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_chsh - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80727-1 - DISA-STIG-RHEL-08-030400 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_crontab - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/crontab block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80727-1 - DISA-STIG-RHEL-08-030400 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_crontab - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80728-9 - DISA-STIG-RHEL-08-030370 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_gpasswd - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/gpasswd block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80728-9 - DISA-STIG-RHEL-08-030370 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_gpasswd - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-89455-0 - DISA-STIG-RHEL-08-030580 - NIST-800-53-AU-12(a) - NIST-800-53-AU-12.1(ii) - NIST-800-53-AU-12.1(iv)AU-12(c) - NIST-800-53-AU-3 - NIST-800-53-AU-3.1 - NIST-800-53-MA-4(1)(a) - audit_rules_privileged_commands_kmod - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/kmod block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-89455-0 - DISA-STIG-RHEL-08-030580 - NIST-800-53-AU-12(a) - NIST-800-53-AU-12.1(ii) - NIST-800-53-AU-12.1(iv)AU-12(c) - NIST-800-53-AU-3 - NIST-800-53-AU-3.1 - NIST-800-53-MA-4(1)(a) - audit_rules_privileged_commands_kmod - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80989-7 - DISA-STIG-RHEL-08-030300 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_mount - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/mount block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80989-7 - DISA-STIG-RHEL-08-030300 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_mount - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80729-7 - DISA-STIG-RHEL-08-030350 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_newgrp - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/newgrp block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80729-7 - DISA-STIG-RHEL-08-030350 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_newgrp - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80730-5 - DISA-STIG-RHEL-08-030340 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_pam_timestamp_check - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/pam_timestamp_check block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80730-5 - DISA-STIG-RHEL-08-030340 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_pam_timestamp_check - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80731-3 - DISA-STIG-RHEL-08-030290 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_passwd - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/passwd block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80731-3 - DISA-STIG-RHEL-08-030290 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_passwd - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80732-1 - DISA-STIG-RHEL-08-030311 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_postdrop - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/postdrop block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80732-1 - DISA-STIG-RHEL-08-030311 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_postdrop - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80733-9 - DISA-STIG-RHEL-08-030312 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_postqueue - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/postqueue block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80733-9 - DISA-STIG-RHEL-08-030312 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_postqueue - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-85944-7 - DISA-STIG-RHEL-08-030280 - audit_rules_privileged_commands_ssh_agent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/ssh-agent block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85944-7 - DISA-STIG-RHEL-08-030280 - audit_rules_privileged_commands_ssh_agent - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80735-4 - DISA-STIG-RHEL-08-030320 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_ssh_keysign - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/libexec/openssh/ssh-keysign block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80735-4 - DISA-STIG-RHEL-08-030320 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_ssh_keysign - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80736-2 - DISA-STIG-RHEL-08-030190 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_su - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/su block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80736-2 - DISA-STIG-RHEL-08-030190 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_su - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80737-0 - DISA-STIG-RHEL-08-030550 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_sudo - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/sudo block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80737-0 - DISA-STIG-RHEL-08-030550 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_sudo - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80739-6 - DISA-STIG-RHEL-08-030301 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_umount - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/bin/umount block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80739-6 - DISA-STIG-RHEL-08-030301 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_umount - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80740-4 - DISA-STIG-RHEL-08-030317 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(a) - NIST-800-53-AU-12(c) - NIST-800-53-AU-12.1(ii) - NIST-800-53-AU-12.1(iv) - NIST-800-53-AU-2(d) - NIST-800-53-AU-3 - NIST-800-53-AU-3.1 - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(1)(a) - audit_rules_privileged_commands_unix_chkpwd - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/unix_chkpwd block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80740-4 - DISA-STIG-RHEL-08-030317 - NIST-800-171-3.1.7 - NIST-800-53-AC-2(4) - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(a) - NIST-800-53-AU-12(c) - NIST-800-53-AU-12.1(ii) - NIST-800-53-AU-12.1(iv) - NIST-800-53-AU-2(d) - NIST-800-53-AU-3 - NIST-800-53-AU-3.1 - NIST-800-53-CM-6(a) - NIST-800-53-MA-4(1)(a) - audit_rules_privileged_commands_unix_chkpwd - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-89480-8 - DISA-STIG-RHEL-08-030310 - audit_rules_privileged_commands_unix_update - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/unix_update block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-89480-8 - DISA-STIG-RHEL-08-030310 - audit_rules_privileged_commands_unix_update - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80741-2 - DISA-STIG-RHEL-08-030315 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_userhelper - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/userhelper block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80741-2 - DISA-STIG-RHEL-08-030315 - NIST-800-171-3.1.7 - NIST-800-53-AC-6(9) - NIST-800-53-AU-12(c) - NIST-800-53-AU-2(d) - NIST-800-53-CM-6(a) - audit_rules_privileged_commands_userhelper - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86027-0 - DISA-STIG-RHEL-08-030560 - audit_rules_privileged_commands_usermod - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Perform remediation of Audit rules for /usr/sbin/usermod block: - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/rules.d/ find: paths: /etc/audit/rules.d contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: '*.rules' register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Reset syscalls found per file set_fact: syscalls_per_file: {} found_paths_dict: {} - name: Declare syscalls found per file set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}" loop: '{{ find_command.results | selectattr(''matched'') | list }}' - name: Declare files where syscalls were found set_fact: found_paths="{{ find_command.results | map(attribute='files') | flatten | map(attribute='path') | list }}" - name: Count occurrences of syscalls in paths set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item, 0) }) }}" loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'') | list }}' - name: Get path with most syscalls set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value') | last).key }}" when: found_paths | length >= 1 - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules set_fact: audit_file="/etc/audit/rules.d/privileged.rules" when: found_paths | length == 0 - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file] | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 - name: Declare list of syscalls set_fact: syscalls: [] syscall_grouping: [] - name: Check existence of in /etc/audit/audit.rules find: paths: /etc/audit contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)* -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$ patterns: audit.rules register: find_command loop: '{{ (syscall_grouping + syscalls) | unique }}' - name: Set path to /etc/audit/audit.rules set_fact: audit_file="/etc/audit/audit.rules" - name: Declare found syscalls set_fact: syscalls_found="{{ find_command.results | selectattr('matched') | map(attribute='item') | list }}" - name: Declare missing syscalls set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found) }}" - name: Replace the audit rule in {{ audit_file }} lineinfile: path: '{{ audit_file }}' regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+) line: \1\2\3{{ missing_syscalls | join("\3") }}\4 backrefs: true state: present when: syscalls_found | length > 0 and missing_syscalls | length > 0 - name: Add the audit rule to {{ audit_file }} lineinfile: path: '{{ audit_file }}' line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged create: true mode: o-rwx state: present when: syscalls_found | length == 0 when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86027-0 - DISA-STIG-RHEL-08-030560 - audit_rules_privileged_commands_usermod - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-84046-2 - DISA-STIG-RHEL-08-030040 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - auditd_data_disk_error_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure auditd Disk Error Action on Disk Error lineinfile: dest: /etc/audit/auditd.conf line: disk_error_action = {{ var_auditd_disk_error_action.split('|')[0] }} regexp: ^\s*disk_error_action\s*=\s*.*$ state: present create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84046-2 - DISA-STIG-RHEL-08-030040 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - auditd_data_disk_error_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-84045-4 - DISA-STIG-RHEL-08-030060 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - auditd_data_disk_full_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure auditd Disk Full Action when Disk Space Is Full lineinfile: dest: /etc/audit/auditd.conf line: disk_full_action = {{ var_auditd_disk_full_action.split('|')[0] }} regexp: ^\s*disk_full_action\s*=\s*.*$ state: present create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84045-4 - DISA-STIG-RHEL-08-030060 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - auditd_data_disk_full_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80678-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030020 - NIST-800-171-3.3.1 - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1) - PCI-DSS-Req-10.7.a - auditd_data_retention_action_mail_acct - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure auditd mail_acct Action on Low Disk Space lineinfile: dest: /etc/audit/auditd.conf line: action_mail_acct = {{ var_auditd_action_mail_acct }} state: present create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80678-6 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030020 - NIST-800-171-3.3.1 - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(a) - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(1) - PCI-DSS-Req-10.7.a - auditd_data_retention_action_mail_acct - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80684-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030731 - NIST-800-171-3.3.1 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.7 - PCI-DSSv4-10.5.1 - auditd_data_retention_space_left_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure auditd space_left Action on Low Disk Space lineinfile: dest: /etc/audit/auditd.conf line: space_left_action = {{ var_auditd_space_left_action.split('|')[0] }} regexp: ^\s*space_left_action\s*=\s*.*$ state: present create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80684-4 - CJIS-5.4.1.1 - DISA-STIG-RHEL-08-030731 - NIST-800-171-3.3.1 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.7 - PCI-DSSv4-10.5.1 - auditd_data_retention_space_left_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86055-1 - DISA-STIG-RHEL-08-030730 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.7 - auditd_data_retention_space_left_percentage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure auditd space_left on Low Disk Space lineinfile: dest: /etc/audit/auditd.conf line: space_left = {{ var_auditd_space_left_percentage }}% regexp: ^\s*space_left\s*=\s*.*$ state: present create: true when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86055-1 - DISA-STIG-RHEL-08-030730 - NIST-800-53-AU-5(1) - NIST-800-53-AU-5(2) - NIST-800-53-AU-5(4) - NIST-800-53-AU-5(b) - NIST-800-53-CM-6(a) - PCI-DSS-Req-10.7 - auditd_data_retention_space_left_percentage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82233-8 - DISA-STIG-RHEL-08-030061 - NIST-800-53-CM-6 - auditd_local_events - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Include Local Events in Audit Logs block: - name: Check for duplicate values lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*local_events\s*=\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*local_events\s*=\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*local_events\s*=\s* line: local_events = yes state: present when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82233-8 - DISA-STIG-RHEL-08-030061 - NIST-800-53-CM-6 - auditd_local_events - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82201-5 - DISA-STIG-RHEL-08-030063 - NIST-800-53-AU-3 - NIST-800-53-CM-6 - auditd_log_format - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Resolve information before writing to audit logs block: - name: Check for duplicate values lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*log_format\s*=\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*log_format\s*=\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*log_format\s*=\s* line: log_format = ENRICHED state: present when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82201-5 - DISA-STIG-RHEL-08-030063 - NIST-800-53-AU-3 - NIST-800-53-CM-6 - auditd_log_format - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82897-0 - DISA-STIG-RHEL-08-030062 - NIST-800-53-AU-3 - NIST-800-53-CM-6 - auditd_name_format - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set type of computer node name logging in audit logs - Define Value to Be Used in the Remediation ansible.builtin.set_fact: auditd_name_format_split="{{ var_auditd_name_format.split('|')[0] }}" when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82897-0 - DISA-STIG-RHEL-08-030062 - NIST-800-53-AU-3 - NIST-800-53-CM-6 - auditd_name_format - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set type of computer node name logging in audit logs block: - name: Check for duplicate values lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*name_format\s*=\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*name_format\s*=\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*name_format\s*=\s* line: name_format = {{ auditd_name_format_split }} state: present when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82897-0 - DISA-STIG-RHEL-08-030062 - NIST-800-53-AU-3 - NIST-800-53-CM-6 - auditd_name_format - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-85889-4 - DISA-STIG-RHEL-08-030700 - NIST-800-53-AU-4(1) - auditd_overflow_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Appropriate Action Must be Setup When the Internal Audit Event Queue is Full block: - name: Check for duplicate values lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*overflow_action\s*=\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*overflow_action\s*=\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/audit/auditd.conf lineinfile: path: /etc/audit/auditd.conf create: true regexp: (?i)^\s*overflow_action\s*=\s* line: overflow_action = syslog state: present when: - '"audit" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85889-4 - DISA-STIG-RHEL-08-030700 - NIST-800-53-AU-4(1) - auditd_overflow_action - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82194-2 - DISA-STIG-RHEL-08-040004 - NIST-800-53-SI-16 - grub2_pti_argument - low_disruption - low_severity - medium_complexity - reboot_required - restrict_strategy - name: Update grub defaults and the bootloader menu command: /sbin/grubby --update-kernel=ALL --args="pti=on" when: - '"grub2-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82194-2 - DISA-STIG-RHEL-08-040004 - NIST-800-53-SI-16 - grub2_pti_argument - low_disruption - low_severity - medium_complexity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80946-7 - DISA-STIG-RHEL-08-010422 - NIST-800-53-CM-7(a) - grub2_vsyscall_argument - low_disruption - medium_complexity - medium_severity - reboot_required - restrict_strategy - name: Update grub defaults and the bootloader menu command: /sbin/grubby --update-kernel=ALL --args="vsyscall=none" when: - '"grub2-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80946-7 - DISA-STIG-RHEL-08-010422 - NIST-800-53-CM-7(a) - grub2_vsyscall_argument - low_disruption - medium_complexity - medium_severity - reboot_required - restrict_strategy - name: Ensure rsyslog-gnutls is installed package: name: rsyslog-gnutls state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82859-0 - DISA-STIG-RHEL-08-030680 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_rsyslog-gnutls_installed - name: Ensure rsyslog is installed package: name: rsyslog state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80847-7 - DISA-STIG-RHEL-08-030670 - NIST-800-53-CM-6(a) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_rsyslog_installed - name: Enable service rsyslog block: - name: Gather the package facts package_facts: manager: auto - name: Enable service rsyslog systemd: name: rsyslog enabled: 'yes' state: started masked: 'no' when: - '"rsyslog" in ansible_facts.packages' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80886-5 - DISA-STIG-RHEL-08-010561 - NIST-800-53-AU-4(1) - NIST-800-53-CM-6(a) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_rsyslog_enabled - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records block: - name: Deduplicate values from /etc/rsyslog.conf lineinfile: path: /etc/rsyslog.conf create: false regexp: ^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s state: absent - name: Check if /etc/rsyslog.d exists stat: path: /etc/rsyslog.d register: _etc_rsyslog_d_exists - name: Check if the parameter $ActionSendStreamDriverAuthMode is present in /etc/rsyslog.d find: paths: /etc/rsyslog.d recurse: 'yes' follow: 'no' contains: ^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s register: _etc_rsyslog_d_has_parameter when: _etc_rsyslog_d_exists.stat.isdir is defined and _etc_rsyslog_d_exists.stat.isdir - name: Remove parameter from files in /etc/rsyslog.d lineinfile: path: '{{ item.path }}' create: false regexp: ^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s state: absent with_items: '{{ _etc_rsyslog_d_has_parameter.files }}' when: _etc_rsyslog_d_has_parameter.matched - name: Insert correct line to /etc/rsyslog.conf lineinfile: path: /etc/rsyslog.conf create: true regexp: ^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s line: $ActionSendStreamDriverAuthMode x509/name state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86339-9 - DISA-STIG-RHEL-08-030720 - NIST-800-53-AU-4(1) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - rsyslog_encrypt_offload_actionsendstreamdriverauthmode - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records block: - name: Deduplicate values from /etc/rsyslog.conf lineinfile: path: /etc/rsyslog.conf create: false regexp: '^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} ' state: absent - name: Check if /etc/rsyslog.d exists stat: path: /etc/rsyslog.d register: _etc_rsyslog_d_exists - name: Check if the parameter $ActionSendStreamDriverMode is present in /etc/rsyslog.d find: paths: /etc/rsyslog.d recurse: 'yes' follow: 'no' contains: '^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} ' register: _etc_rsyslog_d_has_parameter when: _etc_rsyslog_d_exists.stat.isdir is defined and _etc_rsyslog_d_exists.stat.isdir - name: Remove parameter from files in /etc/rsyslog.d lineinfile: path: '{{ item.path }}' create: false regexp: '^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} ' state: absent with_items: '{{ _etc_rsyslog_d_has_parameter.files }}' when: _etc_rsyslog_d_has_parameter.matched - name: Insert correct line to /etc/rsyslog.conf lineinfile: path: /etc/rsyslog.conf create: true regexp: '^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} ' line: $ActionSendStreamDriverMode 1 state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86098-1 - DISA-STIG-RHEL-08-030710 - NIST-800-53-AU-4(1) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - rsyslog_encrypt_offload_actionsendstreamdrivermode - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records block: - name: Deduplicate values from /etc/rsyslog.conf lineinfile: path: /etc/rsyslog.conf create: false regexp: '^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} ' state: absent - name: Check if /etc/rsyslog.d exists stat: path: /etc/rsyslog.d register: _etc_rsyslog_d_exists - name: Check if the parameter $DefaultNetstreamDriver is present in /etc/rsyslog.d find: paths: /etc/rsyslog.d recurse: 'yes' follow: 'no' contains: '^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} ' register: _etc_rsyslog_d_has_parameter when: _etc_rsyslog_d_exists.stat.isdir is defined and _etc_rsyslog_d_exists.stat.isdir - name: Remove parameter from files in /etc/rsyslog.d lineinfile: path: '{{ item.path }}' create: false regexp: '^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} ' state: absent with_items: '{{ _etc_rsyslog_d_has_parameter.files }}' when: _etc_rsyslog_d_has_parameter.matched - name: Insert correct line to /etc/rsyslog.conf lineinfile: path: /etc/rsyslog.conf create: true regexp: '^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} ' line: $DefaultNetstreamDriver gtls state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85992-6 - DISA-STIG-RHEL-08-030710 - NIST-800-53-AU-4(1) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - rsyslog_encrypt_offload_defaultnetstreamdriver - name: 'Ensure remote access methods are monitored in Rsyslog: Set facts' set_fact: conf_files: - /etc/rsyslog.conf remote_methods: - selector: auth.* regexp: ^.*auth\.\*.*$ - selector: authpriv.* regexp: ^.*authpriv\.\*.*$ - selector: daemon.* regexp: ^.*daemon\.\*.*$ when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83426-7 - DISA-STIG-RHEL-08-010070 - NIST-800-53-AC-17(1) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - rsyslog_remote_access_monitoring - name: 'Ensure remote access methods are monitored in Rsyslog: Ensure rsyslog.conf exists' file: path: '{{ conf_files.0 }}' state: touch when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83426-7 - DISA-STIG-RHEL-08-010070 - NIST-800-53-AC-17(1) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - rsyslog_remote_access_monitoring - name: 'Ensure remote access methods are monitored in Rsyslog: Gather conf.d files' find: patterns: - '*.conf' paths: - /etc/rsyslog.d register: rsyslogd when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83426-7 - DISA-STIG-RHEL-08-010070 - NIST-800-53-AC-17(1) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - rsyslog_remote_access_monitoring - name: 'Ensure remote access methods are monitored in Rsyslog: Set conf file(s)' set_fact: conf_files: '{{ conf_files + [item.path] }}' loop: '{{ rsyslogd.files }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - rsyslogd.matched > 0 tags: - CCE-83426-7 - DISA-STIG-RHEL-08-010070 - NIST-800-53-AC-17(1) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - rsyslog_remote_access_monitoring - name: 'Ensure remote access methods are monitored in Rsyslog: Check for existing values' lineinfile: path: '{{ item.1 }}' regexp: '{{ item.0.regexp }}' state: absent check_mode: true changed_when: false register: remote_method_values loop: '{{ remote_methods|product(conf_files)|list }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83426-7 - DISA-STIG-RHEL-08-010070 - NIST-800-53-AC-17(1) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - rsyslog_remote_access_monitoring - name: 'Ensure remote access methods are monitored in Rsyslog: Configure' lineinfile: path: /etc/rsyslog.conf line: '{{ item.item.0.selector }} /var/log/secure' insertafter: ^.*\/var\/log\/secure.*$ create: true loop: '{{ remote_method_values.results }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - item.found == 0 tags: - CCE-83426-7 - DISA-STIG-RHEL-08-010070 - NIST-800-53-AC-17(1) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - rsyslog_remote_access_monitoring - name: Set rsyslog remote loghost lineinfile: dest: /etc/rsyslog.conf regexp: ^\*\.\* line: '*.* @@{{ rsyslog_remote_loghost_address }}' create: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80863-4 - DISA-STIG-RHEL-08-030690 - NIST-800-53-AU-4(1) - NIST-800-53-AU-9(2) - NIST-800-53-CM-6(a) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - rsyslog_remote_loghost - name: Ensure System is Not Acting as a Network Sniffer - Gather network interfaces ansible.builtin.command: cmd: ip link show register: network_interfaces when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82283-3 - DISA-STIG-RHEL-08-040330 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(2) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MA-3 - PCI-DSSv4-1.4.5 - low_complexity - low_disruption - medium_severity - network_sniffer_disabled - no_reboot_needed - restrict_strategy - name: Ensure System is Not Acting as a Network Sniffer - Disable promiscuous mode ansible.builtin.command: cmd: ip link set dev {{ item.split(':')[1] }} multicast off promisc off loop: '{{ network_interfaces.stdout_lines }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - item.split(':') | length == 3 tags: - CCE-82283-3 - DISA-STIG-RHEL-08-040330 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(2) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MA-3 - PCI-DSSv4-1.4.5 - low_complexity - low_disruption - medium_severity - network_sniffer_disabled - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-86506-3 - DISA-STIG-RHEL-08-040150 - NIST-800-53-SC-5 - firewalld-backend - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Setting unquoted shell-style assignment of 'FirewallBackend' to 'nftables' in '/etc/firewalld/firewalld.conf' block: - name: Check for duplicate values lineinfile: path: /etc/firewalld/firewalld.conf create: true regexp: ^\s*FirewallBackend= state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/firewalld/firewalld.conf lineinfile: path: /etc/firewalld/firewalld.conf create: true regexp: ^\s*FirewallBackend= state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/firewalld/firewalld.conf lineinfile: path: /etc/firewalld/firewalld.conf create: true regexp: ^\s*FirewallBackend= line: FirewallBackend=nftables state: present insertbefore: ^# FirewallBackend validate: /usr/bin/bash -n %s when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"firewalld" in ansible_facts.packages' tags: - CCE-86506-3 - DISA-STIG-RHEL-08-040150 - NIST-800-53-SC-5 - firewalld-backend - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure firewalld is installed package: name: firewalld state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82998-6 - DISA-STIG-RHEL-08-040100 - NIST-800-53-CM-6(a) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_firewalld_installed - name: Gather the package facts package_facts: manager: auto tags: - CCE-80877-4 - DISA-STIG-RHEL-08-040101 - NIST-800-171-3.1.3 - NIST-800-171-3.4.7 - NIST-800-53-AC-4 - NIST-800-53-CA-3(5) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(21) - PCI-DSSv4-1.2.1 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_firewalld_enabled - name: Enable service firewalld block: - name: Gather the package facts package_facts: manager: auto - name: Enable service firewalld systemd: name: firewalld enabled: 'yes' state: started masked: 'no' when: - '"firewalld" in ansible_facts.packages' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"firewalld" in ansible_facts.packages' tags: - CCE-80877-4 - DISA-STIG-RHEL-08-040101 - NIST-800-171-3.1.3 - NIST-800-171-3.4.7 - NIST-800-53-AC-4 - NIST-800-53-CA-3(5) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(21) - PCI-DSSv4-1.2.1 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_firewalld_enabled - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv6.conf.all.accept_ra.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81006-9 - DISA-STIG-RHEL-08-040261 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_ra - name: Comment out any occurrences of net.ipv6.conf.all.accept_ra from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv6.conf.all.accept_ra replace: '#net.ipv6.conf.all.accept_ra' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81006-9 - DISA-STIG-RHEL-08-040261 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_ra - name: Ensure sysctl net.ipv6.conf.all.accept_ra is set sysctl: name: net.ipv6.conf.all.accept_ra value: '{{ sysctl_net_ipv6_conf_all_accept_ra_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81006-9 - DISA-STIG-RHEL-08-040261 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_ra - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv6.conf.all.accept_redirects.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81009-3 - DISA-STIG-RHEL-08-040280 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_redirects - name: Comment out any occurrences of net.ipv6.conf.all.accept_redirects from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv6.conf.all.accept_redirects replace: '#net.ipv6.conf.all.accept_redirects' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81009-3 - DISA-STIG-RHEL-08-040280 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_redirects - name: Ensure sysctl net.ipv6.conf.all.accept_redirects is set sysctl: name: net.ipv6.conf.all.accept_redirects value: '{{ sysctl_net_ipv6_conf_all_accept_redirects_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81009-3 - DISA-STIG-RHEL-08-040280 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_redirects - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv6.conf.all.accept_source_route.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81013-5 - DISA-STIG-RHEL-08-040240 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_source_route - name: Comment out any occurrences of net.ipv6.conf.all.accept_source_route from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv6.conf.all.accept_source_route replace: '#net.ipv6.conf.all.accept_source_route' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81013-5 - DISA-STIG-RHEL-08-040240 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_source_route - name: Ensure sysctl net.ipv6.conf.all.accept_source_route is set sysctl: name: net.ipv6.conf.all.accept_source_route value: '{{ sysctl_net_ipv6_conf_all_accept_source_route_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81013-5 - DISA-STIG-RHEL-08-040240 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_accept_source_route - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv6.conf.all.forwarding.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82863-2 - DISA-STIG-RHEL-08-040260 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_forwarding - name: Comment out any occurrences of net.ipv6.conf.all.forwarding from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv6.conf.all.forwarding replace: '#net.ipv6.conf.all.forwarding' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82863-2 - DISA-STIG-RHEL-08-040260 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_forwarding - name: Ensure sysctl net.ipv6.conf.all.forwarding is set sysctl: name: net.ipv6.conf.all.forwarding value: '{{ sysctl_net_ipv6_conf_all_forwarding_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82863-2 - DISA-STIG-RHEL-08-040260 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_all_forwarding - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv6.conf.default.accept_ra.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81007-7 - DISA-STIG-RHEL-08-040262 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_ra - name: Comment out any occurrences of net.ipv6.conf.default.accept_ra from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv6.conf.default.accept_ra replace: '#net.ipv6.conf.default.accept_ra' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81007-7 - DISA-STIG-RHEL-08-040262 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_ra - name: Ensure sysctl net.ipv6.conf.default.accept_ra is set sysctl: name: net.ipv6.conf.default.accept_ra value: '{{ sysctl_net_ipv6_conf_default_accept_ra_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81007-7 - DISA-STIG-RHEL-08-040262 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_ra - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv6.conf.default.accept_redirects.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81010-1 - DISA-STIG-RHEL-08-040210 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_redirects - name: Comment out any occurrences of net.ipv6.conf.default.accept_redirects from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv6.conf.default.accept_redirects replace: '#net.ipv6.conf.default.accept_redirects' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81010-1 - DISA-STIG-RHEL-08-040210 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_redirects - name: Ensure sysctl net.ipv6.conf.default.accept_redirects is set sysctl: name: net.ipv6.conf.default.accept_redirects value: '{{ sysctl_net_ipv6_conf_default_accept_redirects_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81010-1 - DISA-STIG-RHEL-08-040210 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_redirects - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv6.conf.default.accept_source_route.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81015-0 - DISA-STIG-RHEL-08-040250 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.2 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_source_route - name: Comment out any occurrences of net.ipv6.conf.default.accept_source_route from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv6.conf.default.accept_source_route replace: '#net.ipv6.conf.default.accept_source_route' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81015-0 - DISA-STIG-RHEL-08-040250 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.2 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_source_route - name: Ensure sysctl net.ipv6.conf.default.accept_source_route is set sysctl: name: net.ipv6.conf.default.accept_source_route value: '{{ sysctl_net_ipv6_conf_default_accept_source_route_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81015-0 - DISA-STIG-RHEL-08-040250 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.2 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv6_conf_default_accept_source_route - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.all.accept_redirects.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80917-8 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040279 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_accept_redirects - name: Comment out any occurrences of net.ipv4.conf.all.accept_redirects from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.all.accept_redirects replace: '#net.ipv4.conf.all.accept_redirects' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80917-8 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040279 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_accept_redirects - name: Ensure sysctl net.ipv4.conf.all.accept_redirects is set sysctl: name: net.ipv4.conf.all.accept_redirects value: '{{ sysctl_net_ipv4_conf_all_accept_redirects_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80917-8 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040279 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_accept_redirects - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.all.accept_source_route.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81011-9 - DISA-STIG-RHEL-08-040239 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_accept_source_route - name: Comment out any occurrences of net.ipv4.conf.all.accept_source_route from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.all.accept_source_route replace: '#net.ipv4.conf.all.accept_source_route' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81011-9 - DISA-STIG-RHEL-08-040239 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_accept_source_route - name: Ensure sysctl net.ipv4.conf.all.accept_source_route is set sysctl: name: net.ipv4.conf.all.accept_source_route value: '{{ sysctl_net_ipv4_conf_all_accept_source_route_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81011-9 - DISA-STIG-RHEL-08-040239 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_accept_source_route - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.all.forwarding.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86220-1 - DISA-STIG-RHEL-08-040259 - NIST-800-53-CM-6(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_forwarding - name: Comment out any occurrences of net.ipv4.conf.all.forwarding from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.all.forwarding replace: '#net.ipv4.conf.all.forwarding' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86220-1 - DISA-STIG-RHEL-08-040259 - NIST-800-53-CM-6(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_forwarding - name: Ensure sysctl net.ipv4.conf.all.forwarding is set sysctl: name: net.ipv4.conf.all.forwarding value: '{{ sysctl_net_ipv4_conf_all_forwarding_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86220-1 - DISA-STIG-RHEL-08-040259 - NIST-800-53-CM-6(b) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_forwarding - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.all.rp_filter.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81021-8 - DISA-STIG-RHEL-08-040285 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.3 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_rp_filter - name: Comment out any occurrences of net.ipv4.conf.all.rp_filter from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.all.rp_filter replace: '#net.ipv4.conf.all.rp_filter' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81021-8 - DISA-STIG-RHEL-08-040285 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.3 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_rp_filter - name: Ensure sysctl net.ipv4.conf.all.rp_filter is set sysctl: name: net.ipv4.conf.all.rp_filter value: '{{ sysctl_net_ipv4_conf_all_rp_filter_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81021-8 - DISA-STIG-RHEL-08-040285 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.3 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_rp_filter - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.default.accept_redirects.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80919-4 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040209 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.3 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_accept_redirects - name: Comment out any occurrences of net.ipv4.conf.default.accept_redirects from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.default.accept_redirects replace: '#net.ipv4.conf.default.accept_redirects' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80919-4 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040209 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.3 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_accept_redirects - name: Ensure sysctl net.ipv4.conf.default.accept_redirects is set sysctl: name: net.ipv4.conf.default.accept_redirects value: '{{ sysctl_net_ipv4_conf_default_accept_redirects_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80919-4 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040209 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-7(a) - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.3 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_accept_redirects - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.default.accept_source_route.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80920-2 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040249 - NIST-800-171-3.1.20 - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_accept_source_route - name: Comment out any occurrences of net.ipv4.conf.default.accept_source_route from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.default.accept_source_route replace: '#net.ipv4.conf.default.accept_source_route' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80920-2 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040249 - NIST-800-171-3.1.20 - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_accept_source_route - name: Ensure sysctl net.ipv4.conf.default.accept_source_route is set sysctl: name: net.ipv4.conf.default.accept_source_route value: '{{ sysctl_net_ipv4_conf_default_accept_source_route_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80920-2 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040249 - NIST-800-171-3.1.20 - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_accept_source_route - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.icmp_echo_ignore_broadcasts.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80922-8 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040230 - NIST-800-171-3.1.20 - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.2 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_icmp_echo_ignore_broadcasts - name: Comment out any occurrences of net.ipv4.icmp_echo_ignore_broadcasts from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.icmp_echo_ignore_broadcasts replace: '#net.ipv4.icmp_echo_ignore_broadcasts' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80922-8 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040230 - NIST-800-171-3.1.20 - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.2 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_icmp_echo_ignore_broadcasts - name: Ensure sysctl net.ipv4.icmp_echo_ignore_broadcasts is set sysctl: name: net.ipv4.icmp_echo_ignore_broadcasts value: '{{ sysctl_net_ipv4_icmp_echo_ignore_broadcasts_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80922-8 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040230 - NIST-800-171-3.1.20 - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - PCI-DSS-Req-1.4.3 - PCI-DSSv4-1.4.2 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_icmp_echo_ignore_broadcasts - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.all.send_redirects.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80918-6 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040220 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - PCI-DSSv4-1.4.5 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_send_redirects - name: Comment out any occurrences of net.ipv4.conf.all.send_redirects from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.all.send_redirects replace: '#net.ipv4.conf.all.send_redirects' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80918-6 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040220 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - PCI-DSSv4-1.4.5 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_send_redirects - name: Ensure sysctl net.ipv4.conf.all.send_redirects is set to 0 sysctl: name: net.ipv4.conf.all.send_redirects value: '0' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80918-6 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040220 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - PCI-DSSv4-1.4.5 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_all_send_redirects - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.ipv4.conf.default.send_redirects.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80921-0 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040270 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - PCI-DSSv4-1.4.5 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_send_redirects - name: Comment out any occurrences of net.ipv4.conf.default.send_redirects from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.ipv4.conf.default.send_redirects replace: '#net.ipv4.conf.default.send_redirects' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80921-0 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040270 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - PCI-DSSv4-1.4.5 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_send_redirects - name: Ensure sysctl net.ipv4.conf.default.send_redirects is set to 0 sysctl: name: net.ipv4.conf.default.send_redirects value: '0' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80921-0 - CJIS-5.10.1.1 - DISA-STIG-RHEL-08-040270 - NIST-800-171-3.1.20 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-SC-5 - NIST-800-53-SC-7(a) - PCI-DSSv4-1.4.5 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_ipv4_conf_default_send_redirects - name: Ensure kernel module 'atm' is disabled lineinfile: create: true dest: /etc/modprobe.d/atm.conf regexp: install\s+atm line: install atm /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82028-2 - DISA-STIG-RHEL-08-040021 - NIST-800-53-AC-18 - disable_strategy - kernel_module_atm_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'atm' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/atm.conf regexp: ^blacklist atm$ line: blacklist atm when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82028-2 - DISA-STIG-RHEL-08-040021 - NIST-800-53-AC-18 - disable_strategy - kernel_module_atm_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'can' is disabled lineinfile: create: true dest: /etc/modprobe.d/can.conf regexp: install\s+can line: install can /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82059-7 - DISA-STIG-RHEL-08-040022 - NIST-800-53-AC-18 - disable_strategy - kernel_module_can_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'can' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/can.conf regexp: ^blacklist can$ line: blacklist can when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82059-7 - DISA-STIG-RHEL-08-040022 - NIST-800-53-AC-18 - disable_strategy - kernel_module_can_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'firewire-core' is disabled lineinfile: create: true dest: /etc/modprobe.d/firewire-core.conf regexp: install\s+firewire-core line: install firewire-core /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82005-0 - DISA-STIG-RHEL-08-040026 - NIST-800-53-AC-18 - disable_strategy - kernel_module_firewire-core_disabled - low_complexity - low_severity - medium_disruption - reboot_required - name: Ensure kernel module 'firewire-core' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/firewire-core.conf regexp: ^blacklist firewire-core$ line: blacklist firewire-core when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82005-0 - DISA-STIG-RHEL-08-040026 - NIST-800-53-AC-18 - disable_strategy - kernel_module_firewire-core_disabled - low_complexity - low_severity - medium_disruption - reboot_required - name: Ensure kernel module 'sctp' is disabled lineinfile: create: true dest: /etc/modprobe.d/sctp.conf regexp: install\s+sctp line: install sctp /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80834-5 - CJIS-5.10.1 - DISA-STIG-RHEL-08-040023 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-1.4.2 - PCI-DSSv4-1.4.2 - disable_strategy - kernel_module_sctp_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'sctp' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/sctp.conf regexp: ^blacklist sctp$ line: blacklist sctp when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80834-5 - CJIS-5.10.1 - DISA-STIG-RHEL-08-040023 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-1.4.2 - PCI-DSSv4-1.4.2 - disable_strategy - kernel_module_sctp_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'tipc' is disabled lineinfile: create: true dest: /etc/modprobe.d/tipc.conf regexp: install\s+tipc line: install tipc /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82297-3 - DISA-STIG-RHEL-08-040024 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - kernel_module_tipc_disabled - low_complexity - low_severity - medium_disruption - reboot_required - name: Ensure kernel module 'tipc' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/tipc.conf regexp: ^blacklist tipc$ line: blacklist tipc when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82297-3 - DISA-STIG-RHEL-08-040024 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - kernel_module_tipc_disabled - low_complexity - low_severity - medium_disruption - reboot_required - name: Ensure kernel module 'bluetooth' is disabled lineinfile: create: true dest: /etc/modprobe.d/bluetooth.conf regexp: install\s+bluetooth line: install bluetooth /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80832-9 - CJIS-5.13.1.3 - DISA-STIG-RHEL-08-040111 - NIST-800-171-3.1.16 - NIST-800-53-AC-18(3) - NIST-800-53-AC-18(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - disable_strategy - kernel_module_bluetooth_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'bluetooth' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/bluetooth.conf regexp: ^blacklist bluetooth$ line: blacklist bluetooth when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80832-9 - CJIS-5.13.1.3 - DISA-STIG-RHEL-08-040111 - NIST-800-171-3.1.16 - NIST-800-53-AC-18(3) - NIST-800-53-AC-18(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - disable_strategy - kernel_module_bluetooth_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Gather the package facts package_facts: manager: auto tags: - CCE-83501-7 - DISA-STIG-RHEL-08-040110 - NIST-800-171-3.1.16 - NIST-800-53-AC-18(3) - NIST-800-53-AC-18(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - PCI-DSS-Req-1.3.3 - PCI-DSSv4-1.3.3 - PCI-DSSv4-2.3 - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - wireless_disable_interfaces - name: Service facts ansible.builtin.service_facts: null tags: - CCE-83501-7 - DISA-STIG-RHEL-08-040110 - NIST-800-171-3.1.16 - NIST-800-53-AC-18(3) - NIST-800-53-AC-18(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - PCI-DSS-Req-1.3.3 - PCI-DSSv4-1.3.3 - PCI-DSSv4-2.3 - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - wireless_disable_interfaces - name: Ensure NetworkManager is installed ansible.builtin.package: name: '{{ item }}' state: present with_items: - NetworkManager tags: - CCE-83501-7 - DISA-STIG-RHEL-08-040110 - NIST-800-171-3.1.16 - NIST-800-53-AC-18(3) - NIST-800-53-AC-18(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - PCI-DSS-Req-1.3.3 - PCI-DSSv4-1.3.3 - PCI-DSSv4-2.3 - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - wireless_disable_interfaces - name: NetworkManager Deactivate Wireless Network Interfaces command: nmcli radio wifi off when: - '''NetworkManager'' in ansible_facts.packages' - ansible_facts.services['NetworkManager.service'].state == 'running' tags: - CCE-83501-7 - DISA-STIG-RHEL-08-040110 - NIST-800-171-3.1.16 - NIST-800-53-AC-18(3) - NIST-800-53-AC-18(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - PCI-DSS-Req-1.3.3 - PCI-DSSv4-1.3.3 - PCI-DSSv4-2.3 - low_complexity - medium_disruption - medium_severity - no_reboot_needed - unknown_strategy - wireless_disable_interfaces - name: Ensure All World-Writable Directories Are Owned by root User - Define Excluded (Non-Local) File Systems and Paths ansible.builtin.set_fact: excluded_fstypes: - afs - ceph - cifs - smb3 - smbfs - sshfs - ncpfs - ncp - nfs - nfs4 - gfs - gfs2 - glusterfs - gpfs - pvfs2 - ocfs2 - lustre - davfs - fuse.sshfs excluded_paths: - dev - proc - run - sys search_paths: [] tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Find Relevant Root Directories Ignoring Pre-Defined Excluded Paths ansible.builtin.find: paths: / file_type: directory excludes: '{{ excluded_paths }}' hidden: true recurse: false register: result_relevant_root_dirs tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Include Relevant Root Directories in a List of Paths to be Searched ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.path]) }}' loop: '{{ result_relevant_root_dirs.files }}' tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Increment Search Paths List with Local Partitions Mount Points ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.mount]) }}' loop: '{{ ansible_mounts }}' when: - item.fstype not in excluded_fstypes - item.mount != '/' tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Increment Search Paths List with Local NFS File System Targets ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}' loop: '{{ ansible_mounts }}' when: item.device is search("localhost:") tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Define Rule Specific Facts ansible.builtin.set_fact: world_writable_dirs: [] tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Find All Uncompliant Directories in Local File Systems ansible.builtin.command: cmd: find {{ item }} -xdev -type d -perm -0002 -uid +0 loop: '{{ search_paths }}' changed_when: false register: result_found_dirs tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Create List of World Writable Directories Not Owned by root ansible.builtin.set_fact: world_writable_dirs: '{{ world_writable_dirs | union(item.stdout_lines) | list }}' loop: '{{ result_found_dirs.results }}' when: item is not skipped tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure All World-Writable Directories Are Owned by root User - Ensure root Ownership on Local World Writable Directories ansible.builtin.file: path: '{{ item }}' owner: root loop: '{{ world_writable_dirs }}' tags: - CCE-83375-6 - DISA-STIG-RHEL-08-010700 - dir_perms_world_writable_root_owned - low_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Define Excluded (Non-Local) File Systems and Paths ansible.builtin.set_fact: excluded_fstypes: - afs - ceph - cifs - smb3 - smbfs - sshfs - ncpfs - ncp - nfs - nfs4 - gfs - gfs2 - glusterfs - gpfs - pvfs2 - ocfs2 - lustre - davfs - fuse.sshfs excluded_paths: - dev - proc - run - sys search_paths: [] tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Find Relevant Root Directories Ignoring Pre-Defined Excluded Paths ansible.builtin.find: paths: / file_type: directory excludes: '{{ excluded_paths }}' hidden: true recurse: false register: result_relevant_root_dirs tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Include Relevant Root Directories in a List of Paths to be Searched ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.path]) }}' loop: '{{ result_relevant_root_dirs.files }}' tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Increment Search Paths List with Local Partitions Mount Points ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.mount]) }}' loop: '{{ ansible_mounts }}' when: - item.fstype not in excluded_fstypes - item.mount != '/' tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Increment Search Paths List with Local NFS File System Targets ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}' loop: '{{ ansible_mounts }}' when: item.device is search("localhost:") tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Define Rule Specific Facts ansible.builtin.set_fact: world_writable_dirs: [] tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Find All Uncompliant Directories in Local File Systems ansible.builtin.command: cmd: find {{ item }} -xdev -type d ( -perm -0002 -a ! -perm -1000 ) loop: '{{ search_paths }}' changed_when: false register: result_found_dirs tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Create List of World Writable Directories Without Sticky Bit ansible.builtin.set_fact: world_writable_dirs: '{{ world_writable_dirs | union(item.stdout_lines) | list }}' loop: '{{ result_found_dirs.results }}' when: result_found_dirs is not skipped and item is not skipped tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Verify that All World-Writable Directories Have Sticky Bits Set - Ensure Sticky Bit is Set on Local World Writable Directories ansible.builtin.file: path: '{{ item }}' mode: a+t loop: '{{ world_writable_dirs }}' tags: - CCE-80783-4 - DISA-STIG-RHEL-08-010190 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSSv4-2.2.6 - dir_perms_world_writable_sticky_bits - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Test for existence /etc/audit/auditd.conf stat: path: /etc/audit/auditd.conf register: file_exists tags: - CCE-85871-2 - DISA-STIG-RHEL-08-030610 - NIST-800-53-AU-12(b) - configure_strategy - file_permissions_etc_audit_auditd - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-xs,g-xws,o-xwrt on /etc/audit/auditd.conf file: path: /etc/audit/auditd.conf mode: u-xs,g-xws,o-xwrt when: file_exists.stat is defined and file_exists.stat.exists tags: - CCE-85871-2 - DISA-STIG-RHEL-08-030610 - NIST-800-53-AU-12(b) - configure_strategy - file_permissions_etc_audit_auditd - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /etc/audit/rules.d/ file(s) command: find -H /etc/audit/rules.d/ -maxdepth 1 -perm /u+xs,g+xws,o+xwrt -type f -regex "^.*rules$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-85875-3 - DISA-STIG-RHEL-08-030610 - NIST-800-53-AU-12(b) - configure_strategy - file_permissions_etc_audit_rulesd - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /etc/audit/rules.d/ file(s) file: path: '{{ item }}' mode: u-xs,g-xws,o-xwrt state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-85875-3 - DISA-STIG-RHEL-08-030610 - NIST-800-53-AU-12(b) - configure_strategy - file_permissions_etc_audit_rulesd - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*fs.protected_hardlinks.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81027-5 - DISA-STIG-RHEL-08-010374 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_fs_protected_hardlinks - name: Comment out any occurrences of fs.protected_hardlinks from config files replace: path: '{{ item.path }}' regexp: ^[\s]*fs.protected_hardlinks replace: '#fs.protected_hardlinks' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81027-5 - DISA-STIG-RHEL-08-010374 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_fs_protected_hardlinks - name: Ensure sysctl fs.protected_hardlinks is set to 1 sysctl: name: fs.protected_hardlinks value: '1' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81027-5 - DISA-STIG-RHEL-08-010374 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_fs_protected_hardlinks - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*fs.protected_symlinks.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81030-9 - DISA-STIG-RHEL-08-010373 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_fs_protected_symlinks - name: Comment out any occurrences of fs.protected_symlinks from config files replace: path: '{{ item.path }}' regexp: ^[\s]*fs.protected_symlinks replace: '#fs.protected_symlinks' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81030-9 - DISA-STIG-RHEL-08-010373 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_fs_protected_symlinks - name: Ensure sysctl fs.protected_symlinks is set to 1 sysctl: name: fs.protected_symlinks value: '1' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81030-9 - DISA-STIG-RHEL-08-010373 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_fs_protected_symlinks - name: Ensure group owner on /var/log/ file: path: /var/log/ state: directory group: '0' tags: - CCE-83659-3 - DISA-STIG-RHEL-08-010260 - configure_strategy - file_groupowner_var_log - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /var/log/messages stat: path: /var/log/messages register: file_exists tags: - CCE-83660-1 - DISA-STIG-RHEL-08-010230 - configure_strategy - file_groupowner_var_log_messages - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner 0 on /var/log/messages file: path: /var/log/messages group: '0' when: file_exists.stat is defined and file_exists.stat.exists tags: - CCE-83660-1 - DISA-STIG-RHEL-08-010230 - configure_strategy - file_groupowner_var_log_messages - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on directory /var/log/ file: path: /var/log/ state: directory owner: '0' tags: - CCE-83661-9 - DISA-STIG-RHEL-08-010250 - configure_strategy - file_owner_var_log - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /var/log/messages stat: path: /var/log/messages register: file_exists tags: - CCE-83662-7 - DISA-STIG-RHEL-08-010220 - configure_strategy - file_owner_var_log_messages - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner 0 on /var/log/messages file: path: /var/log/messages owner: '0' when: file_exists.stat is defined and file_exists.stat.exists tags: - CCE-83662-7 - DISA-STIG-RHEL-08-010220 - configure_strategy - file_owner_var_log_messages - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /var/log/ file(s) command: 'find -H /var/log/ -maxdepth 1 -perm /u+s,g+ws,o+wt -type d ' register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-83663-5 - DISA-STIG-RHEL-08-010240 - configure_strategy - file_permissions_var_log - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /var/log/ file(s) file: path: '{{ item }}' mode: u-s,g-ws,o-wt state: directory with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-83663-5 - DISA-STIG-RHEL-08-010240 - configure_strategy - file_permissions_var_log - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Test for existence /var/log/messages stat: path: /var/log/messages register: file_exists tags: - CCE-83665-0 - DISA-STIG-RHEL-08-010210 - configure_strategy - file_permissions_var_log_messages - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure permission u-xs,g-xws,o-xwrt on /var/log/messages file: path: /var/log/messages mode: u-xs,g-xws,o-xwrt when: file_exists.stat is defined and file_exists.stat.exists tags: - CCE-83665-0 - DISA-STIG-RHEL-08-010210 - configure_strategy - file_permissions_var_log_messages - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner on /lib/ recursively file: path: /lib/ state: directory recurse: true group: '0' tags: - CCE-85894-4 - DISA-STIG-RHEL-08-010351 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_group_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner on /lib64/ recursively file: path: /lib64/ state: directory recurse: true group: '0' tags: - CCE-85894-4 - DISA-STIG-RHEL-08-010351 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_group_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner on /usr/lib/ recursively file: path: /usr/lib/ state: directory recurse: true group: '0' tags: - CCE-85894-4 - DISA-STIG-RHEL-08-010351 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_group_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure group owner on /usr/lib64/ recursively file: path: /usr/lib64/ state: directory recurse: true group: '0' tags: - CCE-85894-4 - DISA-STIG-RHEL-08-010351 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_group_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on directory /lib/ recursively file: path: /lib/ state: directory recurse: true owner: '0' tags: - CCE-89021-0 - DISA-STIG-RHEL-08-010341 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on directory /lib64/ recursively file: path: /lib64/ state: directory recurse: true owner: '0' tags: - CCE-89021-0 - DISA-STIG-RHEL-08-010341 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on directory /usr/lib/ recursively file: path: /usr/lib/ state: directory recurse: true owner: '0' tags: - CCE-89021-0 - DISA-STIG-RHEL-08-010341 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on directory /usr/lib64/ recursively file: path: /usr/lib64/ state: directory recurse: true owner: '0' tags: - CCE-89021-0 - DISA-STIG-RHEL-08-010341 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /lib/ file(s) recursively command: 'find -H /lib/ -perm /g+w,o+w -type d ' register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /lib/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: directory with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /lib64/ file(s) recursively command: 'find -H /lib64/ -perm /g+w,o+w -type d ' register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /lib64/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: directory with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /usr/lib/ file(s) recursively command: 'find -H /usr/lib/ -perm /g+w,o+w -type d ' register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /usr/lib/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: directory with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /usr/lib64/ file(s) recursively command: 'find -H /usr/lib64/ -perm /g+w,o+w -type d ' register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /usr/lib64/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: directory with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-88692-9 - DISA-STIG-RHEL-08-010331 - NIST-800-53-CM-5 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - dir_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Retrieve the system command files and set their group ownership to root command: find -L {{ item }} ! -group root -type f -exec chgrp root '{}' \; with_items: - /bin - /sbin - /usr/bin - /usr/sbin - /usr/local/bin - /usr/local/sbin changed_when: false failed_when: false check_mode: false tags: - CCE-86519-6 - DISA-STIG-RHEL-08-010320 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - file_groupownership_system_commands_dirs - medium_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Read list of system executables without root ownership command: find /bin/ /usr/bin/ /usr/local/bin/ /sbin/ /usr/sbin/ /usr/local/sbin/ /usr/libexec \! -user root register: no_root_system_executables changed_when: false failed_when: false check_mode: false tags: - CCE-80806-3 - DISA-STIG-RHEL-08-010310 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - file_ownership_binary_dirs - medium_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Set ownership to root of system executables file: path: '{{ item }}' owner: root with_items: '{{ no_root_system_executables.stdout_lines }}' when: no_root_system_executables.stdout_lines | length > 0 tags: - CCE-80806-3 - DISA-STIG-RHEL-08-010310 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - file_ownership_binary_dirs - medium_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Find /lib/ file(s) matching ^.*$ recursively command: find -H /lib/ -type f ! -uid 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on /lib/ file(s) matching ^.*$ file: path: '{{ item }}' owner: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /lib64/ file(s) matching ^.*$ recursively command: find -H /lib64/ -type f ! -uid 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on /lib64/ file(s) matching ^.*$ file: path: '{{ item }}' owner: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /usr/lib/ file(s) matching ^.*$ recursively command: find -H /usr/lib/ -type f ! -uid 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on /usr/lib/ file(s) matching ^.*$ file: path: '{{ item }}' owner: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /usr/lib64/ file(s) matching ^.*$ recursively command: find -H /usr/lib64/ -type f ! -uid 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure owner on /usr/lib64/ file(s) matching ^.*$ file: path: '{{ item }}' owner: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80807-1 - DISA-STIG-RHEL-08-010340 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_ownership_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Read list of world and group writable system executables ansible.builtin.command: find /bin /usr/bin /usr/local/bin /sbin /usr/sbin /usr/local/sbin /usr/libexec -perm /022 -type f register: world_writable_library_files changed_when: false failed_when: false check_mode: false tags: - CCE-80809-7 - DISA-STIG-RHEL-08-010300 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - file_permissions_binary_dirs - medium_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Remove world/group writability of system executables ansible.builtin.file: path: '{{ item }}' mode: go-w state: file with_items: '{{ world_writable_library_files.stdout_lines }}' when: world_writable_library_files.stdout_lines | length > 0 tags: - CCE-80809-7 - DISA-STIG-RHEL-08-010300 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - file_permissions_binary_dirs - medium_complexity - medium_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Find /lib/ file(s) recursively command: find -H /lib/ -perm /g+w,o+w -type f -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /lib/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /lib64/ file(s) recursively command: find -H /lib64/ -perm /g+w,o+w -type f -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /lib64/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /usr/lib/ file(s) recursively command: find -H /usr/lib/ -perm /g+w,o+w -type f -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /usr/lib/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /usr/lib64/ file(s) recursively command: find -H /usr/lib64/ -perm /g+w,o+w -type f -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /usr/lib64/ file(s) file: path: '{{ item }}' mode: g-w,o-w state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-80815-4 - DISA-STIG-RHEL-08-010330 - NIST-800-53-AC-6(1) - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - NIST-800-53-CM-6(a) - configure_strategy - file_permissions_library_dirs - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /lib/ file(s) matching ^.*$ recursively command: find -H /lib/ -type f ! -group 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Ensure group owner on /lib/ file(s) matching ^.*$ file: path: '{{ item }}' group: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Find /lib64/ file(s) matching ^.*$ recursively command: find -H /lib64/ -type f ! -group 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Ensure group owner on /lib64/ file(s) matching ^.*$ file: path: '{{ item }}' group: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Find /usr/lib/ file(s) matching ^.*$ recursively command: find -H /usr/lib/ -type f ! -group 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Ensure group owner on /usr/lib/ file(s) matching ^.*$ file: path: '{{ item }}' group: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Find /usr/lib64/ file(s) matching ^.*$ recursively command: find -H /usr/lib64/ -type f ! -group 0 -regex "^.*$" register: files_found changed_when: false failed_when: false check_mode: false tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Ensure group owner on /usr/lib64/ file(s) matching ^.*$ file: path: '{{ item }}' group: '0' state: file with_items: - '{{ files_found.stdout_lines }}' tags: - CCE-86523-8 - DISA-STIG-RHEL-08-010350 - NIST-800-53-CM-5(6) - NIST-800-53-CM-5(6).1 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - root_permissions_syslibrary_files - name: Gather the package facts package_facts: manager: auto tags: - CCE-80873-3 - DISA-STIG-RHEL-08-040070 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_autofs_disabled - name: Block Disable service autofs block: - name: Disable service autofs block: - name: Disable service autofs systemd: name: autofs.service enabled: 'no' state: stopped masked: 'yes' rescue: - name: Intentionally ignored previous 'Disable service autofs' failure, service was already disabled meta: noop when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "autofs" in ansible_facts.packages ) tags: - CCE-80873-3 - DISA-STIG-RHEL-08-040070 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_autofs_disabled - name: Unit Socket Exists - autofs.socket command: systemctl -q list-unit-files autofs.socket register: socket_file_exists changed_when: false failed_when: socket_file_exists.rc not in [0, 1] check_mode: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "autofs" in ansible_facts.packages ) tags: - CCE-80873-3 - DISA-STIG-RHEL-08-040070 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_autofs_disabled - name: Disable socket autofs systemd: name: autofs.socket enabled: 'no' state: stopped masked: 'yes' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "autofs" in ansible_facts.packages ) - socket_file_exists.stdout_lines is search("autofs.socket",multiline=True) tags: - CCE-80873-3 - DISA-STIG-RHEL-08-040070 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_autofs_disabled - name: Ensure kernel module 'cramfs' is disabled lineinfile: create: true dest: /etc/modprobe.d/cramfs.conf regexp: install\s+cramfs line: install cramfs /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81031-7 - DISA-STIG-RHEL-08-040025 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - kernel_module_cramfs_disabled - low_complexity - low_severity - medium_disruption - reboot_required - name: Ensure kernel module 'cramfs' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/cramfs.conf regexp: ^blacklist cramfs$ line: blacklist cramfs when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81031-7 - DISA-STIG-RHEL-08-040025 - NIST-800-171-3.4.6 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - kernel_module_cramfs_disabled - low_complexity - low_severity - medium_disruption - reboot_required - name: Ensure kernel module 'usb-storage' is disabled lineinfile: create: true dest: /etc/modprobe.d/usb-storage.conf regexp: install\s+usb-storage line: install usb-storage /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80835-2 - DISA-STIG-RHEL-08-040080 - NIST-800-171-3.1.21 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - PCI-DSSv4-3.4.2 - disable_strategy - kernel_module_usb-storage_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'usb-storage' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/usb-storage.conf regexp: ^blacklist usb-storage$ line: blacklist usb-storage when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80835-2 - DISA-STIG-RHEL-08-040080 - NIST-800-171-3.1.21 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - PCI-DSSv4-3.4.2 - disable_strategy - kernel_module_usb-storage_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: 'Add nosuid Option to /boot/efi: Check information associated to mountpoint' command: findmnt --fstab '/boot/efi' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/boot/efi" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-86038-7 - DISA-STIG-RHEL-08-010572 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_efi_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot/efi: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/boot/efi" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-86038-7 - DISA-STIG-RHEL-08-010572 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_efi_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot/efi: If /boot/efi not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /boot/efi - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/boot/efi" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-86038-7 - DISA-STIG-RHEL-08-010572 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_efi_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot/efi: Make sure nosuid option is part of the to /boot/efi options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/boot/efi" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-86038-7 - DISA-STIG-RHEL-08-010572 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_efi_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot/efi: Ensure /boot/efi is mounted with nosuid option' mount: path: /boot/efi src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/boot/efi" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-86038-7 - DISA-STIG-RHEL-08-010572 - NIST-800-53-CM-6(b) - NIST-800-53-CM-6.1(iv) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_efi_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot: Check information associated to mountpoint' command: findmnt --fstab '/boot' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81033-3 - DISA-STIG-RHEL-08-010571 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-81033-3 - DISA-STIG-RHEL-08-010571 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot: If /boot not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /boot - '' - '' - defaults when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-81033-3 - DISA-STIG-RHEL-08-010571 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot: Make sure nosuid option is part of the to /boot options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-81033-3 - DISA-STIG-RHEL-08-010571 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_nosuid - no_reboot_needed - name: 'Add nosuid Option to /boot: Ensure /boot is mounted with nosuid option' mount: path: /boot src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-81033-3 - DISA-STIG-RHEL-08-010571 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_boot_nosuid - no_reboot_needed - name: 'Add nodev Option to /dev/shm: Check information associated to mountpoint' command: findmnt '/dev/shm' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80837-8 - DISA-STIG-RHEL-08-040120 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nodev - no_reboot_needed - name: 'Add nodev Option to /dev/shm: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-80837-8 - DISA-STIG-RHEL-08-040120 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nodev - no_reboot_needed - name: 'Add nodev Option to /dev/shm: If /dev/shm not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /dev/shm - tmpfs - tmpfs - defaults when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ("" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-80837-8 - DISA-STIG-RHEL-08-040120 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nodev - no_reboot_needed - name: 'Add nodev Option to /dev/shm: Make sure nodev option is part of the to /dev/shm options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nodev'' }) }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined and "nodev" not in mount_info.options tags: - CCE-80837-8 - DISA-STIG-RHEL-08-040120 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nodev - no_reboot_needed - name: 'Add nodev Option to /dev/shm: Ensure /dev/shm is mounted with nodev option' mount: path: /dev/shm src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("" | length == 0) tags: - CCE-80837-8 - DISA-STIG-RHEL-08-040120 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nodev - no_reboot_needed - name: 'Add noexec Option to /dev/shm: Check information associated to mountpoint' command: findmnt '/dev/shm' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80838-6 - DISA-STIG-RHEL-08-040122 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_noexec - no_reboot_needed - name: 'Add noexec Option to /dev/shm: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-80838-6 - DISA-STIG-RHEL-08-040122 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_noexec - no_reboot_needed - name: 'Add noexec Option to /dev/shm: If /dev/shm not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /dev/shm - tmpfs - tmpfs - defaults when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ("" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-80838-6 - DISA-STIG-RHEL-08-040122 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_noexec - no_reboot_needed - name: 'Add noexec Option to /dev/shm: Make sure noexec option is part of the to /dev/shm options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',noexec'' }) }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined and "noexec" not in mount_info.options tags: - CCE-80838-6 - DISA-STIG-RHEL-08-040122 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_noexec - no_reboot_needed - name: 'Add noexec Option to /dev/shm: Ensure /dev/shm is mounted with noexec option' mount: path: /dev/shm src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("" | length == 0) tags: - CCE-80838-6 - DISA-STIG-RHEL-08-040122 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_noexec - no_reboot_needed - name: 'Add nosuid Option to /dev/shm: Check information associated to mountpoint' command: findmnt '/dev/shm' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80839-4 - DISA-STIG-RHEL-08-040121 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nosuid - no_reboot_needed - name: 'Add nosuid Option to /dev/shm: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-80839-4 - DISA-STIG-RHEL-08-040121 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nosuid - no_reboot_needed - name: 'Add nosuid Option to /dev/shm: If /dev/shm not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /dev/shm - tmpfs - tmpfs - defaults when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ("" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-80839-4 - DISA-STIG-RHEL-08-040121 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nosuid - no_reboot_needed - name: 'Add nosuid Option to /dev/shm: Make sure nosuid option is part of the to /dev/shm options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-80839-4 - DISA-STIG-RHEL-08-040121 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nosuid - no_reboot_needed - name: 'Add nosuid Option to /dev/shm: Ensure /dev/shm is mounted with nosuid option' mount: path: /dev/shm src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("" | length == 0) tags: - CCE-80839-4 - DISA-STIG-RHEL-08-040121 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_dev_shm_nosuid - no_reboot_needed - name: 'Add noexec Option to /home: Check information associated to mountpoint' command: findmnt --fstab '/home' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83328-5 - DISA-STIG-RHEL-08-010590 - NIST-800-53-CM-6(b) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_noexec - no_reboot_needed - name: 'Add noexec Option to /home: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-83328-5 - DISA-STIG-RHEL-08-010590 - NIST-800-53-CM-6(b) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_noexec - no_reboot_needed - name: 'Add noexec Option to /home: If /home not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /home - '' - '' - defaults when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-83328-5 - DISA-STIG-RHEL-08-010590 - NIST-800-53-CM-6(b) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_noexec - no_reboot_needed - name: 'Add noexec Option to /home: Make sure noexec option is part of the to /home options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',noexec'' }) }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined and "noexec" not in mount_info.options tags: - CCE-83328-5 - DISA-STIG-RHEL-08-010590 - NIST-800-53-CM-6(b) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_noexec - no_reboot_needed - name: 'Add noexec Option to /home: Ensure /home is mounted with noexec option' mount: path: /home src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-83328-5 - DISA-STIG-RHEL-08-010590 - NIST-800-53-CM-6(b) - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_noexec - no_reboot_needed - name: 'Add nosuid Option to /home: Check information associated to mountpoint' command: findmnt --fstab '/home' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/home" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-81050-7 - DISA-STIG-RHEL-08-010570 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_nosuid - no_reboot_needed - name: 'Add nosuid Option to /home: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/home" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-81050-7 - DISA-STIG-RHEL-08-010570 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_nosuid - no_reboot_needed - name: 'Add nosuid Option to /home: If /home not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /home - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/home" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-81050-7 - DISA-STIG-RHEL-08-010570 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_nosuid - no_reboot_needed - name: 'Add nosuid Option to /home: Make sure nosuid option is part of the to /home options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/home" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-81050-7 - DISA-STIG-RHEL-08-010570 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_nosuid - no_reboot_needed - name: 'Add nosuid Option to /home: Ensure /home is mounted with nosuid option' mount: path: /home src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/home" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-81050-7 - DISA-STIG-RHEL-08-010570 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_home_nosuid - no_reboot_needed - name: Ensure non-root local partitions are mounted with nodev option mount: path: '{{ item.mount }}' src: '{{ item.device }}' opts: '{{ item.options }},nodev' state: mounted fstype: '{{ item.fstype }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - item.mount is match('/\w') - item.options is not search('nodev') with_items: - '{{ ansible_facts.mounts }}' tags: - CCE-82069-6 - DISA-STIG-RHEL-08-010580 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_nodev_nonroot_local_partitions - no_reboot_needed - name: Ensure permission nodev are set on var_removable_partition lineinfile: path: /etc/fstab regexp: ^\s*({{ var_removable_partition }})\s+([^\s]*)\s+([^\s]*)\s+([^\s]*)(.*)$ backrefs: true line: \1 \2 \3 \4,nodev \5 when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82742-8 - DISA-STIG-RHEL-08-010600 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_nodev_removable_partitions - no_reboot_needed - name: Ensure permission noexec are set on var_removable_partition lineinfile: path: /etc/fstab regexp: ^\s*({{ var_removable_partition }})\s+([^\s]*)\s+([^\s]*)\s+([^\s]*)(.*)$ backrefs: true line: \1 \2 \3 \4,noexec \5 when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82746-9 - DISA-STIG-RHEL-08-010610 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_noexec_removable_partitions - no_reboot_needed - name: Ensure permission nosuid are set on var_removable_partition lineinfile: path: /etc/fstab regexp: ^\s*({{ var_removable_partition }})\s+([^\s]*)\s+([^\s]*)\s+([^\s]*)(.*)$ backrefs: true line: \1 \2 \3 \4,nosuid \5 when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82744-4 - DISA-STIG-RHEL-08-010620 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_nosuid_removable_partitions - no_reboot_needed - name: 'Add nodev Option to /tmp: Check information associated to mountpoint' command: findmnt --fstab '/tmp' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82623-0 - DISA-STIG-RHEL-08-040123 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /tmp: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82623-0 - DISA-STIG-RHEL-08-040123 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /tmp: If /tmp not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /tmp - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82623-0 - DISA-STIG-RHEL-08-040123 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /tmp: Make sure nodev option is part of the to /tmp options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nodev'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nodev" not in mount_info.options tags: - CCE-82623-0 - DISA-STIG-RHEL-08-040123 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /tmp: Ensure /tmp is mounted with nodev option' mount: path: /tmp src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82623-0 - DISA-STIG-RHEL-08-040123 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nodev - no_reboot_needed - name: 'Add noexec Option to /tmp: Check information associated to mountpoint' command: findmnt --fstab '/tmp' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82139-7 - DISA-STIG-RHEL-08-040125 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /tmp: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82139-7 - DISA-STIG-RHEL-08-040125 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /tmp: If /tmp not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /tmp - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82139-7 - DISA-STIG-RHEL-08-040125 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /tmp: Make sure noexec option is part of the to /tmp options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',noexec'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "noexec" not in mount_info.options tags: - CCE-82139-7 - DISA-STIG-RHEL-08-040125 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /tmp: Ensure /tmp is mounted with noexec option' mount: path: /tmp src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82139-7 - DISA-STIG-RHEL-08-040125 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_noexec - no_reboot_needed - name: 'Add nosuid Option to /tmp: Check information associated to mountpoint' command: findmnt --fstab '/tmp' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82140-5 - DISA-STIG-RHEL-08-040124 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /tmp: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82140-5 - DISA-STIG-RHEL-08-040124 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /tmp: If /tmp not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /tmp - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82140-5 - DISA-STIG-RHEL-08-040124 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /tmp: Make sure nosuid option is part of the to /tmp options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-82140-5 - DISA-STIG-RHEL-08-040124 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /tmp: Ensure /tmp is mounted with nosuid option' mount: path: /tmp src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82140-5 - DISA-STIG-RHEL-08-040124 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_tmp_nosuid - no_reboot_needed - name: 'Add nodev Option to /var/log/audit: Check information associated to mountpoint' command: findmnt --fstab '/var/log/audit' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82080-3 - DISA-STIG-RHEL-08-040129 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log/audit: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82080-3 - DISA-STIG-RHEL-08-040129 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log/audit: If /var/log/audit not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/log/audit - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82080-3 - DISA-STIG-RHEL-08-040129 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log/audit: Make sure nodev option is part of the to /var/log/audit options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nodev'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nodev" not in mount_info.options tags: - CCE-82080-3 - DISA-STIG-RHEL-08-040129 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log/audit: Ensure /var/log/audit is mounted with nodev option' mount: path: /var/log/audit src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82080-3 - DISA-STIG-RHEL-08-040129 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nodev - no_reboot_needed - name: 'Add noexec Option to /var/log/audit: Check information associated to mountpoint' command: findmnt --fstab '/var/log/audit' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82975-4 - DISA-STIG-RHEL-08-040131 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log/audit: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82975-4 - DISA-STIG-RHEL-08-040131 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log/audit: If /var/log/audit not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/log/audit - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82975-4 - DISA-STIG-RHEL-08-040131 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log/audit: Make sure noexec option is part of the to /var/log/audit options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',noexec'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "noexec" not in mount_info.options tags: - CCE-82975-4 - DISA-STIG-RHEL-08-040131 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log/audit: Ensure /var/log/audit is mounted with noexec option' mount: path: /var/log/audit src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82975-4 - DISA-STIG-RHEL-08-040131 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_noexec - no_reboot_needed - name: 'Add nosuid Option to /var/log/audit: Check information associated to mountpoint' command: findmnt --fstab '/var/log/audit' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82921-8 - DISA-STIG-RHEL-08-040130 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log/audit: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82921-8 - DISA-STIG-RHEL-08-040130 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log/audit: If /var/log/audit not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/log/audit - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82921-8 - DISA-STIG-RHEL-08-040130 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log/audit: Make sure nosuid option is part of the to /var/log/audit options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-82921-8 - DISA-STIG-RHEL-08-040130 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log/audit: Ensure /var/log/audit is mounted with nosuid option' mount: path: /var/log/audit src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log/audit" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82921-8 - DISA-STIG-RHEL-08-040130 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_audit_nosuid - no_reboot_needed - name: 'Add nodev Option to /var/log: Check information associated to mountpoint' command: findmnt --fstab '/var/log' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82077-9 - DISA-STIG-RHEL-08-040126 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82077-9 - DISA-STIG-RHEL-08-040126 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log: If /var/log not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/log - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82077-9 - DISA-STIG-RHEL-08-040126 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log: Make sure nodev option is part of the to /var/log options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nodev'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nodev" not in mount_info.options tags: - CCE-82077-9 - DISA-STIG-RHEL-08-040126 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nodev - no_reboot_needed - name: 'Add nodev Option to /var/log: Ensure /var/log is mounted with nodev option' mount: path: /var/log src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82077-9 - DISA-STIG-RHEL-08-040126 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nodev - no_reboot_needed - name: 'Add noexec Option to /var/log: Check information associated to mountpoint' command: findmnt --fstab '/var/log' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82008-4 - DISA-STIG-RHEL-08-040128 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82008-4 - DISA-STIG-RHEL-08-040128 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log: If /var/log not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/log - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82008-4 - DISA-STIG-RHEL-08-040128 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log: Make sure noexec option is part of the to /var/log options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',noexec'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "noexec" not in mount_info.options tags: - CCE-82008-4 - DISA-STIG-RHEL-08-040128 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_noexec - no_reboot_needed - name: 'Add noexec Option to /var/log: Ensure /var/log is mounted with noexec option' mount: path: /var/log src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82008-4 - DISA-STIG-RHEL-08-040128 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_noexec - no_reboot_needed - name: 'Add nosuid Option to /var/log: Check information associated to mountpoint' command: findmnt --fstab '/var/log' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82065-4 - DISA-STIG-RHEL-08-040127 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82065-4 - DISA-STIG-RHEL-08-040127 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log: If /var/log not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/log - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82065-4 - DISA-STIG-RHEL-08-040127 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log: Make sure nosuid option is part of the to /var/log options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-82065-4 - DISA-STIG-RHEL-08-040127 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/log: Ensure /var/log is mounted with nosuid option' mount: path: /var/log src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/log" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82065-4 - DISA-STIG-RHEL-08-040127 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-MP-7 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_log_nosuid - no_reboot_needed - name: 'Add nodev Option to /var/tmp: Check information associated to mountpoint' command: findmnt --fstab '/var/tmp' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82068-8 - DISA-STIG-RHEL-08-040132 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /var/tmp: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82068-8 - DISA-STIG-RHEL-08-040132 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /var/tmp: If /var/tmp not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/tmp - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82068-8 - DISA-STIG-RHEL-08-040132 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /var/tmp: Make sure nodev option is part of the to /var/tmp options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nodev'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nodev" not in mount_info.options tags: - CCE-82068-8 - DISA-STIG-RHEL-08-040132 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nodev - no_reboot_needed - name: 'Add nodev Option to /var/tmp: Ensure /var/tmp is mounted with nodev option' mount: path: /var/tmp src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82068-8 - DISA-STIG-RHEL-08-040132 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nodev - no_reboot_needed - name: 'Add noexec Option to /var/tmp: Check information associated to mountpoint' command: findmnt --fstab '/var/tmp' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82151-2 - DISA-STIG-RHEL-08-040134 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /var/tmp: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82151-2 - DISA-STIG-RHEL-08-040134 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /var/tmp: If /var/tmp not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/tmp - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82151-2 - DISA-STIG-RHEL-08-040134 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /var/tmp: Make sure noexec option is part of the to /var/tmp options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',noexec'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "noexec" not in mount_info.options tags: - CCE-82151-2 - DISA-STIG-RHEL-08-040134 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_noexec - no_reboot_needed - name: 'Add noexec Option to /var/tmp: Ensure /var/tmp is mounted with noexec option' mount: path: /var/tmp src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82151-2 - DISA-STIG-RHEL-08-040134 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_noexec - no_reboot_needed - name: 'Add nosuid Option to /var/tmp: Check information associated to mountpoint' command: findmnt --fstab '/var/tmp' register: device_name failed_when: device_name.rc > 1 changed_when: false when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) tags: - CCE-82154-6 - DISA-STIG-RHEL-08-040133 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/tmp: Create mount_info dictionary variable' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - '{{ device_name.stdout_lines[0].split() | list | lower }}' - '{{ device_name.stdout_lines[1].split() | list }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length > 0) tags: - CCE-82154-6 - DISA-STIG-RHEL-08-040133 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/tmp: If /var/tmp not mounted, craft mount_info manually' set_fact: mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}' with_together: - - target - source - fstype - options - - /var/tmp - '' - '' - defaults when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - ("--fstab" | length == 0) - device_name.stdout is defined and device_name.stdout_lines is defined - (device_name.stdout | length == 0) tags: - CCE-82154-6 - DISA-STIG-RHEL-08-040133 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/tmp: Make sure nosuid option is part of the to /var/tmp options' set_fact: mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',nosuid'' }) }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined and "nosuid" not in mount_info.options tags: - CCE-82154-6 - DISA-STIG-RHEL-08-040133 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nosuid - no_reboot_needed - name: 'Add nosuid Option to /var/tmp: Ensure /var/tmp is mounted with nosuid option' mount: path: /var/tmp src: '{{ mount_info.source }}' opts: '{{ mount_info.options }}' state: mounted fstype: '{{ mount_info.fstype }}' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and "/var/tmp" in ansible_mounts | map(attribute="mount") | list ) - mount_info is defined - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab" | length == 0) tags: - CCE-82154-6 - DISA-STIG-RHEL-08-040133 - configure_strategy - high_disruption - low_complexity - medium_severity - mount_option_var_tmp_nosuid - no_reboot_needed - name: Ensure kernel module 'uvcvideo' is disabled lineinfile: create: true dest: /etc/modprobe.d/uvcvideo.conf regexp: install\s+uvcvideo line: install uvcvideo /bin/false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86960-2 - DISA-STIG-RHEL-08-040020 - NIST-800-53-CM-7 (5) (b) - NIST-800-53-CM-7 (a) - disable_strategy - kernel_module_uvcvideo_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: Ensure kernel module 'uvcvideo' is blacklisted lineinfile: create: true dest: /etc/modprobe.d/uvcvideo.conf regexp: ^blacklist uvcvideo$ line: blacklist uvcvideo when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86960-2 - DISA-STIG-RHEL-08-040020 - NIST-800-53-CM-7 (5) (b) - NIST-800-53-CM-7 (a) - disable_strategy - kernel_module_uvcvideo_disabled - low_complexity - medium_disruption - medium_severity - reboot_required - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.core_pattern.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82215-5 - DISA-STIG-RHEL-08-010671 - NIST-800-53-SC-7(10) - PCI-DSSv4-3.3.1 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_core_pattern - name: Comment out any occurrences of kernel.core_pattern from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.core_pattern replace: '#kernel.core_pattern' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82215-5 - DISA-STIG-RHEL-08-010671 - NIST-800-53-SC-7(10) - PCI-DSSv4-3.3.1 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_core_pattern - name: Ensure sysctl kernel.core_pattern is set to |/bin/false sysctl: name: kernel.core_pattern value: '|/bin/false' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82215-5 - DISA-STIG-RHEL-08-010671 - NIST-800-53-SC-7(10) - PCI-DSSv4-3.3.1 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_core_pattern - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.dmesg_restrict.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80913-7 - DISA-STIG-RHEL-08-010375 - NIST-800-171-3.1.5 - NIST-800-53-SI-11(a) - NIST-800-53-SI-11(b) - disable_strategy - low_complexity - low_severity - medium_disruption - reboot_required - sysctl_kernel_dmesg_restrict - name: Comment out any occurrences of kernel.dmesg_restrict from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.dmesg_restrict replace: '#kernel.dmesg_restrict' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80913-7 - DISA-STIG-RHEL-08-010375 - NIST-800-171-3.1.5 - NIST-800-53-SI-11(a) - NIST-800-53-SI-11(b) - disable_strategy - low_complexity - low_severity - medium_disruption - reboot_required - sysctl_kernel_dmesg_restrict - name: Ensure sysctl kernel.dmesg_restrict is set to 1 sysctl: name: kernel.dmesg_restrict value: '1' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80913-7 - DISA-STIG-RHEL-08-010375 - NIST-800-171-3.1.5 - NIST-800-53-SI-11(a) - NIST-800-53-SI-11(b) - disable_strategy - low_complexity - low_severity - medium_disruption - reboot_required - sysctl_kernel_dmesg_restrict - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.kexec_load_disabled.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80952-5 - DISA-STIG-RHEL-08-010372 - NIST-800-53-CM-6 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_kexec_load_disabled - name: Comment out any occurrences of kernel.kexec_load_disabled from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.kexec_load_disabled replace: '#kernel.kexec_load_disabled' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80952-5 - DISA-STIG-RHEL-08-010372 - NIST-800-53-CM-6 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_kexec_load_disabled - name: Ensure sysctl kernel.kexec_load_disabled is set to 1 sysctl: name: kernel.kexec_load_disabled value: '1' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80952-5 - DISA-STIG-RHEL-08-010372 - NIST-800-53-CM-6 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_kexec_load_disabled - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.perf_event_paranoid.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81054-9 - DISA-STIG-RHEL-08-010376 - NIST-800-53-AC-6 - disable_strategy - low_complexity - low_severity - medium_disruption - reboot_required - sysctl_kernel_perf_event_paranoid - name: Comment out any occurrences of kernel.perf_event_paranoid from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.perf_event_paranoid replace: '#kernel.perf_event_paranoid' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81054-9 - DISA-STIG-RHEL-08-010376 - NIST-800-53-AC-6 - disable_strategy - low_complexity - low_severity - medium_disruption - reboot_required - sysctl_kernel_perf_event_paranoid - name: Ensure sysctl kernel.perf_event_paranoid is set to 2 sysctl: name: kernel.perf_event_paranoid value: '2' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81054-9 - DISA-STIG-RHEL-08-010376 - NIST-800-53-AC-6 - disable_strategy - low_complexity - low_severity - medium_disruption - reboot_required - sysctl_kernel_perf_event_paranoid - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.unprivileged_bpf_disabled.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82974-7 - DISA-STIG-RHEL-08-040281 - NIST-800-53-AC-6 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_unprivileged_bpf_disabled - name: Comment out any occurrences of kernel.unprivileged_bpf_disabled from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.unprivileged_bpf_disabled replace: '#kernel.unprivileged_bpf_disabled' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82974-7 - DISA-STIG-RHEL-08-040281 - NIST-800-53-AC-6 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_unprivileged_bpf_disabled - name: Ensure sysctl kernel.unprivileged_bpf_disabled is set to 1 sysctl: name: kernel.unprivileged_bpf_disabled value: '1' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82974-7 - DISA-STIG-RHEL-08-040281 - NIST-800-53-AC-6 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_unprivileged_bpf_disabled - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.yama.ptrace_scope.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80953-3 - DISA-STIG-RHEL-08-040282 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_yama_ptrace_scope - name: Comment out any occurrences of kernel.yama.ptrace_scope from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.yama.ptrace_scope replace: '#kernel.yama.ptrace_scope' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80953-3 - DISA-STIG-RHEL-08-040282 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_yama_ptrace_scope - name: Ensure sysctl kernel.yama.ptrace_scope is set to 1 sysctl: name: kernel.yama.ptrace_scope value: '1' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80953-3 - DISA-STIG-RHEL-08-040282 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_yama_ptrace_scope - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*net.core.bpf_jit_harden.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82934-1 - DISA-STIG-RHEL-08-040286 - NIST-800-53-CM-6 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_core_bpf_jit_harden - name: Comment out any occurrences of net.core.bpf_jit_harden from config files replace: path: '{{ item.path }}' regexp: ^[\s]*net.core.bpf_jit_harden replace: '#net.core.bpf_jit_harden' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82934-1 - DISA-STIG-RHEL-08-040286 - NIST-800-53-CM-6 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_core_bpf_jit_harden - name: Ensure sysctl net.core.bpf_jit_harden is set to 2 sysctl: name: net.core.bpf_jit_harden value: '2' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82934-1 - DISA-STIG-RHEL-08-040286 - NIST-800-53-CM-6 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_net_core_bpf_jit_harden - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*user.max_user_namespaces.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82211-4 - DISA-STIG-RHEL-08-040284 - NIST-800-53-CM-6(a) - NIST-800-53-SC-39 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_user_max_user_namespaces - name: Comment out any occurrences of user.max_user_namespaces from config files replace: path: '{{ item.path }}' regexp: ^[\s]*user.max_user_namespaces replace: '#user.max_user_namespaces' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82211-4 - DISA-STIG-RHEL-08-040284 - NIST-800-53-CM-6(a) - NIST-800-53-SC-39 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_user_max_user_namespaces - name: Ensure sysctl user.max_user_namespaces is set to 0 sysctl: name: user.max_user_namespaces value: '0' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82211-4 - DISA-STIG-RHEL-08-040284 - NIST-800-53-CM-6(a) - NIST-800-53-SC-39 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_user_max_user_namespaces - name: Disable acquiring, saving, and processing core dumps - Collect systemd Socket Units Present in the System ansible.builtin.command: cmd: systemctl -q list-unit-files --type socket register: result_systemd_unit_files changed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82881-4 - DISA-STIG-RHEL-08-010672 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_systemd-coredump_disabled - name: Disable acquiring, saving, and processing core dumps - Ensure systemd-coredump.socket is Masked ansible.builtin.systemd: name: systemd-coredump.socket state: stopped enabled: false masked: true when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - result_systemd_unit_files.stdout_lines is search("systemd-coredump.socket") tags: - CCE-82881-4 - DISA-STIG-RHEL-08-010672 - NIST-800-53-SC-7(10) - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_systemd-coredump_disabled - name: Gather the package facts package_facts: manager: auto tags: - CCE-82251-0 - DISA-STIG-RHEL-08-010675 - NIST-800-53-CM-6 - PCI-DSS-Req-3.2 - PCI-DSSv4-3.3.1 - coredump_disable_backtraces - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Disable core dump backtraces block: - name: Check for duplicate values lineinfile: path: /etc/systemd/coredump.conf create: false regexp: ^\s*ProcessSizeMax\s*=\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/systemd/coredump.conf lineinfile: path: /etc/systemd/coredump.conf create: false regexp: ^\s*ProcessSizeMax\s*=\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/systemd/coredump.conf lineinfile: path: /etc/systemd/coredump.conf create: false regexp: ^\s*ProcessSizeMax\s*=\s* line: ProcessSizeMax=0 state: present when: '"systemd" in ansible_facts.packages' tags: - CCE-82251-0 - DISA-STIG-RHEL-08-010675 - NIST-800-53-CM-6 - PCI-DSS-Req-3.2 - PCI-DSSv4-3.3.1 - coredump_disable_backtraces - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-82252-8 - DISA-STIG-RHEL-08-010674 - NIST-800-53-CM-6 - PCI-DSS-Req-3.2 - PCI-DSSv4-3.3.1 - coredump_disable_storage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Disable storing core dump block: - name: Check for duplicate values lineinfile: path: /etc/systemd/coredump.conf create: false regexp: ^\s*Storage\s*=\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/systemd/coredump.conf lineinfile: path: /etc/systemd/coredump.conf create: false regexp: ^\s*Storage\s*=\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/systemd/coredump.conf lineinfile: path: /etc/systemd/coredump.conf create: false regexp: ^\s*Storage\s*=\s* line: Storage=none state: present when: '"systemd" in ansible_facts.packages' tags: - CCE-82252-8 - DISA-STIG-RHEL-08-010674 - NIST-800-53-CM-6 - PCI-DSS-Req-3.2 - PCI-DSSv4-3.3.1 - coredump_disable_storage - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-81038-2 - DISA-STIG-RHEL-08-010673 - NIST-800-53-CM-6 - NIST-800-53-SC-7(10) - PCI-DSSv4-3.3.1 - disable_users_coredumps - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Disable core dumps with limits lineinfile: dest: /etc/security/limits.conf regexp: ^[^#].*core line: '* hard core 0' create: true when: '"pam" in ansible_facts.packages' tags: - CCE-81038-2 - DISA-STIG-RHEL-08-010673 - NIST-800-53-CM-6 - NIST-800-53-SC-7(10) - PCI-DSSv4-3.3.1 - disable_users_coredumps - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.kptr_restrict.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80915-2 - DISA-STIG-RHEL-08-040283 - NIST-800-53-CM-6(a) - NIST-800-53-SC-30 - NIST-800-53-SC-30(2) - NIST-800-53-SC-30(5) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_kptr_restrict - name: Comment out any occurrences of kernel.kptr_restrict from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.kptr_restrict replace: '#kernel.kptr_restrict' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80915-2 - DISA-STIG-RHEL-08-040283 - NIST-800-53-CM-6(a) - NIST-800-53-SC-30 - NIST-800-53-SC-30(2) - NIST-800-53-SC-30(5) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_kptr_restrict - name: Ensure sysctl kernel.kptr_restrict is set sysctl: name: kernel.kptr_restrict value: '{{ sysctl_kernel_kptr_restrict_value }}' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80915-2 - DISA-STIG-RHEL-08-040283 - NIST-800-53-CM-6(a) - NIST-800-53-SC-30 - NIST-800-53-SC-30(2) - NIST-800-53-SC-30(5) - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_kptr_restrict - name: List /etc/sysctl.d/*.conf files find: paths: - /etc/sysctl.d/ - /run/sysctl.d/ - /usr/local/lib/sysctl.d/ contains: ^[\s]*kernel.randomize_va_space.*$ patterns: '*.conf' file_type: any register: find_sysctl_d when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80916-0 - DISA-STIG-RHEL-08-010430 - NIST-800-171-3.1.7 - NIST-800-53-CM-6(a) - NIST-800-53-SC-30 - NIST-800-53-SC-30(2) - PCI-DSS-Req-2.2.1 - PCI-DSSv4-3.3.1 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_randomize_va_space - name: Comment out any occurrences of kernel.randomize_va_space from config files replace: path: '{{ item.path }}' regexp: ^[\s]*kernel.randomize_va_space replace: '#kernel.randomize_va_space' loop: '{{ find_sysctl_d.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80916-0 - DISA-STIG-RHEL-08-010430 - NIST-800-171-3.1.7 - NIST-800-53-CM-6(a) - NIST-800-53-SC-30 - NIST-800-53-SC-30(2) - PCI-DSS-Req-2.2.1 - PCI-DSSv4-3.3.1 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_randomize_va_space - name: Ensure sysctl kernel.randomize_va_space is set to 2 sysctl: name: kernel.randomize_va_space value: '2' sysctl_file: /etc/sysctl.conf state: present reload: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80916-0 - DISA-STIG-RHEL-08-010430 - NIST-800-171-3.1.7 - NIST-800-53-CM-6(a) - NIST-800-53-SC-30 - NIST-800-53-SC-30(2) - PCI-DSS-Req-2.2.1 - PCI-DSSv4-3.3.1 - disable_strategy - low_complexity - medium_disruption - medium_severity - reboot_required - sysctl_kernel_randomize_va_space - name: Gather the package facts package_facts: manager: auto tags: - CCE-80944-2 - DISA-STIG-RHEL-08-010421 - NIST-800-53-CM-6(a) - grub2_page_poison_argument - low_disruption - medium_complexity - medium_severity - reboot_required - restrict_strategy - name: Update grub defaults and the bootloader menu command: /sbin/grubby --update-kernel=ALL --args="page_poison=1" when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"grub2-common" in ansible_facts.packages' tags: - CCE-80944-2 - DISA-STIG-RHEL-08-010421 - NIST-800-53-CM-6(a) - grub2_page_poison_argument - low_disruption - medium_complexity - medium_severity - reboot_required - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-80945-9 - DISA-STIG-RHEL-08-010423 - NIST-800-53-CM-6(a) - grub2_slub_debug_argument - low_disruption - medium_complexity - medium_severity - reboot_required - restrict_strategy - name: Update grub defaults and the bootloader menu command: /sbin/grubby --update-kernel=ALL --args="slub_debug={{ var_slub_debug_options }}" when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - '"grub2-common" in ansible_facts.packages' tags: - CCE-80945-9 - DISA-STIG-RHEL-08-010423 - NIST-800-53-CM-6(a) - grub2_slub_debug_argument - low_disruption - medium_complexity - medium_severity - reboot_required - restrict_strategy - name: Ensure policycoreutils is installed package: name: policycoreutils state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82976-2 - DISA-STIG-RHEL-08-010171 - enable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - package_policycoreutils_installed - name: Configure SELinux Policy block: - name: Check for duplicate values lineinfile: path: /etc/selinux/config create: true regexp: ^SELINUXTYPE= state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/selinux/config lineinfile: path: /etc/selinux/config create: true regexp: ^SELINUXTYPE= state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/selinux/config lineinfile: path: /etc/selinux/config create: true regexp: ^SELINUXTYPE= line: SELINUXTYPE={{ var_selinux_policy_name }} state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80868-3 - DISA-STIG-RHEL-08-010450 - NIST-800-171-3.1.2 - NIST-800-171-3.7.2 - NIST-800-53-AC-3 - NIST-800-53-AC-3(3)(a) - NIST-800-53-AU-9 - NIST-800-53-SC-7(21) - PCI-DSSv4-1.2.6 - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - selinux_policytype - name: Ensure SELinux State is Enforcing block: - name: Check for duplicate values lineinfile: path: /etc/selinux/config create: true regexp: ^SELINUX= state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/selinux/config lineinfile: path: /etc/selinux/config create: true regexp: ^SELINUX= state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/selinux/config lineinfile: path: /etc/selinux/config create: true regexp: ^SELINUX= line: SELINUX={{ var_selinux_state }} state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80869-1 - DISA-STIG-RHEL-08-010170 - NIST-800-171-3.1.2 - NIST-800-171-3.7.2 - NIST-800-53-AC-3 - NIST-800-53-AC-3(3)(a) - NIST-800-53-AU-9 - NIST-800-53-SC-7(21) - high_severity - low_complexity - low_disruption - no_reboot_needed - restrict_strategy - selinux_state - name: Ensure abrt is removed package: name: abrt state: absent tags: - CCE-80948-3 - DISA-STIG-RHEL-08-040001 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_abrt_removed - name: Block Disable service kdump block: - name: Disable service kdump block: - name: Disable service kdump systemd: name: kdump.service enabled: 'no' state: stopped masked: 'yes' rescue: - name: Intentionally ignored previous 'Disable service kdump' failure, service was already disabled meta: noop when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80878-2 - DISA-STIG-RHEL-08-010670 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_kdump_disabled - name: Unit Socket Exists - kdump.socket command: systemctl -q list-unit-files kdump.socket register: socket_file_exists changed_when: false failed_when: socket_file_exists.rc not in [0, 1] check_mode: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80878-2 - DISA-STIG-RHEL-08-010670 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_kdump_disabled - name: Disable socket kdump systemd: name: kdump.socket enabled: 'no' state: stopped masked: 'yes' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - socket_file_exists.stdout_lines is search("kdump.socket",multiline=True) tags: - CCE-80878-2 - DISA-STIG-RHEL-08-010670 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_kdump_disabled - name: Ensure fapolicyd is installed package: name: fapolicyd state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82191-8 - DISA-STIG-RHEL-08-040135 - NIST-800-53-CM-6(a) - NIST-800-53-SI-4(22) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_fapolicyd_installed - name: Enable service fapolicyd block: - name: Gather the package facts package_facts: manager: auto - name: Enable service fapolicyd systemd: name: fapolicyd enabled: 'yes' state: started masked: 'no' when: - '"fapolicyd" in ansible_facts.packages' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82249-4 - DISA-STIG-RHEL-08-040136 - NIST-800-53-CM-6(a) - NIST-800-53-SI-4(22) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_fapolicyd_enabled - name: Configure Fapolicy Module to Employ a Deny-all, Permit-by-exception Policy to Allow the Execution of Authorized Software Programs. - Ensure a Final Rule Denying Everything ansible.builtin.copy: content: | # Red Hat KCS 7003854 (https://access.redhat.com/solutions/7003854) deny perm=any all : all dest: /etc/fapolicyd/rules.d/99-deny-everything.rules owner: root group: fapolicyd mode: '0644' register: result_fapolicyd_final_rule when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86478-5 - DISA-STIG-RHEL-08-040137 - NIST-800-53-CM-6 b - NIST-800-53-CM-7 (2) - NIST-800-53-CM-7 (5) (b) - fapolicy_default_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Fapolicy Module to Employ a Deny-all, Permit-by-exception Policy to Allow the Execution of Authorized Software Programs. - Ensure fapolicyd is Not Permissive ansible.builtin.lineinfile: path: /etc/fapolicyd/fapolicyd.conf regexp: ^(permissive\s*=).*$ line: \1 0 backrefs: true register: result_fapolicyd_enforced when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-86478-5 - DISA-STIG-RHEL-08-040137 - NIST-800-53-CM-6 b - NIST-800-53-CM-7 (2) - NIST-800-53-CM-7 (5) (b) - fapolicy_default_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Fapolicy Module to Employ a Deny-all, Permit-by-exception Policy to Allow the Execution of Authorized Software Programs. - Restart fapolicyd If Permissive Mode or Final Rule is Changed ansible.builtin.service: name: fapolicyd state: restarted when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - result_fapolicyd_final_rule is changed or result_fapolicyd_enforced is changed tags: - CCE-86478-5 - DISA-STIG-RHEL-08-040137 - NIST-800-53-CM-6 b - NIST-800-53-CM-7 (2) - NIST-800-53-CM-7 (5) (b) - fapolicy_default_deny - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure vsftpd is removed package: name: vsftpd state: absent tags: - CCE-82414-4 - DISA-STIG-RHEL-08-040360 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7 - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-CM-7.1(ii) - NIST-800-53-IA-5(1)(c) - NIST-800-53-IA-5(1).1(v) - disable_strategy - high_severity - low_complexity - low_disruption - no_reboot_needed - package_vsftpd_removed - name: Ensure krb5-server is removed package: name: krb5-server state: absent when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85887-8 - DISA-STIG-RHEL-08-010163 - NIST-800-53-IA-7 - NIST-800-53-IA-7.1 - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_krb5-server_removed - name: Find keytab files find: paths: /etc/ patterns: '*.keytab' register: keytab_files when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82175-1 - DISA-STIG-RHEL-08-010161 - disable_strategy - kerberos_disable_no_keytab - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Remove keytab files file: path: '{{ item.path }}' state: absent with_items: '{{ keytab_files.files }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82175-1 - DISA-STIG-RHEL-08-010161 - disable_strategy - kerberos_disable_no_keytab - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Ensure mailx is installed package: name: mailx state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-87036-0 - DISA-STIG-RHEL-08-010358 - NIST-800-53-CM-3(5) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_mailx_installed - name: Ensure postfix is installed package: name: postfix state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-85983-5 - DISA-STIG-RHEL-08-030030 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_postfix_installed - name: Ensure sendmail is removed package: name: sendmail state: absent when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-81039-0 - DISA-STIG-RHEL-08-040002 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - disable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_sendmail_removed - name: Configure System to Forward All Mail From Postmaster to The Root Account block: - name: Check for duplicate values lineinfile: path: /etc/aliases create: true regexp: ^\s*postmaster\s*:\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/aliases lineinfile: path: /etc/aliases create: true regexp: ^\s*postmaster\s*:\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/aliases lineinfile: path: /etc/aliases create: true regexp: ^\s*postmaster\s*:\s* line: 'postmaster: root' state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-89063-2 - DISA-STIG-RHEL-08-030030 - NIST-800-53-AU-5(a) - NIST-800-53-AU-5.1(ii) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - postfix_client_configure_mail_alias_postmaster - name: Check if newaliases command is available ansible.builtin.stat: path: /usr/bin/newaliases register: result_newaliases_present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-89063-2 - DISA-STIG-RHEL-08-030030 - NIST-800-53-AU-5(a) - NIST-800-53-AU-5.1(ii) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - postfix_client_configure_mail_alias_postmaster - name: Update postfix aliases ansible.builtin.command: cmd: newaliases when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - result_newaliases_present.stat.exists tags: - CCE-89063-2 - DISA-STIG-RHEL-08-030030 - NIST-800-53-AU-5(a) - NIST-800-53-AU-5.1(ii) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - postfix_client_configure_mail_alias_postmaster - name: Gather the package facts package_facts: manager: auto tags: - CCE-84054-6 - DISA-STIG-RHEL-08-040290 - low_complexity - low_disruption - medium_severity - no_reboot_needed - postfix_prevent_unrestricted_relay - restrict_strategy - name: Prevent Unrestricted Mail Relaying block: - name: Check for duplicate values lineinfile: path: /etc/postfix/main.cf create: true regexp: ^[ \t]*smtpd_client_restrictions\s*=\s* state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/postfix/main.cf lineinfile: path: /etc/postfix/main.cf create: true regexp: ^[ \t]*smtpd_client_restrictions\s*=\s* state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/postfix/main.cf lineinfile: path: /etc/postfix/main.cf create: true regexp: ^[ \t]*smtpd_client_restrictions\s*=\s* line: smtpd_client_restrictions = permit_mynetworks,reject state: present when: - '"postfix" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84054-6 - DISA-STIG-RHEL-08-040290 - low_complexity - low_disruption - medium_severity - no_reboot_needed - postfix_prevent_unrestricted_relay - restrict_strategy - name: Get nfs and nfs4 mount points, that don't have nodev command: findmnt --fstab --types nfs,nfs4 -O nonodev -n -P register: points_register check_mode: false changed_when: false failed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84052-0 - DISA-STIG-RHEL-08-010640 - NIST-800-53-CM-6(a) - NIST-800-53-MP-2 - configure_strategy - low_complexity - medium_disruption - medium_severity - mount_option_nodev_remote_filesystems - no_reboot_needed - name: Add nodev to nfs and nfs4 mount points mount: path: '{{ item | regex_search(''TARGET="([^"]+)"'',''\1'') | first }}' src: '{{ item | regex_search(''SOURCE="([^"]+)"'',''\1'') | first }}' fstype: '{{ item | regex_search(''FSTYPE="([^"]+)"'',''\1'') | first }}' state: present opts: '{{ item | regex_search(''OPTIONS="([^"]+)"'',''\1'') | first }},nodev' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - (points_register.stdout | length > 0) and '\\x09' not in item with_items: '{{ points_register.stdout_lines }}' tags: - CCE-84052-0 - DISA-STIG-RHEL-08-010640 - NIST-800-53-CM-6(a) - NIST-800-53-MP-2 - configure_strategy - low_complexity - medium_disruption - medium_severity - mount_option_nodev_remote_filesystems - no_reboot_needed - name: Get nfs and nfs4 mount points, that don't have noexec command: findmnt --fstab --types nfs,nfs4 -O nonoexec -n -P register: points_register check_mode: false changed_when: false failed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84050-4 - DISA-STIG-RHEL-08-010630 - NIST-800-53-AC-6 - NIST-800-53-AC-6(10) - NIST-800-53-AC-6(8) - NIST-800-53-CM-6(a) - configure_strategy - low_complexity - medium_disruption - medium_severity - mount_option_noexec_remote_filesystems - no_reboot_needed - name: Add noexec to nfs and nfs4 mount points mount: path: '{{ item | regex_search(''TARGET="([^"]+)"'',''\1'') | first }}' src: '{{ item | regex_search(''SOURCE="([^"]+)"'',''\1'') | first }}' fstype: '{{ item | regex_search(''FSTYPE="([^"]+)"'',''\1'') | first }}' state: present opts: '{{ item | regex_search(''OPTIONS="([^"]+)"'',''\1'') | first }},noexec' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - (points_register.stdout | length > 0) and '\\x09' not in item with_items: '{{ points_register.stdout_lines }}' tags: - CCE-84050-4 - DISA-STIG-RHEL-08-010630 - NIST-800-53-AC-6 - NIST-800-53-AC-6(10) - NIST-800-53-AC-6(8) - NIST-800-53-CM-6(a) - configure_strategy - low_complexity - medium_disruption - medium_severity - mount_option_noexec_remote_filesystems - no_reboot_needed - name: Get nfs and nfs4 mount points, that don't have nosuid command: findmnt --fstab --types nfs,nfs4 -O nonosuid -n -P register: points_register check_mode: false changed_when: false failed_when: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84053-8 - DISA-STIG-RHEL-08-010650 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM6(a) - configure_strategy - low_complexity - medium_disruption - medium_severity - mount_option_nosuid_remote_filesystems - no_reboot_needed - name: Add nosuid to nfs and nfs4 mount points mount: path: '{{ item | regex_search(''TARGET="([^"]+)"'',''\1'') | first }}' src: '{{ item | regex_search(''SOURCE="([^"]+)"'',''\1'') | first }}' fstype: '{{ item | regex_search(''FSTYPE="([^"]+)"'',''\1'') | first }}' state: present opts: '{{ item | regex_search(''OPTIONS="([^"]+)"'',''\1'') | first }},nosuid' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - (points_register.stdout | length > 0) and '\\x09' not in item with_items: '{{ points_register.stdout_lines }}' tags: - CCE-84053-8 - DISA-STIG-RHEL-08-010650 - NIST-800-53-AC-6 - NIST-800-53-AC-6(1) - NIST-800-53-CM6(a) - configure_strategy - low_complexity - medium_disruption - medium_severity - mount_option_nosuid_remote_filesystems - no_reboot_needed - name: Disable chrony daemon from acting as server block: - name: Check for duplicate values lineinfile: path: /etc/chrony.conf create: true regexp: ^\s*port\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/chrony.conf lineinfile: path: /etc/chrony.conf create: true regexp: ^\s*port\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/chrony.conf lineinfile: path: /etc/chrony.conf create: true regexp: ^\s*port\s+ line: port 0 state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82988-7 - DISA-STIG-RHEL-08-030741 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1) - chronyd_client_only - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Disable network management of chrony daemon block: - name: Check for duplicate values lineinfile: path: /etc/chrony.conf create: true regexp: ^\s*cmdport\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/chrony.conf lineinfile: path: /etc/chrony.conf create: true regexp: ^\s*cmdport\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/chrony.conf lineinfile: path: /etc/chrony.conf create: true regexp: ^\s*cmdport\s+ line: cmdport 0 state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82840-0 - DISA-STIG-RHEL-08-030742 - NIST-800-53-CM-7(1) - chronyd_no_chronyc_network - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - name: Gather the package facts package_facts: manager: auto tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Check That /etc/ntp.conf Exist ansible.builtin.stat: path: /etc/ntp.conf register: ntp_conf_exist_result when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Update the Maxpoll Values in /etc/ntp.conf ansible.builtin.replace: path: /etc/ntp.conf regexp: ^(server.*maxpoll)[ ]+[0-9]+(.*)$ replace: \1 {{ var_time_service_set_maxpoll }}\2 when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) - ntp_conf_exist_result.stat.exists tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Set the Maxpoll Values in /etc/ntp.conf ansible.builtin.replace: path: /etc/ntp.conf regexp: (^server\s+((?!maxpoll).)*)$ replace: \1 maxpoll {{ var_time_service_set_maxpoll }}\n when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) - ntp_conf_exist_result.stat.exists tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Check That /etc/chrony.conf Exist ansible.builtin.stat: path: /etc/chrony.conf register: chrony_conf_exist_result when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Set Chrony Path Facts ansible.builtin.set_fact: chrony_path: /etc/chrony.conf when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Get Conf Files from {{ chrony_path | dirname }} ansible.builtin.find: path: '{{ chrony_path | dirname }}' patterns: '*.conf' file_type: file register: chrony_conf_files when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Update the Maxpoll Values in /etc/chrony.conf ansible.builtin.replace: path: '{{ item.path }}' regexp: ^((?:server|pool|peer).*maxpoll)[ ]+[0-9]+(.*)$ replace: \1 {{ var_time_service_set_maxpoll }}\2 loop: '{{ chrony_conf_files.files }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) - chrony_conf_files.matched tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Configure Time Service Maxpoll Interval - Set the Maxpoll Values in /etc/chrony.conf ansible.builtin.replace: path: '{{ item.path }}' regexp: (^(?:server|pool|peer)\s+((?!maxpoll).)*)$ replace: \1 maxpoll {{ var_time_service_set_maxpoll }}\n loop: '{{ chrony_conf_files.files }}' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages ) - chrony_conf_files.matched tags: - CCE-84059-5 - DISA-STIG-RHEL-08-030740 - NIST-800-53-AU-12(1) - NIST-800-53-AU-8(1)(b) - NIST-800-53-CM-6(a) - chronyd_or_ntpd_set_maxpoll - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - name: Ensure rsh-server is removed package: name: rsh-server state: absent tags: - CCE-82184-3 - DISA-STIG-RHEL-08-040010 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-IA-5(1)(c) - PCI-DSSv4-2.2.4 - disable_strategy - high_severity - low_complexity - low_disruption - no_reboot_needed - package_rsh-server_removed - name: Remove Host-Based Authentication Files - Define Excluded (Non-Local) File Systems and Paths ansible.builtin.set_fact: excluded_fstypes: - afs - ceph - cifs - smb3 - smbfs - sshfs - ncpfs - ncp - nfs - nfs4 - gfs - gfs2 - glusterfs - gpfs - pvfs2 - ocfs2 - lustre - davfs - fuse.sshfs excluded_paths: - dev - proc - run - sys search_paths: [] tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Find Relevant Root Directories Ignoring Pre-Defined Excluded Paths ansible.builtin.find: paths: / file_type: directory excludes: '{{ excluded_paths }}' hidden: true recurse: false register: result_relevant_root_dirs tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Include Relevant Root Directories in a List of Paths to be Searched ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.path]) }}' loop: '{{ result_relevant_root_dirs.files }}' tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Increment Search Paths List with Local Partitions Mount Points ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.mount]) }}' loop: '{{ ansible_mounts }}' when: - item.fstype not in excluded_fstypes - item.mount != '/' tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Increment Search Paths List with Local NFS File System Targets ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}' loop: '{{ ansible_mounts }}' when: item.device is search("localhost:") tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Define Rule Specific Facts ansible.builtin.set_fact: shosts_equiv_files: - /shosts.equiv tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Find All shosts.equiv Files in Local File Systems ansible.builtin.command: cmd: find {{ item }} -xdev -type f -name "shosts.equiv" loop: '{{ search_paths }}' changed_when: false register: result_found_shosts_equiv_files tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Create List of shosts.equiv Files Present in Local File Systems ansible.builtin.set_fact: shosts_equiv_files: '{{ shosts_equiv_files | union(item.stdout_lines) | list }}' loop: '{{ result_found_shosts_equiv_files.results }}' tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove Host-Based Authentication Files - Ensure No shosts.equiv Files Are Present in the System ansible.builtin.file: path: '{{ item }}' state: absent loop: '{{ shosts_equiv_files }}' tags: - CCE-84055-3 - DISA-STIG-RHEL-08-010460 - high_severity - low_complexity - low_disruption - no_host_based_files - no_reboot_needed - restrict_strategy - name: Remove User Host-Based Authentication Files - Define Excluded (Non-Local) File Systems and Paths ansible.builtin.set_fact: excluded_fstypes: - afs - ceph - cifs - smb3 - smbfs - sshfs - ncpfs - ncp - nfs - nfs4 - gfs - gfs2 - glusterfs - gpfs - pvfs2 - ocfs2 - lustre - davfs - fuse.sshfs excluded_paths: - dev - proc - run - sys search_paths: [] tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Find Relevant Root Directories Ignoring Pre-Defined Excluded Paths ansible.builtin.find: paths: / file_type: directory excludes: '{{ excluded_paths }}' hidden: true recurse: false register: result_relevant_root_dirs tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Include Relevant Root Directories in a List of Paths to be Searched ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.path]) }}' loop: '{{ result_relevant_root_dirs.files }}' tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Increment Search Paths List with Local Partitions Mount Points ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.mount]) }}' loop: '{{ ansible_mounts }}' when: - item.fstype not in excluded_fstypes - item.mount != '/' tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Increment Search Paths List with Local NFS File System Targets ansible.builtin.set_fact: search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}' loop: '{{ ansible_mounts }}' when: item.device is search("localhost:") tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Define Rule Specific Facts ansible.builtin.set_fact: user_shosts_files: - /.shosts tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Find All .shosts Files in Local File Systems ansible.builtin.command: cmd: find {{ item }} -xdev -type f -name ".shosts" loop: '{{ search_paths }}' changed_when: false register: result_found_shosts_files tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Create List of .shosts Files Present in Local File Systems ansible.builtin.set_fact: user_shosts_files: '{{ user_shosts_files | union(item.stdout_lines) | list }}' loop: '{{ result_found_shosts_files.results }}' tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Remove User Host-Based Authentication Files - Ensure No .shosts Files Are Present in the System ansible.builtin.file: path: '{{ item }}' state: absent loop: '{{ user_shosts_files }}' tags: - CCE-84056-1 - DISA-STIG-RHEL-08-010470 - high_severity - low_complexity - low_disruption - no_reboot_needed - no_user_host_based_files - restrict_strategy - name: Ensure telnet-server is removed package: name: telnet-server state: absent tags: - CCE-82182-7 - DISA-STIG-RHEL-08-040000 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-2.2.2 - PCI-DSSv4-2.2.4 - disable_strategy - high_severity - low_complexity - low_disruption - no_reboot_needed - package_telnet-server_removed - name: Ensure tftp-server is removed package: name: tftp-server state: absent tags: - CCE-82436-7 - DISA-STIG-RHEL-08-040190 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSSv4-2.2.4 - disable_strategy - high_severity - low_complexity - low_disruption - no_reboot_needed - package_tftp-server_removed - name: Gather the package facts package_facts: manager: auto tags: - CCE-82434-2 - DISA-STIG-RHEL-08-040350 - NIST-800-53-AC-6 - NIST-800-53-CM-6(b) - NIST-800-53-CM-7(a) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - tftpd_uses_secure_mode - name: Find out if the file exists and contains the line configuring server arguments find: path: /etc/xinetd.d patterns: tftp contains: ^[\s]+server_args.*$ register: tftpd_secure_config_line when: '"tftp-server" in ansible_facts.packages' tags: - CCE-82434-2 - DISA-STIG-RHEL-08-040350 - NIST-800-53-AC-6 - NIST-800-53-CM-6(b) - NIST-800-53-CM-7(a) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - tftpd_uses_secure_mode - name: Ensure that TFTP server is configured to start with secure directory lineinfile: path: /etc/xinetd.d/tftp regexp: ^[\s]*(server_args[\s]+=[\s]+.*?)(-s[\s]+[/\.\w]+)*(.*)$ line: \1 -s {{ var_tftpd_secure_directory }} \3 state: present backrefs: true when: - '"tftp-server" in ansible_facts.packages' - tftpd_secure_config_line is defined and tftpd_secure_config_line.matched > 0 tags: - CCE-82434-2 - DISA-STIG-RHEL-08-040350 - NIST-800-53-AC-6 - NIST-800-53-CM-6(b) - NIST-800-53-CM-7(a) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - tftpd_uses_secure_mode - name: Insert correct config line to start TFTP server with secure directory lineinfile: path: /etc/xinetd.d/tftp line: server_args = -s {{ var_tftpd_secure_directory }} state: present create: true when: - '"tftp-server" in ansible_facts.packages' - tftpd_secure_config_line is defined and tftpd_secure_config_line.matched == 0 tags: - CCE-82434-2 - DISA-STIG-RHEL-08-040350 - NIST-800-53-AC-6 - NIST-800-53-CM-6(b) - NIST-800-53-CM-7(a) - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - tftpd_uses_secure_mode - name: Enable service rngd block: - name: Gather the package facts package_facts: manager: auto - name: Enable service rngd systemd: name: rngd enabled: 'yes' state: started masked: 'no' when: - '"rng-tools" in ansible_facts.packages' when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.3', '<=') tags: - CCE-82831-9 - DISA-STIG-RHEL-08-010471 - enable_strategy - low_complexity - low_disruption - low_severity - no_reboot_needed - service_rngd_enabled - name: Ensure openssh-server is installed package: name: openssh-server state: present when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83303-8 - DISA-STIG-RHEL-08-040159 - NIST-800-53-CM-6(a) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_openssh-server_installed - name: Enable service sshd block: - name: Gather the package facts package_facts: manager: auto - name: Enable service sshd systemd: name: sshd enabled: 'yes' state: started masked: 'no' when: - '"openssh-server" in ansible_facts.packages' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82426-8 - DISA-STIG-RHEL-08-040160 - NIST-800-171-3.1.13 - NIST-800-171-3.13.8 - NIST-800-171-3.5.4 - NIST-800-53-CM-6(a) - NIST-800-53-SC-8 - NIST-800-53-SC-8(1) - NIST-800-53-SC-8(2) - NIST-800-53-SC-8(3) - NIST-800-53-SC-8(4) - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_sshd_enabled - name: Find root:root-owned keys ansible.builtin.command: find -H /etc/ssh/ -maxdepth 1 -user root -regex ".*_key$" -type f -group root -perm /u+xs,g+xwrs,o+xwrt register: root_owned_keys changed_when: false failed_when: false check_mode: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82424-3 - DISA-STIG-RHEL-08-010490 - NIST-800-171-3.1.13 - NIST-800-171-3.13.10 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - configure_strategy - file_permissions_sshd_private_key - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for root:root-owned keys ansible.builtin.file: path: '{{ item }}' mode: u-xs,g-xwrs,o-xwrt state: file with_items: - '{{ root_owned_keys.stdout_lines }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82424-3 - DISA-STIG-RHEL-08-010490 - NIST-800-171-3.1.13 - NIST-800-171-3.13.10 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - configure_strategy - file_permissions_sshd_private_key - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find root:ssh_keys-owned keys ansible.builtin.command: find -H /etc/ssh/ -maxdepth 1 -user root -regex ".*_key$" -type f -group ssh_keys -perm /u+xs,g+xws,o+xwrt register: dedicated_group_owned_keys changed_when: false failed_when: false check_mode: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82424-3 - DISA-STIG-RHEL-08-010490 - NIST-800-171-3.1.13 - NIST-800-171-3.13.10 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - configure_strategy - file_permissions_sshd_private_key - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for root:ssh_keys-owned keys ansible.builtin.file: path: '{{ item }}' mode: u-xs,g-xws,o-xwrt state: file with_items: - '{{ dedicated_group_owned_keys.stdout_lines }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82424-3 - DISA-STIG-RHEL-08-010490 - NIST-800-171-3.1.13 - NIST-800-171-3.13.10 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - configure_strategy - file_permissions_sshd_private_key - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Find /etc/ssh/ file(s) command: find -H /etc/ssh/ -maxdepth 1 -perm /u+xs,g+xws,o+xwt -type f -regex "^.*\.pub$" register: files_found changed_when: false failed_when: false check_mode: false when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82428-4 - DISA-STIG-RHEL-08-010480 - NIST-800-171-3.1.13 - NIST-800-171-3.13.10 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - configure_strategy - file_permissions_sshd_pub_key - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set permissions for /etc/ssh/ file(s) file: path: '{{ item }}' mode: u-xs,g-xws,o-xwt state: file with_items: - '{{ files_found.stdout_lines }}' when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82428-4 - DISA-STIG-RHEL-08-010480 - NIST-800-171-3.1.13 - NIST-800-171-3.13.10 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6(1) - NIST-800-53-CM-6(a) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - configure_strategy - file_permissions_sshd_pub_key - low_complexity - low_disruption - medium_severity - no_reboot_needed - name: Set SSH Client Alive Count Max block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*ClientAliveCountMax\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*ClientAliveCountMax\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*ClientAliveCountMax\s+ line: ClientAliveCountMax {{ var_sshd_set_keepalive }} state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80907-9 - CJIS-5.5.6 - DISA-STIG-RHEL-08-010200 - NIST-800-171-3.1.11 - NIST-800-53-AC-12 - NIST-800-53-AC-17(a) - NIST-800-53-AC-2(5) - NIST-800-53-CM-6(a) - NIST-800-53-SC-10 - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_set_keepalive - name: Set SSH Client Alive Interval block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*ClientAliveInterval\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*ClientAliveInterval\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*ClientAliveInterval\s+ line: ClientAliveInterval {{ sshd_idle_timeout_value }} state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.5', '<=') tags: - CCE-80906-1 - CJIS-5.5.6 - DISA-STIG-RHEL-08-010201 - NIST-800-171-3.1.11 - NIST-800-53-AC-12 - NIST-800-53-AC-17(a) - NIST-800-53-AC-17(a) - NIST-800-53-AC-2(5) - NIST-800-53-CM-6(a) - NIST-800-53-CM-6(a) - NIST-800-53-SC-10 - PCI-DSS-Req-8.1.8 - PCI-DSSv4-8.2.8 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_set_idle_timeout - name: Disable SSH Access via Empty Passwords block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitEmptyPasswords\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitEmptyPasswords\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitEmptyPasswords\s+ line: PermitEmptyPasswords no state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80896-4 - CJIS-5.5.6 - DISA-STIG-RHEL-08-020330 - NIST-800-171-3.1.1 - NIST-800-171-3.1.5 - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - high_severity - low_complexity - low_disruption - no_reboot_needed - restrict_strategy - sshd_disable_empty_passwords - name: Disable GSSAPI Authentication block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*GSSAPIAuthentication\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*GSSAPIAuthentication\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*GSSAPIAuthentication\s+ line: GSSAPIAuthentication no state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80897-2 - DISA-STIG-RHEL-08-010522 - NIST-800-171-3.1.12 - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_disable_gssapi_auth - name: Disable Kerberos Authentication block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*KerberosAuthentication\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*KerberosAuthentication\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*KerberosAuthentication\s+ line: KerberosAuthentication no state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80898-0 - DISA-STIG-RHEL-08-010521 - NIST-800-171-3.1.12 - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_disable_kerb_auth - name: Disable SSH Root Login block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitRootLogin\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitRootLogin\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitRootLogin\s+ line: PermitRootLogin no state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80901-2 - CJIS-5.5.6 - DISA-STIG-RHEL-08-010550 - NIST-800-171-3.1.1 - NIST-800-171-3.1.5 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6(2) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - NIST-800-53-IA-2 - NIST-800-53-IA-2(5) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_disable_root_login - name: Disable SSH Support for User Known Hosts block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*IgnoreUserKnownHosts\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*IgnoreUserKnownHosts\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*IgnoreUserKnownHosts\s+ line: IgnoreUserKnownHosts yes state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80902-0 - DISA-STIG-RHEL-08-010520 - NIST-800-171-3.1.12 - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_disable_user_known_hosts - name: Disable X11 Forwarding block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*X11Forwarding\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*X11Forwarding\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*X11Forwarding\s+ line: X11Forwarding no state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83360-8 - DISA-STIG-RHEL-08-040340 - NIST-800-53-CM-6(b) - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_disable_x11_forwarding - name: Do Not Allow SSH Environment Options block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitUserEnvironment\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitUserEnvironment\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PermitUserEnvironment\s+ line: PermitUserEnvironment no state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80903-8 - CJIS-5.5.6 - DISA-STIG-RHEL-08-010830 - NIST-800-171-3.1.12 - NIST-800-53-AC-17(a) - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - PCI-DSS-Req-2.2.4 - PCI-DSSv4-2.2.6 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_do_not_permit_user_env - name: Enable Use of Strict Mode Checking block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*StrictModes\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*StrictModes\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*StrictModes\s+ line: StrictModes yes state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80904-6 - DISA-STIG-RHEL-08-010500 - NIST-800-171-3.1.12 - NIST-800-53-AC-17(a) - NIST-800-53-AC-6 - NIST-800-53-CM-6(a) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_enable_strictmodes - name: Enable SSH Warning Banner block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*Banner\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*Banner\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*Banner\s+ line: Banner /etc/issue state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80905-3 - CJIS-5.5.6 - DISA-STIG-RHEL-08-010040 - NIST-800-171-3.1.9 - NIST-800-53-AC-17(a) - NIST-800-53-AC-8(a) - NIST-800-53-AC-8(c) - NIST-800-53-CM-6(a) - PCI-DSS-Req-2.2.4 - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_enable_warning_banner - name: Enable SSH Print Last Log block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PrintLastLog\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PrintLastLog\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*PrintLastLog\s+ line: PrintLastLog yes state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82281-7 - DISA-STIG-RHEL-08-020350 - NIST-800-53-AC-9 - NIST-800-53-AC-9(1) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_print_last_log - name: Force frequent session key renegotiation block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*RekeyLimit\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*RekeyLimit\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*RekeyLimit\s+ line: RekeyLimit {{ var_rekey_limit_size }} {{ var_rekey_limit_time }} state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82177-7 - DISA-STIG-RHEL-08-040161 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - sshd_rekey_limit - name: Setting unquoted shell-style assignment of 'SSH_USE_STRONG_RNG' to '32' in '/etc/sysconfig/sshd' block: - name: Check for duplicate values lineinfile: path: /etc/sysconfig/sshd create: true regexp: ^\s*SSH_USE_STRONG_RNG= state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/sysconfig/sshd lineinfile: path: /etc/sysconfig/sshd create: true regexp: ^\s*SSH_USE_STRONG_RNG= state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/sysconfig/sshd lineinfile: path: /etc/sysconfig/sshd create: true regexp: ^\s*SSH_USE_STRONG_RNG= line: SSH_USE_STRONG_RNG=32 state: present insertbefore: ^# SSH_USE_STRONG_RNG validate: /usr/bin/bash -n %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82462-3 - DISA-STIG-RHEL-08-010292 - low_complexity - low_disruption - low_severity - no_reboot_needed - restrict_strategy - sshd_use_strong_rng - name: Prevent remote hosts from connecting to the proxy display block: - name: Check for duplicate values lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*X11UseLocalhost\s+ state: absent check_mode: true changed_when: false register: dupes - name: Deduplicate values from /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*X11UseLocalhost\s+ state: absent when: dupes.found is defined and dupes.found > 1 - name: Insert correct line to /etc/ssh/sshd_config lineinfile: path: /etc/ssh/sshd_config create: true regexp: (?i)^\s*X11UseLocalhost\s+ line: X11UseLocalhost yes state: present insertbefore: BOF validate: /usr/sbin/sshd -t -f %s when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-84058-7 - DISA-STIG-RHEL-08-040341 - NIST-800-53-CM-6(b) - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy - sshd_x11_use_localhost - name: Gather the package facts package_facts: manager: auto tags: - CCE-86120-3 - DISA-STIG-RHEL-08-010400 - NIST-800-53-IA-2(11) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_certificate_verification - name: Ensure that "certificate_verification" is not set in /etc/sssd/sssd.conf ini_file: path: /etc/sssd/sssd.conf section: sssd option: certificate_verification state: absent mode: 384 when: '"sssd-common" in ansible_facts.packages' tags: - CCE-86120-3 - DISA-STIG-RHEL-08-010400 - NIST-800-53-IA-2(11) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_certificate_verification - name: Ensure that "certificate_verification" is not set in /etc/sssd/conf.d/*.conf ini_file: path: /etc/sssd/conf.d/*.conf section: sssd option: certificate_verification state: absent mode: 384 when: '"sssd-common" in ansible_facts.packages' tags: - CCE-86120-3 - DISA-STIG-RHEL-08-010400 - NIST-800-53-IA-2(11) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_certificate_verification - name: Ensure that "certificate_verification" is set ini_file: path: /etc/sssd/conf.d/certificate_verification.conf section: sssd option: certificate_verification value: ocsp_dgst = {{ var_sssd_certificate_verification_digest_function }} state: present mode: 384 when: '"sssd-common" in ansible_facts.packages' tags: - CCE-86120-3 - DISA-STIG-RHEL-08-010400 - NIST-800-53-IA-2(11) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_certificate_verification - name: Gather the package facts package_facts: manager: auto tags: - CCE-80909-5 - DISA-STIG-RHEL-08-020250 - PCI-DSS-Req-8.3 - PCI-DSSv4-8.4 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_enable_smartcards - name: Test for domain group command: grep '^\s*\[domain\/[^]]*]' /etc/sssd/sssd.conf register: test_grep_domain ignore_errors: true changed_when: false check_mode: false when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80909-5 - DISA-STIG-RHEL-08-020250 - PCI-DSS-Req-8.3 - PCI-DSSv4-8.4 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_enable_smartcards - name: Add default domain group (if no domain there) ini_file: path: /etc/sssd/sssd.conf section: '{{ item.section }}' option: '{{ item.option }}' value: '{{ item.value }}' create: true mode: 384 with_items: - section: sssd option: domains value: default - section: domain/default option: id_provider value: files when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - test_grep_domain.stdout is defined - test_grep_domain.stdout | length < 1 tags: - CCE-80909-5 - DISA-STIG-RHEL-08-020250 - PCI-DSS-Req-8.3 - PCI-DSSv4-8.4 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_enable_smartcards - name: Enable Smartcards in SSSD ini_file: dest: /etc/sssd/sssd.conf section: pam option: pam_cert_auth value: 'True' create: true mode: 384 when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80909-5 - DISA-STIG-RHEL-08-020250 - PCI-DSS-Req-8.3 - PCI-DSSv4-8.4 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_enable_smartcards - name: Enable Smartcards in SSSD - Check if system relies on authselect ansible.builtin.stat: path: /usr/bin/authselect register: result_authselect_present when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-80909-5 - DISA-STIG-RHEL-08-020250 - PCI-DSS-Req-8.3 - PCI-DSSv4-8.4 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_enable_smartcards - name: Enable Smartcards in SSSD - Remediate using authselect block: - name: Enable Smartcards in SSSD - Check integrity of authselect current profile ansible.builtin.command: cmd: authselect check register: result_authselect_check_cmd changed_when: false failed_when: false - name: Enable Smartcards in SSSD - 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: Enable Smartcards in SSSD - Get authselect current features 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: Enable Smartcards in SSSD - Ensure "with-smartcard" feature is enabled using authselect tool ansible.builtin.command: cmd: authselect enable-feature with-smartcard register: result_authselect_enable_feature_cmd when: - result_authselect_check_cmd is success - result_authselect_features.stdout is not search("with-smartcard") - name: Enable Smartcards in SSSD - Ensure authselect changes are applied ansible.builtin.command: cmd: authselect apply-changes -b when: - result_authselect_enable_feature_cmd is not skipped - result_authselect_enable_feature_cmd is success when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - result_authselect_present.stat.exists tags: - CCE-80909-5 - DISA-STIG-RHEL-08-020250 - PCI-DSS-Req-8.3 - PCI-DSSv4-8.4 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_enable_smartcards - name: Enable Smartcards in SSSD - Remediate by directly editing PAM files block: - name: Enable Smartcards in SSSD - Check if expected PAM module line is present in /etc/pam.d/smartcard-auth ansible.builtin.lineinfile: path: /etc/pam.d/smartcard-auth regexp: ^\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: Enable Smartcards in SSSD - Include or update the PAM module line in /etc/pam.d/smartcard-auth block: - name: Enable Smartcards in SSSD - Check if required PAM module line is present in /etc/pam.d/smartcard-auth with different control ansible.builtin.lineinfile: path: /etc/pam.d/smartcard-auth regexp: ^\s*auth\s+.*\s+pam_sss.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: Enable Smartcards in SSSD - Ensure the correct control for the required PAM module line in /etc/pam.d/smartcard-auth ansible.builtin.replace: dest: /etc/pam.d/smartcard-auth regexp: ^(\s*auth\s+).*(\bpam_sss.so.*) replace: \1sufficient \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: Enable Smartcards in SSSD - Ensure the required PAM module line is included in /etc/pam.d/smartcard-auth ansible.builtin.lineinfile: dest: /etc/pam.d/smartcard-auth line: auth sufficient pam_sss.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: Enable Smartcards in SSSD - 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: Enable Smartcards in SSSD - Check if the required PAM module option is present in /etc/pam.d/smartcard-auth ansible.builtin.lineinfile: path: /etc/pam.d/smartcard-auth regexp: ^\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so\s*.*\sallow_missing_name\b state: absent check_mode: true changed_when: false register: result_pam_module_allow_missing_name_option_present - name: Enable Smartcards in SSSD - Ensure the "allow_missing_name" PAM option for "pam_sss.so" is included in /etc/pam.d/smartcard-auth ansible.builtin.lineinfile: path: /etc/pam.d/smartcard-auth backrefs: true 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 when: - result_pam_module_allow_missing_name_option_present.found == 0 - name: Enable Smartcards in SSSD - Check if expected PAM module line is present 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\]' | regex_escape() }}\s+pam_sss.so\s*.* state: absent check_mode: true changed_when: false register: result_pam_line_present - name: Enable Smartcards in SSSD - Include or update the PAM module line in /etc/pam.d/system-auth block: - name: Enable Smartcards in SSSD - Check if required PAM module line is present in /etc/pam.d/system-auth with different control ansible.builtin.lineinfile: path: /etc/pam.d/system-auth regexp: ^\s*auth\s+.*\s+pam_sss.so\s* state: absent check_mode: true changed_when: false register: result_pam_line_other_control_present - name: Enable Smartcards in SSSD - Ensure the correct control for the required PAM module line in /etc/pam.d/system-auth ansible.builtin.replace: dest: /etc/pam.d/system-auth regexp: ^(\s*auth\s+).*(\bpam_sss.so.*) replace: \1\[success=done authinfo_unavail=ignore ignore=ignore default=die\] \2 register: result_pam_module_edit when: - result_pam_line_other_control_present.found == 1 - name: Enable Smartcards in SSSD - Ensure the required PAM module line is included in /etc/pam.d/system-auth ansible.builtin.lineinfile: dest: /etc/pam.d/system-auth line: auth \[success=done authinfo_unavail=ignore ignore=ignore default=die\] pam_sss.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: Enable Smartcards in SSSD - 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: Enable Smartcards in SSSD - Check if the required PAM module option is present 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\]' | regex_escape() }}\s+pam_sss.so\s*.*\stry_cert_auth\b state: absent check_mode: true changed_when: false register: result_pam_module_try_cert_auth_option_present - name: Enable Smartcards in SSSD - Ensure the "try_cert_auth" PAM option for "pam_sss.so" is included in /etc/pam.d/system-auth ansible.builtin.lineinfile: path: /etc/pam.d/system-auth backrefs: true 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 when: - result_pam_module_try_cert_auth_option_present.found == 0 when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - not result_authselect_present.stat.exists tags: - CCE-80909-5 - DISA-STIG-RHEL-08-020250 - PCI-DSS-Req-8.3 - PCI-DSSv4-8.4 - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_enable_smartcards - name: Gather the package facts package_facts: manager: auto tags: - CCE-82460-7 - DISA-STIG-RHEL-08-020290 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(13) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_offline_cred_expiration - name: Test for domain group command: grep '\s*\[domain\/[^]]*]' /etc/sssd/sssd.conf register: test_grep_domain ignore_errors: true changed_when: false check_mode: false when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82460-7 - DISA-STIG-RHEL-08-020290 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(13) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_offline_cred_expiration - name: Add default domain group (if no domain there) ini_file: path: /etc/sssd/sssd.conf section: '{{ item.section }}' option: '{{ item.option }}' value: '{{ item.value }}' create: true mode: 384 with_items: - section: sssd option: domains value: default - section: domain/default option: id_provider value: files when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] - test_grep_domain.stdout is defined - test_grep_domain.stdout | length < 1 tags: - CCE-82460-7 - DISA-STIG-RHEL-08-020290 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(13) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_offline_cred_expiration - name: Configure SSD to Expire Offline Credentials ini_file: dest: /etc/sssd/sssd.conf section: pam option: offline_credentials_expiration value: 1 create: true mode: 384 when: - '"sssd-common" in ansible_facts.packages' - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-82460-7 - DISA-STIG-RHEL-08-020290 - NIST-800-53-CM-6(a) - NIST-800-53-IA-5(13) - configure_strategy - low_complexity - medium_disruption - medium_severity - no_reboot_needed - sssd_offline_cred_expiration - name: Ensure usbguard is installed package: name: usbguard state: present when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and ansible_architecture != "s390x" ) tags: - CCE-82959-8 - DISA-STIG-RHEL-08-040139 - NIST-800-53-CM-8(3) - NIST-800-53-IA-3 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - package_usbguard_installed - name: Enable service usbguard block: - name: Gather the package facts package_facts: manager: auto - name: Enable service usbguard systemd: name: usbguard enabled: 'yes' state: started masked: 'no' when: - '"usbguard" in ansible_facts.packages' when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and ansible_architecture != "s390x" ) tags: - CCE-82853-3 - DISA-STIG-RHEL-08-040141 - NIST-800-53-CM-8(3)(a) - NIST-800-53-IA-3 - enable_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - service_usbguard_enabled - name: Gather the package facts package_facts: manager: auto tags: - CCE-83774-0 - DISA-STIG-RHEL-08-040140 - NIST-800-53-CM-8(3)(a) - NIST-800-53-IA-3 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - usbguard_generate_policy - name: Generate USBGuard Policy block: - name: Gather the package facts package_facts: manager: auto - name: Check that the /etc/usbguard/rules.conf exists stat: path: /etc/usbguard/rules.conf register: policy_file - name: Create USBGuard Policy configuration command: usbguard generate-policy register: policy when: not policy_file.stat.exists or policy_file.stat.size == 0 - name: Copy the Generated Policy configuration to a persistent file copy: content: '{{ policy.stdout }}' dest: /etc/usbguard/rules.conf mode: 384 when: not policy_file.stat.exists or policy_file.stat.size == 0 - name: Add comment into /etc/usbguard/rules.conf when system has no USB devices lineinfile: path: /etc/usbguard/rules.conf line: '# No USB devices found' state: present when: not policy_file.stat.exists or policy_file.stat.size == 0 - name: Enable service usbguard systemd: name: usbguard enabled: 'yes' state: started masked: 'no' when: - ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] and ansible_architecture != "s390x" ) - '"usbguard" in ansible_facts.packages' tags: - CCE-83774-0 - DISA-STIG-RHEL-08-040140 - NIST-800-53-CM-8(3)(a) - NIST-800-53-IA-3 - configure_strategy - low_complexity - low_disruption - medium_severity - no_reboot_needed - usbguard_generate_policy - name: Ensure xorg packages are removed package: name: - xorg-x11-server-Xorg - xorg-x11-server-common - xorg-x11-server-utils - xorg-x11-server-Xwayland state: absent tags: - CCE-83411-9 - DISA-STIG-RHEL-08-040320 - NIST-800-53-CM-6(b) - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - xwindows_remove_packages - name: Switch to multi-user runlevel file: src: /usr/lib/systemd/system/multi-user.target dest: /etc/systemd/system/default.target state: link force: true when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"] tags: - CCE-83380-6 - DISA-STIG-RHEL-08-040321 - NIST-800-53-CM-6(a) - NIST-800-53-CM-7(a) - NIST-800-53-CM-7(b) - low_complexity - low_disruption - medium_severity - reboot_required - restrict_strategy - xwindows_runlevel_target