diff --git a/build-scripts/compile_profiles.py b/build-scripts/compile_profiles.py index 0967252348f..d1ce8984b2f 100644 --- a/build-scripts/compile_profiles.py +++ b/build-scripts/compile_profiles.py @@ -3,6 +3,7 @@ import argparse import sys import os.path +from copy import deepcopy from glob import glob import ssg.build_yaml @@ -36,7 +37,8 @@ def resolve(self, all_profiles): updated_variables.update(self.variables) self.variables = updated_variables - updated_refinements = dict(extended_profile.refine_rules) + extended_refinements = deepcopy(extended_profile.refine_rules) + updated_refinements = self._subtract_refinements(extended_refinements) updated_refinements.update(self.refine_rules) self.refine_rules = updated_refinements @@ -50,6 +52,18 @@ def resolve(self, all_profiles): self.resolved = True + def _subtract_refinements(self, extended_refinements): + """ + Given a dict of rule refinements from the extended profile, + "undo" every refinement prefixed with '!' in this profile. + """ + for rule, refinements in list(self.refine_rules.items()): + if rule.startswith("!"): + for prop, val in refinements: + extended_refinements[rule[1:]].remove((prop, val)) + del self.refine_rules[rule] + return extended_refinements + def create_parser(): parser = argparse.ArgumentParser() diff --git a/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/rule.yml b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/rule.yml index 624b4e7041a..b1307ef3f2e 100644 --- a/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/rule.yml +++ b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/rule.yml @@ -20,6 +20,9 @@ rationale: |- severity: medium +identifiers: + cce@rhel8: 83321-0 + ocil_clause: 'auditing is not enabled at boot time' ocil: |- @@ -28,3 +31,9 @@ ocil: |- No line should be returned, each line returned is a boot entry that doesn't enable audit. platform: machine + +template: + name: zipl_bls_entries_option + vars: + arg_name: audit + arg_value: '1' diff --git a/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/correct_option.pass.sh b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/correct_option.pass.sh new file mode 100644 index 00000000000..7a828837fee --- /dev/null +++ b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/correct_option.pass.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# platform = multi_platform_fedora,Red Hat Enterprise Linux 8 + +# Make sure boot loader entries contain audit=1 +for file in /boot/loader/entries/*.conf +do + if ! grep -q '^options.*audit=1.*$' "$file" ; then + sed -i '/^options / s/$/ audit=1/' "$file" + fi +done + +# Make sure /etc/kernel/cmdline contains audit=1 +if ! grep -qs '^(.*\s)?audit=1(\s.*)?$' /etc/kernel/cmdline ; then + echo "audit=1" >> /etc/kernel/cmdline +fi diff --git a/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/missing_in_cmdline.fail.sh b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/missing_in_cmdline.fail.sh new file mode 100644 index 00000000000..3af83d30d8c --- /dev/null +++ b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/missing_in_cmdline.fail.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# platform = multi_platform_fedora,Red Hat Enterprise Linux 8 + +# Make sure boot loader entries contain audit=1 +for file in /boot/loader/entries/*.conf +do + if ! grep -q '^options.*audit=1.*$' "$file" ; then + sed -i '/^options / s/$/ audit=1/' "$file" + fi +done + +# Make sure /etc/kernel/cmdline doesn't contain audit=1 +sed -Ei 's/(^.*)audit=1(.*?)$/\1\2/' /etc/kernel/cmdline || true diff --git a/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/missing_in_entry.fail.sh b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/missing_in_entry.fail.sh new file mode 100644 index 00000000000..5650cc0a745 --- /dev/null +++ b/linux_os/guide/system/bootloader-zipl/zipl_audit_argument/tests/missing_in_entry.fail.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# platform = multi_platform_fedora,Red Hat Enterprise Linux 8 + +# Remove audit=1 from all boot entries +sed -Ei 's/(^options.*\s)audit=1(.*?)$/\1\2/' /boot/loader/entries/* +# But make sure one boot loader entry contains audit=1 +sed -i '/^options / s/$/ audit=1/' /boot/loader/entries/*rescue.conf +sed -Ei 's/(^options.*\s)\$kernelopts(.*?)$/\1\2/' /boot/loader/entries/*rescue.conf + +# Make sure /etc/kernel/cmdline contains audit=1 +if ! grep -qs '^(.*\s)?audit=1(\s.*)?$' /etc/kernel/cmdline ; then + echo "audit=1" >> /etc/kernel/cmdline +fi diff --git a/linux_os/guide/system/bootloader-zipl/zipl_audit_backlog_limit_argument/rule.yml b/linux_os/guide/system/bootloader-zipl/zipl_audit_backlog_limit_argument/rule.yml index faf114591a4..18391bee6c2 100644 --- a/linux_os/guide/system/bootloader-zipl/zipl_audit_backlog_limit_argument/rule.yml +++ b/linux_os/guide/system/bootloader-zipl/zipl_audit_backlog_limit_argument/rule.yml @@ -19,12 +19,21 @@ rationale: |- severity: medium +identifiers: + cce@rhel8: 83341-8 + ocil_clause: 'audit backlog limit is not configured' ocil: |- To check that all boot entries extend the backlog limit; Check that all boot entries extend the log events queue: -
sudo grep -L "^options\s+.*\baudit_backlog_limit=0\b" /boot/loader/entries/*.conf
+
sudo grep -L "^options\s+.*\baudit_backlog_limit=8192\b" /boot/loader/entries/*.conf
No line should be returned, each line returned is a boot entry that does not extend the log events queue. platform: machine + +template: + name: zipl_bls_entries_option + vars: + arg_name: audit_backlog_limit + arg_value: '8192' diff --git a/linux_os/guide/system/bootloader-zipl/zipl_page_poison_argument/rule.yml b/linux_os/guide/system/bootloader-zipl/zipl_page_poison_argument/rule.yml index 866664c01bd..7ffea8ce6a3 100644 --- a/linux_os/guide/system/bootloader-zipl/zipl_page_poison_argument/rule.yml +++ b/linux_os/guide/system/bootloader-zipl/zipl_page_poison_argument/rule.yml @@ -20,6 +20,9 @@ rationale: |- severity: medium +identifiers: + cce@rhel8: 83351-7 + ocil_clause: 'page allocator poisoning is not enabled' ocil: |- @@ -28,3 +31,9 @@ ocil: |- No line should be returned, each line returned is a boot entry that doesn't enable page poisoning. platform: machine + +template: + name: zipl_bls_entries_option + vars: + arg_name: page_poison + arg_value: '1' diff --git a/linux_os/guide/system/bootloader-zipl/zipl_pti_argument/rule.yml b/linux_os/guide/system/bootloader-zipl/zipl_pti_argument/rule.yml index 2f02d9668c9..6fd10822926 100644 --- a/linux_os/guide/system/bootloader-zipl/zipl_pti_argument/rule.yml +++ b/linux_os/guide/system/bootloader-zipl/zipl_pti_argument/rule.yml @@ -19,6 +19,9 @@ rationale: |- severity: medium +identifiers: + cce@rhel8: 83361-6 + ocil_clause: 'Kernel page-table isolation is not enabled' ocil: |- @@ -27,3 +30,9 @@ ocil: |- No line should be returned, each line returned is a boot entry that doesn't enable page-table isolation . platform: machine + +template: + name: zipl_bls_entries_option + vars: + arg_name: pti + arg_value: 'on' diff --git a/linux_os/guide/system/bootloader-zipl/zipl_slub_debug_argument/rule.yml b/linux_os/guide/system/bootloader-zipl/zipl_slub_debug_argument/rule.yml index 0cb10d3cd83..c499140c35b 100644 --- a/linux_os/guide/system/bootloader-zipl/zipl_slub_debug_argument/rule.yml +++ b/linux_os/guide/system/bootloader-zipl/zipl_slub_debug_argument/rule.yml @@ -8,7 +8,7 @@ description: |- To enable poisoning of SLUB/SLAB objects, check that all boot entries in /boot/loader/entries/*.conf have slub_debug=P included in its options.
- To ensure that new kernels and boot entries continue to extend the audit log events queue, + To ensure that new kernels and boot entries continue to enable poisoning of SLUB/SLAB objects, add slub_debug=P to /etc/kernel/cmdline. rationale: |- @@ -20,6 +20,9 @@ rationale: |- severity: medium +identifiers: + cce@rhel8: 83371-5 + ocil_clause: 'SLUB/SLAB poisoning is not enabled' ocil: |- @@ -28,3 +31,9 @@ ocil: |- No line should be returned, each line returned is a boot entry that does not enable poisoning. platform: machine + +template: + name: zipl_bls_entries_option + vars: + arg_name: slub_debug + arg_value: 'P' diff --git a/linux_os/guide/system/bootloader-zipl/zipl_vsyscall_argument/rule.yml b/linux_os/guide/system/bootloader-zipl/zipl_vsyscall_argument/rule.yml index f79adeb0838..7edd43074f3 100644 --- a/linux_os/guide/system/bootloader-zipl/zipl_vsyscall_argument/rule.yml +++ b/linux_os/guide/system/bootloader-zipl/zipl_vsyscall_argument/rule.yml @@ -17,6 +17,9 @@ rationale: |- severity: medium +identifiers: + cce@rhel8: 83381-4 + ocil_clause: 'vsyscalls are enabled' ocil: |- @@ -25,3 +28,9 @@ ocil: |- No line should be returned, each line returned is a boot entry that doesn't disable virtual syscalls. platform: machine + +template: + name: zipl_bls_entries_option + vars: + arg_name: vsyscall + arg_value: 'none' diff --git a/rhel8/profiles/ospp.profile b/rhel8/profiles/ospp.profile index 80e4b71fff6..d3732fa8054 100644 --- a/rhel8/profiles/ospp.profile +++ b/rhel8/profiles/ospp.profile @@ -419,3 +419,11 @@ selections: # zIPl specific rules - zipl_bls_entries_only - zipl_bootmap_is_up_to_date + - zipl_audit_argument + - zipl_audit_backlog_limit_argument + - zipl_slub_debug_argument + - zipl_page_poison_argument + - zipl_vsyscall_argument + - zipl_vsyscall_argument.role=unscored + - zipl_vsyscall_argument.severity=info + - zipl_pti_argument diff --git a/rhel8/profiles/stig.profile b/rhel8/profiles/stig.profile index cfc2160be16..53647475aa0 100644 --- a/rhel8/profiles/stig.profile +++ b/rhel8/profiles/stig.profile @@ -49,3 +49,11 @@ selections: # Unselect zIPL rules from OSPP - "!zipl_bls_entries_only" - "!zipl_bootmap_is_up_to_date" + - "!zipl_audit_argument" + - "!zipl_audit_backlog_limit_argument" + - "!zipl_page_poison_argument" + - "!zipl_pti_argument" + - "!zipl_slub_debug_argument" + - "!zipl_vsyscall_argument" + - "!zipl_vsyscall_argument.role=unscored" + - "!zipl_vsyscall_argument.severity=info" diff --git a/shared/references/cce-redhat-avail.txt b/shared/references/cce-redhat-avail.txt index 3df70caa779..0fa6651e10d 100644 --- a/shared/references/cce-redhat-avail.txt +++ b/shared/references/cce-redhat-avail.txt @@ -22,7 +22,6 @@ CCE-83317-8 CCE-83318-6 CCE-83319-4 CCE-83320-2 -CCE-83321-0 CCE-83322-8 CCE-83327-7 CCE-83328-5 @@ -32,7 +31,6 @@ CCE-83333-5 CCE-83336-8 CCE-83339-2 CCE-83340-0 -CCE-83341-8 CCE-83342-6 CCE-83343-4 CCE-83344-2 @@ -40,14 +38,12 @@ CCE-83345-9 CCE-83346-7 CCE-83349-1 CCE-83350-9 -CCE-83351-7 CCE-83352-5 CCE-83353-3 CCE-83354-1 CCE-83355-8 CCE-83356-6 CCE-83358-2 -CCE-83361-6 CCE-83362-4 CCE-83363-2 CCE-83364-0 @@ -57,7 +53,6 @@ CCE-83367-3 CCE-83368-1 CCE-83369-9 CCE-83370-7 -CCE-83371-5 CCE-83372-3 CCE-83373-1 CCE-83374-9 @@ -66,7 +61,6 @@ CCE-83376-4 CCE-83377-2 CCE-83378-0 CCE-83379-8 -CCE-83381-4 CCE-83382-2 CCE-83383-0 CCE-83384-8 diff --git a/shared/templates/template_ANSIBLE_zipl_bls_entries_option b/shared/templates/template_ANSIBLE_zipl_bls_entries_option new file mode 100644 index 00000000000..bccad2267c1 --- /dev/null +++ b/shared/templates/template_ANSIBLE_zipl_bls_entries_option @@ -0,0 +1,52 @@ +# platform = Red Hat Enterprise Linux 8 +# reboot = true +# strategy = configure +# complexity = medium +# disruption = low + +- name: "Ensure BLS boot entries options contain {{{ ARG_NAME_VALUE }}}" + block: + - name: "Check how many boot entries exist " + find: + paths: "/boot/loader/entries/" + patterns: "*.conf" + register: n_entries + + - name: "Check how many boot entries set {{{ ARG_NAME_VALUE }}}" + find: + paths: "/boot/loader/entries/" + contains: "^options .*{{{ ARG_NAME_VALUE }}}.*$" + patterns: "*.conf" + register: n_entries_options + + - name: "Update boot entries options" + command: grubby --update-kernel=ALL --args="{{{ ARG_NAME_VALUE }}}" + when: n_entries is defined and n_entries_options is defined and n_entries.matched != n_entries_options.matched + + - name: "Check if /etc/kernel/cmdline exists" + stat: + path: /etc/kernel/cmdline + register: cmdline_stat + + - name: "Check if /etc/kernel/cmdline contains {{{ ARG_NAME_VALUE }}}" + find: + paths: "/etc/kernel/" + patterns: "cmdline" + contains: "^.*{{{ ARG_NAME_VALUE }}}.*$" + register: cmdline_find + + - name: "Add /etc/kernel/cmdline contains {{{ ARG_NAME_VALUE }}}" + lineinfile: + create: yes + path: "/etc/kernel/cmdline" + line: '{{{ ARG_NAME_VALUE }}}' + when: cmdline_stat is defined and not cmdline_stat.stat.exists + + - name: "Append /etc/kernel/cmdline contains {{{ ARG_NAME_VALUE }}}" + lineinfile: + path: "/etc/kernel/cmdline" + backrefs: yes + regexp: "^(.*)$" + line: '\1 {{{ ARG_NAME_VALUE }}}' + when: cmdline_stat is defined and cmdline_stat.stat.exists and cmdline_find is defined and cmdline_find.matched == 0 + diff --git a/shared/templates/template_BASH_zipl_bls_entries_option b/shared/templates/template_BASH_zipl_bls_entries_option new file mode 100644 index 00000000000..dde8c948f7a --- /dev/null +++ b/shared/templates/template_BASH_zipl_bls_entries_option @@ -0,0 +1,11 @@ +# platform = Red Hat Enterprise Linux 8 + +# Correct BLS option using grubby, which is a thin wrapper around BLS operations +grubby --update-kernel=ALL --args="{{{ ARG_NAME_VALUE }}}" + +# Ensure new kernels and boot entries retain the boot option +if [ ! -f /etc/kernel/cmdline ]; then + echo "{{{ ARG_NAME_VALUE }}}" >> /etc/kernel/cmdline +elif ! grep -q '^(.*\s)?{{{ ARG_NAME_VALUE }}}(\s.*)?$' /etc/kernel/cmdline; then + sed -Ei 's/^(.*)$/\1 {{{ ARG_NAME_VALUE }}}/' /etc/kernel/cmdline +fi diff --git a/shared/templates/template_OVAL_zipl_bls_entries_option b/shared/templates/template_OVAL_zipl_bls_entries_option new file mode 100644 index 00000000000..502d5e7d9aa --- /dev/null +++ b/shared/templates/template_OVAL_zipl_bls_entries_option @@ -0,0 +1,47 @@ + + + + Ensure that BLS-compatible boot loader is configured to run Linux operating system with argument {{{ ARG_NAME_VALUE }}} + {{{- oval_affected(products) }}} + Ensure {{{ ARG_NAME_VALUE }}} option is configured in the 'options' line in /boot/loader/entries/*.conf. + + + + + + + + + + + + + + ^/boot/loader/entries/.*\.conf$ + ^options (.*)$ + 1 + + + + + + + + /etc/kernel/cmdline + ^(.*)$ + 1 + + + + ^(?:.*\s)?{{{ ESCAPED_ARG_NAME_VALUE }}}(?:\s.*)?$ + + diff --git a/ssg/templates.py b/ssg/templates.py index 2795267abd3..a27fbb6cb61 100644 --- a/ssg/templates.py +++ b/ssg/templates.py @@ -375,6 +375,11 @@ def bls_entries_option(data, lang): return data +@template(["ansible", "bash", "oval"]) +def zipl_bls_entries_option(data, lang): + return bls_entries_option(data, lang) + + class Builder(object): """ Class for building all templated content for a given product. diff --git a/tests/data/profile_stability/rhel8/ospp.profile b/tests/data/profile_stability/rhel8/ospp.profile index 08dcccf24cb..5aa35924961 100644 --- a/tests/data/profile_stability/rhel8/ospp.profile +++ b/tests/data/profile_stability/rhel8/ospp.profile @@ -168,6 +168,7 @@ selections: - service_rngd_enabled - service_systemd-coredump_disabled - service_usbguard_enabled +- ssh_client_rekey_limit - sshd_disable_empty_passwords - sshd_disable_gssapi_auth - sshd_disable_kerb_auth @@ -213,8 +214,14 @@ selections: - sysctl_user_max_user_namespaces - timer_dnf-automatic_enabled - usbguard_allow_hid_and_hub +- zipl_audit_argument +- zipl_audit_backlog_limit_argument - zipl_bls_entries_only - zipl_bootmap_is_up_to_date +- zipl_page_poison_argument +- zipl_pti_argument +- zipl_slub_debug_argument +- zipl_vsyscall_argument - var_sshd_set_keepalive=0 - var_rekey_limit_size=1G - var_rekey_limit_time=1hour @@ -238,11 +245,12 @@ selections: - var_accounts_passwords_pam_faillock_deny=3 - var_accounts_passwords_pam_faillock_fail_interval=900 - var_accounts_passwords_pam_faillock_unlock_time=never +- var_ssh_client_rekey_limit_size=1G +- var_ssh_client_rekey_limit_time=1hour - grub2_vsyscall_argument.role=unscored - grub2_vsyscall_argument.severity=info - sysctl_user_max_user_namespaces.role=unscored - sysctl_user_max_user_namespaces.severity=info -- ssh_client_rekey_limit -- var_ssh_client_rekey_limit_size=1G -- var_ssh_client_rekey_limit_time=1hour +- zipl_vsyscall_argument.role=unscored +- zipl_vsyscall_argument.severity=info title: Protection Profile for General Purpose Operating Systems