Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# platform = Red Hat Enterprise Linux 9
# reboot = false
# strategy = restrict
# complexity = low
# disruption = low

{{% set rx_beg = "^[\s]*-a[\s]+always,exit[\s]+" %}}
{{% set rx_b32 = "-F[\s]+arch=b32[\s]+" %}}
{{% set rx_b64 = "-F[\s]+arch=b64[\s]+" %}}
{{% set rx_path = "-F[\s]+path=" ~ xccdf_value("var_accounts_passwords_pam_faillock_dir") ~ "[\s]+" %}}
{{% set rx_perm = "-F[\s]+perm=wa[\s]+" %}}
{{% set rx_auid = "-F[\s]+auid>=" ~ uid_min ~ "[\s]+-F[\s]+auid!=unset[\s]+" %}}
{{% set rx_end = "(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$" %}}

{{{ ansible_instantiate_variables("var_accounts_passwords_pam_faillock_dir") }}}

- name: "{{{ rule_title }}} - Service facts"
ansible.builtin.service_facts:

- name: "{{{ rule_title }}} - Set faillock_audit_rules fact"
ansible.builtin.set_fact:
faillock_audit_rules:
- rule: '-a always,exit -F arch=b32 -F path={{ var_accounts_passwords_pam_faillock_dir }} -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins'
regex: {{{ rx_beg + rx_b32 + rx_path + rx_perm + rx_auid + rx_end }}}
- rule: '-a always,exit -F arch=b64 -F path={{ var_accounts_passwords_pam_faillock_dir }} -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins'
regex: {{{ rx_beg + rx_b64 + rx_path + rx_perm + rx_auid + rx_end }}}

- name: "{{{ rule_title }}} - Update /etc/audit/rules.d/logins.rules to audit faillock"
ansible.builtin.lineinfile:
path: /etc/audit/rules.d/logins.rules
line: "{{ item.rule }}"
regexp: "{{ item.regex }}"
create: yes
mode: 0600
when:
- '"auditd.service" in ansible_facts.services'
register: augenrules_faillock_update_result
with_items: "{{ faillock_audit_rules }}"

- name: "{{{ rule_title }}} - Update /etc/audit/audit.rules to audit faillock"
ansible.builtin.lineinfile:
path: /etc/audit/audit.rules
line: "{{ item.rule }}"
regexp: "{{ item.regex }}"
create: yes
mode: 0600
when:
- '"auditd.service" in ansible_facts.services'
register: auditctl_faillock_update_result
with_items: "{{ faillock_audit_rules }}"

- name: "{{{ rule_title }}} - Restart auditd"
ansible.builtin.command: /usr/sbin/service auditd restart
when:
- augenrules_faillock_update_result is changed or auditctl_faillock_update_result is changed
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# platform = Red Hat Enterprise Linux 9

{{{ bash_instantiate_variables("var_accounts_passwords_pam_faillock_dir") }}}

[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
OTHER_FILTERS="-F path=${var_accounts_passwords_pam_faillock_dir} -F perm=wa"
AUID_FILTERS="-F auid>={{{ uid_min }}} -F auid!=unset"
SYSCALL=""
SYSCALL_GROUPING=""
KEY="logins"

{{{ bash_fix_audit_syscall_rule("augenrules", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}}
{{{ bash_fix_audit_syscall_rule("auditctl", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}}
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<def-group>
<definition class="compliance" id="audit_rules_login_events_faillock" version="1">
{{{ oval_metadata("Record Attempts to Alter Logon and Logout Events - faillock", rule_title=rule_title) }}}

<criteria operator="OR">

<!-- Test the augenrules case -->
<criteria operator="AND">
<extend_definition comment="audit augenrules" definition_ref="audit_rules_augenrules" />

<criterion comment="audit augenrules var_accounts_passwords_pam_faillock_dir" test_ref="test_audit_rules_login_events_faillock_augenrules_32" />
<criterion comment="audit augenrules var_accounts_passwords_pam_faillock_dir" test_ref="test_audit_rules_login_events_faillock_augenrules_64" />

</criteria>

<!-- Test the auditctl case -->
<criteria operator="AND">
<extend_definition comment="audit auditctl" definition_ref="audit_rules_auditctl" />

<criterion comment="audit auditctl var_accounts_passwords_pam_faillock_dir" test_ref="test_audit_rules_login_events_faillock_auditctl_32" />
<criterion comment="audit auditctl var_accounts_passwords_pam_faillock_dir" test_ref="test_audit_rules_login_events_faillock_auditctl_64" />

</criteria>

</criteria>
</definition>



<ind:textfilecontent54_test check="all" comment="audit augenrules var_accounts_passwords_pam_faillock_dir 32" id="test_audit_rules_login_events_faillock_augenrules_32" version="1">
<ind:object object_ref="object_audit_rules_login_events_faillock_augenrules_32" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_faillock_augenrules_32" version="1">
<ind:filepath operation="pattern match">^/etc/audit/rules\.d/.*\.rules$</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_faillock_path_pattern_32"/>
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>
<ind:textfilecontent54_test check="all" comment="audit augenrules var_accounts_passwords_pam_faillock_dir 64" id="test_audit_rules_login_events_faillock_augenrules_64" version="1">
<ind:object object_ref="object_audit_rules_login_events_faillock_augenrules_64" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_faillock_augenrules_64" version="1">
<ind:filepath operation="pattern match">^/etc/audit/rules\.d/.*\.rules$</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_faillock_path_pattern_64"/>
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>
<ind:textfilecontent54_test check="all" comment="audit auditctl var_accounts_passwords_pam_faillock_dir 32" id="test_audit_rules_login_events_faillock_auditctl_32" version="1">
<ind:object object_ref="object_audit_rules_login_events_faillock_auditctl_32" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_faillock_auditctl_32" version="1">
<ind:filepath>/etc/audit/audit.rules</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_faillock_path_pattern_32" />
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>
<ind:textfilecontent54_test check="all" comment="audit auditctl var_accounts_passwords_pam_faillock_dir 64" id="test_audit_rules_login_events_faillock_auditctl_64" version="1">
<ind:object object_ref="object_audit_rules_login_events_faillock_auditctl_64" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_faillock_auditctl_64" version="1">
<ind:filepath>/etc/audit/audit.rules</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_faillock_path_pattern_64" />
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>

<local_variable id="audit_rules_login_events_faillock_path_pattern_32" comment="The composite pattern used to detect if audit has been configured" datatype="string" version="1">
<concat>
<literal_component>^\-a\s+always,exit\s+\-F\s+arch=b32\s+\-F\s+path=</literal_component>

<variable_component var_ref="var_accounts_passwords_pam_faillock_dir"/>

<literal_component>\s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$</literal_component>
</concat>
</local_variable>


<local_variable id="audit_rules_login_events_faillock_path_pattern_64" comment="The composite pattern used to detect if audit has been configured" datatype="string" version="1">
<concat>
<literal_component>^\-a\s+always,exit\s+\-F\s+arch=b64\s+\-F\s+path=</literal_component>

<variable_component var_ref="var_accounts_passwords_pam_faillock_dir"/>

<literal_component>\s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$</literal_component>
</concat>
</local_variable>



<external_variable id="var_accounts_passwords_pam_faillock_dir" comment="variable specifying the path that should be watched by the audit watch" datatype="string" version="1"/>

</def-group>
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ ocil_clause: 'the command does not return a line, or the line is commented out'
ocil: |-
{{{ ocil_audit_rules_watch(xccdf_value("var_accounts_passwords_pam_faillock_dir"), "logins") }}}

{{% if product in ["rhel9"] %}}
warnings:
- general: |-
Note that the OVAL check for this rule accepts audit rules with or without
the <tt>auid</tt> filters (<tt>-F auid&gt;=1000 -F auid!=unset</tt>).
However, the Bash and Ansible remediations will add these filters to ensure
full compliance. This approach ensures compatibility with existing systems
while bringing them into compliance when remediation is applied.
{{% endif %}}

template:
name: audit_rules_watch
vars:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# platform = Red Hat Enterprise Linux 9
# packages = audit
# variables = var_accounts_passwords_pam_faillock_dir=/var/log/faillock

echo "-a always,exit -F arch=b32 -F path=/var/log/faillock -F perm=wa -F auid>=1000 -F auid!=unset -F key=logins" >> /etc/audit/rules.d/logins.rules
echo "-a always,exit -F arch=b64 -F path=/var/log/faillock -F perm=wa -F auid>=1000 -F auid!=unset -F key=logins" >> /etc/audit/rules.d/logins.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
# platform = Red Hat Enterprise Linux 9
# packages = audit
# variables = var_accounts_passwords_pam_faillock_dir=/var/log/faillock

# This test should fail because it's missing the auid filters
echo "-a always,exit -F arch=b32 -F path=/var/log/faillock -F perm=wa -F key=logins" >> /etc/audit/rules.d/logins.rules
echo "-a always,exit -F arch=b64 -F path=/var/log/faillock -F perm=wa -F key=logins" >> /etc/audit/rules.d/logins.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# platform = Red Hat Enterprise Linux 9
# packages = audit
# variables = var_accounts_passwords_pam_faillock_dir=/var/log/faillock

# This test should fail because it's missing the b32 arch rule
echo "-a always,exit -F arch=b64 -F path=/var/log/faillock -F perm=wa -F auid>=1000 -F auid!=unset -F key=logins" >> /etc/audit/rules.d/logins.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# platform = Red Hat Enterprise Linux 9
# reboot = false
# strategy = restrict
# complexity = low
# disruption = low

{{% set rx_beg = "^[\s]*-a[\s]+always,exit[\s]+" %}}
{{% set rx_b32 = "-F[\s]+arch=b32[\s]+" %}}
{{% set rx_b64 = "-F[\s]+arch=b64[\s]+" %}}
{{% set rx_path = "-F[\s]+path=/var/log/lastlog[\s]+" %}}
{{% set rx_perm = "-F[\s]+perm=wa[\s]+" %}}
{{% set rx_auid = "-F[\s]+auid>=" ~ uid_min ~ "[\s]+-F[\s]+auid!=unset[\s]+" %}}
{{% set rx_end = "(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$" %}}

- name: "{{{ rule_title }}} - Service facts"
ansible.builtin.service_facts:

- name: "{{{ rule_title }}} - Set lastlog_audit_rules fact"
ansible.builtin.set_fact:
lastlog_audit_rules:
- rule: '-a always,exit -F arch=b32 -F path=/var/log/lastlog -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins'
regex: {{{ rx_beg + rx_b32 + rx_path + rx_perm + rx_auid + rx_end }}}
- rule: '-a always,exit -F arch=b64 -F path=/var/log/lastlog -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins'
regex: {{{ rx_beg + rx_b64 + rx_path + rx_perm + rx_auid + rx_end }}}

- name: "{{{ rule_title }}} - Update /etc/audit/rules.d/logins.rules to audit lastlog"
ansible.builtin.lineinfile:
path: /etc/audit/rules.d/logins.rules
line: "{{ item.rule }}"
regexp: "{{ item.regex }}"
create: yes
mode: 0600
when:
- '"auditd.service" in ansible_facts.services'
register: augenrules_lastlog_update_result
with_items: "{{ lastlog_audit_rules }}"

- name: "{{{ rule_title }}} - Update /etc/audit/audit.rules to audit lastlog"
ansible.builtin.lineinfile:
path: /etc/audit/audit.rules
line: "{{ item.rule }}"
regexp: "{{ item.regex }}"
create: yes
mode: 0600
when:
- '"auditd.service" in ansible_facts.services'
register: auditctl_lastlog_update_result
with_items: "{{ lastlog_audit_rules }}"

- name: "{{{ rule_title }}} - Restart auditd"
ansible.builtin.command: /usr/sbin/service auditd restart
when:
- augenrules_lastlog_update_result is changed or auditctl_lastlog_update_result is changed
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# platform = Red Hat Enterprise Linux 9

[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
OTHER_FILTERS="-F path=/var/log/lastlog -F perm=wa"
AUID_FILTERS="-F auid>={{{ uid_min }}} -F auid!=unset"
SYSCALL=""
SYSCALL_GROUPING=""
KEY="logins"

{{{ bash_fix_audit_syscall_rule("augenrules", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}}
{{{ bash_fix_audit_syscall_rule("auditctl", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}}
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<def-group>
<definition class="compliance" id="audit_rules_login_events_lastlog" version="1">
{{{ oval_metadata("Record Attempts to Alter Logon and Logout Events - lastlog", rule_title=rule_title) }}}

<criteria operator="OR">

<!-- Test the augenrules case -->
<criteria operator="AND">
<extend_definition comment="audit augenrules" definition_ref="audit_rules_augenrules" />

<criterion comment="audit augenrules lastlog" test_ref="test_audit_rules_login_events_lastlog_augenrules_32" />
<criterion comment="audit augenrules lastlog" test_ref="test_audit_rules_login_events_lastlog_augenrules_64" />

</criteria>

<!-- Test the auditctl case -->
<criteria operator="AND">
<extend_definition comment="audit auditctl" definition_ref="audit_rules_auditctl" />

<criterion comment="audit auditctl lastlog" test_ref="test_audit_rules_login_events_lastlog_auditctl_32" />
<criterion comment="audit auditctl lastlog" test_ref="test_audit_rules_login_events_lastlog_auditctl_64" />

</criteria>

</criteria>
</definition>



<ind:textfilecontent54_test check="all" comment="audit augenrules lastlog 32" id="test_audit_rules_login_events_lastlog_augenrules_32" version="1">
<ind:object object_ref="object_audit_rules_login_events_lastlog_augenrules_32" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_lastlog_augenrules_32" version="1">
<ind:filepath operation="pattern match">^/etc/audit/rules\.d/.*\.rules$</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_lastlog_path_pattern_32"/>
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>
<ind:textfilecontent54_test check="all" comment="audit augenrules lastlog 64" id="test_audit_rules_login_events_lastlog_augenrules_64" version="1">
<ind:object object_ref="object_audit_rules_login_events_lastlog_augenrules_64" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_lastlog_augenrules_64" version="1">
<ind:filepath operation="pattern match">^/etc/audit/rules\.d/.*\.rules$</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_lastlog_path_pattern_64"/>
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>
<ind:textfilecontent54_test check="all" comment="audit auditctl lastlog 32" id="test_audit_rules_login_events_lastlog_auditctl_32" version="1">
<ind:object object_ref="object_audit_rules_login_events_lastlog_auditctl_32" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_lastlog_auditctl_32" version="1">
<ind:filepath>/etc/audit/audit.rules</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_lastlog_path_pattern_32" />
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>
<ind:textfilecontent54_test check="all" comment="audit auditctl lastlog 64" id="test_audit_rules_login_events_lastlog_auditctl_64" version="1">
<ind:object object_ref="object_audit_rules_login_events_lastlog_auditctl_64" />
</ind:textfilecontent54_test>
<ind:textfilecontent54_object id="object_audit_rules_login_events_lastlog_auditctl_64" version="1">
<ind:filepath>/etc/audit/audit.rules</ind:filepath>
<ind:pattern operation="pattern match" var_ref="audit_rules_login_events_lastlog_path_pattern_64" />
<ind:instance datatype="int">1</ind:instance>
</ind:textfilecontent54_object>

<local_variable id="audit_rules_login_events_lastlog_path_pattern_32" comment="The composite pattern used to detect if audit has been configured" datatype="string" version="1">
<concat>
<literal_component>^\-a\s+always,exit\s+\-F\s+arch=b32\s+\-F\s+path=</literal_component>

<literal_component>\/var\/log\/lastlog</literal_component>

<literal_component>\s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$</literal_component>
</concat>
</local_variable>


<local_variable id="audit_rules_login_events_lastlog_path_pattern_64" comment="The composite pattern used to detect if audit has been configured" datatype="string" version="1">
<concat>
<literal_component>^\-a\s+always,exit\s+\-F\s+arch=b64\s+\-F\s+path=</literal_component>

<literal_component>\/var\/log\/lastlog</literal_component>

<literal_component>\s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$</literal_component>
</concat>
</local_variable>



</def-group>
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ ocil_clause: 'the command does not return a line, or the line is commented out'
ocil: |-
{{{ ocil_audit_rules_watch("/var/log/lastlog", "logins") }}}

{{% if product in ["rhel9"] %}}
warnings:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

- general: |-
Note that the OVAL check for this rule accepts audit rules with or without
the <tt>auid</tt> filters (<tt>-F auid&gt;=1000 -F auid!=unset</tt>).
However, the Bash and Ansible remediations will add these filters to ensure
full compliance. This approach ensures compatibility with existing systems
while bringing them into compliance when remediation is applied.
{{% endif %}}

template:
name: audit_rules_watch
vars:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
# platform = Red Hat Enterprise Linux 9
# packages = audit

echo "-a always,exit -F arch=b32 -F path=/var/log/lastlog -F perm=wa -F auid>=1000 -F auid!=unset -k logins" >> /etc/audit/rules.d/logins.rules
echo "-a always,exit -F arch=b64 -F path=/var/log/lastlog -F perm=wa -F auid>=1000 -F auid!=unset -k logins" >> /etc/audit/rules.d/logins.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# platform = Red Hat Enterprise Linux 9
# packages = audit

# This test should fail because it's missing the auid filters
echo "-a always,exit -F arch=b32 -F path=/var/log/lastlog -F perm=wa -k logins" >> /etc/audit/rules.d/logins.rules
echo "-a always,exit -F arch=b64 -F path=/var/log/lastlog -F perm=wa -k logins" >> /etc/audit/rules.d/logins.rules
Loading
Loading