diff --git a/tests/unit/ssg-module/data/content_dir/controls/abcd-levels.yml b/tests/unit/ssg-module/data/content_dir/controls/abcd-levels.yml
new file mode 100644
index 00000000000..105ebfbe2a5
--- /dev/null
+++ b/tests/unit/ssg-module/data/content_dir/controls/abcd-levels.yml
@@ -0,0 +1,69 @@
+---
+policy: ABCD Benchmark for securing Linux systems with levels
+title: ABCD Benchmark for securing Linux systems with levels
+id: abcd-levels
+version: 1.2.3
+source: https://www.abcd.com/linux.pdf
+levels:
+ - id: low
+ - id: medium
+ inherits_from:
+ - low
+ - id: high
+ inherits_from:
+ - medium
+
+controls:
+ - id: S1
+ title: User session timeout
+
+ - id: S2
+ levels:
+ - low
+ rules:
+ - var_password_pam_minlen=1
+
+ - id: S3
+ levels:
+ - medium
+
+ - id: S4
+ title: Configure authentication
+ controls:
+ - id: S4.a
+ title: Disable administrator accounts
+ levels:
+ - low
+
+ - id: S4.b
+ title: Enforce password quality standards
+ levels:
+ - high
+ rules:
+ - var_password_pam_minlen=2
+
+ # S5, S6 and S7 are used to test if level inheritance is working correctly
+ # when multiple levels select the same rule
+ - id: S5
+ title: Default Crypto Policy
+ levels:
+ - low
+ rules:
+ - configure_crypto_policy
+ - var_system_crypto_policy=default_policy
+
+ - id: S6
+ title: FIPS Crypto Policy
+ levels:
+ - medium
+ rules:
+ - configure_crypto_policy
+ - var_system_crypto_policy=fips
+
+ - id: S7
+ title: Future Crypto Policy
+ levels:
+ - high
+ rules:
+ - configure_crypto_policy
+ - var_system_crypto_policy=future
diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/benchmark.yml b/tests/unit/ssg-module/data/content_dir/linux_os/guide/benchmark.yml
new file mode 100644
index 00000000000..0f8afd3757a
--- /dev/null
+++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/benchmark.yml
@@ -0,0 +1,29 @@
+---
+documentation_complete: true
+
+title: Guide to the Secure Configuration of {{{ full_name }}}
+
+status: draft
+
+description: |
+ This guide presents a catalog of security-relevant configuration settings for {{{ full_name }}}.
+ It is a rendering of content structured in the eXtensible Configuration Checklist Description Format (XCCDF)
+ in order to support security automation. The SCAP content is available in the scap-security-guide
+ package which is developed at {{{ weblink(link="https://www.open-scap.org/security-policies/scap-security-guide") }}}.
+
+notice:
+ id: terms_of_use
+ description: |
+ Do not attempt to implement any of the settings in this guide without first testing them
+ in a non-operational environment. The creators of this guidance assume no responsibility
+ whatsoever for its use by other parties, and makes no guarantees, expressed or implied,
+ about its quality, reliability, or any other characteristic.
+
+front-matter: |
+ The SCAP Security Guide Project
+ {{{ weblink(link="https://www.open-scap.org/security-policies/scap-security-guide") }}}
+
+rear-matter: |
+ Red Hat and Red Hat Enterprise Linux are either registered trademarks or trademarks of
+ Red Hat, Inc. in the United States and other countries. All other names are registered
+ trademarks or trademarks of their respective companies.
diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/configure_crypto_policy/rule.yml b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/configure_crypto_policy/rule.yml
new file mode 100644
index 00000000000..0807706e7d8
--- /dev/null
+++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/configure_crypto_policy/rule.yml
@@ -0,0 +1,46 @@
+documentation_complete: true
+
+title: 'Test Configure System Cryptography Policy'
+
+description: |-
+ This is a modified copy from original rule.yml. For testing purposes only.
+ To configure the system cryptography policy to use ciphers only from the {{{ xccdf_value("var_system_crypto_policy") }}}
+
+rationale: |-
+ Centralized cryptographic policies simplify applying secure ciphers across an operating
+ system and the applications that run on that operating system. Use of weak or untested
+ encryption algorithms undermines the purposes of utilizing encryption to protect data.
+
+severity: high
+
+identifiers:
+ cce@rhel8: CCE-12345-0
+ cce@rhel9: CCE-12345-1
+
+references:
+ disa: CCI-000068,CCI-003123,CCI-002450,CCI-000877,CCI-002418,CCI-001453,CCI-002890
+ hipaa: 164.308(a)(4)(i),164.308(b)(1),164.308(b)(3),164.312(e)(1),164.312(e)(2)(ii)
+ nist: AC-17(a),AC-17(2),CM-6(a),MA-4(6),SC-13,SC-12(2),SC-12(3)
+ ospp: FCS_COP.1(1),FCS_COP.1(2),FCS_COP.1(3),FCS_COP.1(4),FCS_CKM.1,FCS_CKM.2,FCS_TLSC_EXT.1
+ srg: SRG-OS-000396-GPOS-00176,SRG-OS-000393-GPOS-00173,SRG-OS-000394-GPOS-00174
+ stigid@ol8: OL08-00-010020
+ stigid@rhel8: RHEL-08-010020
+
+ocil_clause: 'cryptographic policy is not configured or is configured incorrectly'
+
+ocil: |-
+ To verify that cryptography policy has been configured correctly, run the following command:
+
$ update-crypto-policies --show+ The output should return
{{{ xccdf_value("var_system_crypto_policy") }}}. + +warnings: + - general: |- + The system needs to be rebooted for these changes to take effect. + +fixtext: |- + Configure {{{ full_name }}} to use system cryptography policy. + Run the following command: + + $ sudo update-crypto-policies --set {{{ xccdf_value("var_system_crypto_policy") }}} + +srg_requirement: '{{{ full_name }}} must use {{{ xccdf_value("var_system_crypto_policy") }}} for the system cryptography policy.' diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/file_groupownership_sshd_private_key/rule.yml b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/file_groupownership_sshd_private_key/rule.yml new file mode 100644 index 00000000000..197f842669a --- /dev/null +++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/file_groupownership_sshd_private_key/rule.yml @@ -0,0 +1,37 @@ +documentation_complete: true + +title: 'Test Verify Group Ownership on SSH Server Private *_key Key Files' + +{{% set dedicated_ssh_groupname = groups.get("dedicated_ssh_keyowner", {}).get("name") %}} + +description: |- + SSH server private keys, files that match the
/etc/ssh/*_key
glob, must be
+ group-owned by {{{ dedicated_ssh_groupname if dedicated_ssh_groupname else 'root' }}}
group.
+
+rationale: |-
+ If an unauthorized user obtains the private SSH host key file, the host could be impersonated.
+
+severity: medium
+
+identifiers:
+ cce@rhel8: CCE-12345-2
+ cce@rhel9: CCE-12345-3
+
+ocil_clause: '{{{ ocil_clause_file_group_owner(file="/etc/ssh/*_key", group="root") }}}'
+
+ocil: |-
+ {{{ ocil_file_group_owner(file="/etc/ssh/*_key", group="root") }}}
+
+template:
+ name: file_groupowner
+ vars:
+ filepath:
+ - /etc/ssh/
+ file_regex:
+ - ^.*_key$
+ gid_or_name: '{{{ dedicated_ssh_groupname if dedicated_ssh_groupname else '0' }}}'
+
+warnings:
+ - general: |-
+ Remediation is not possible at bootable container build time because SSH host
+ keys are generated post-deployment.
diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/group.yml b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/group.yml
new file mode 100644
index 00000000000..54da5a2c6d3
--- /dev/null
+++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/group.yml
@@ -0,0 +1,9 @@
+documentation_complete: true
+
+title: Services
+
+description: |-
+ The best protection against vulnerable software is running less software. This section
+ describes how to review the software which {{{ full_name }}} installs on a system and disable
+ software which is not needed. It then enumerates the software packages installed on a default
+ {{{ full_name }}} system and provides guidance about which ones can be safely disabled.
diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/sshd_set_keepalive/rule.yml b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/sshd_set_keepalive/rule.yml
new file mode 100644
index 00000000000..a4f4f5f2a84
--- /dev/null
+++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/sshd_set_keepalive/rule.yml
@@ -0,0 +1,48 @@
+documentation_complete: true
+
+title: 'Test Set SSH Client Alive Count Max'
+
+description: |-
+ The SSH server sends at most ClientAliveCountMax messages during a SSH session and
+ waits for a response from the SSH client. The option ClientAliveInterval configures
+ timeout after each ClientAliveCountMax message.
+
+rationale: |-
+ This ensures a user login will be terminated as soon as the ClientAliveInterval
+ is reached.
+
+severity: medium
+
+identifiers:
+ cce@rhel8: CCE-12345-4
+ cce@rhel9: CCE-12345-5
+
+references:
+ cis-csc: 1,12,13,14,15,16,18,3,5,7,8
+ cis@sle15: 5.2.16
+ cis@ubuntu2204: 5.2.22
+ disa: CCI-001133,CCI-002361
+ hipaa: 164.308(a)(4)(i),164.308(b)(1),164.308(b)(3),164.310(b),164.312(e)(1),164.312(e)(2)(ii)
+ nist: AC-2(5),AC-12,AC-17(a),SC-10,CM-6(a)
+ pcidss: Req-8.1.8
+ srg: SRG-OS-000163-GPOS-00072,SRG-OS-000279-GPOS-00109
+ stigid@ol8: OL08-00-010200
+ stigid@rhel8: RHEL-08-010200
+ stigid@sle15: SLES-15-010320
+ stigid@ubuntu2204: UBTU-22-255030
+
+requires:
+ - sshd_set_idle_timeout
+
+ocil_clause: 'it is commented out or not configured properly'
+
+ocil: |-
+ To ensure ClientAliveInterval is set correctly, run the following command:
+ $ sudo grep ClientAliveCountMax /etc/ssh/sshd_config+ +template: + name: sshd_lineinfile + vars: + parameter: ClientAliveCountMax + xccdf_variable: var_sshd_set_keepalive + datatype: int diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_password_pam_minlen.var b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_password_pam_minlen.var new file mode 100644 index 00000000000..b0c54bd87d2 --- /dev/null +++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_password_pam_minlen.var @@ -0,0 +1,24 @@ +documentation_complete: true + +title: minlen + +description: 'Minimum number of characters in password' + +type: number + +operator: equals + +interactive: false + +options: + 10: 10 + 12: 12 + 14: 14 + 15: 15 + 17: 17 + 18: 18 + 20: 20 + 6: 6 + 7: 7 + 8: 8 + default: 15 diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_sshd_set_keepalive.var b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_sshd_set_keepalive.var new file mode 100644 index 00000000000..e3c85cb2924 --- /dev/null +++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_sshd_set_keepalive.var @@ -0,0 +1,19 @@ +documentation_complete: true + +title: 'SSH Max Keep Alive Count' + +description: 'Specify the maximum number of idle message counts before session is terminated.' + +type: number + +operator: equals + +interactive: false + +options: + 10: 10 + 3: 3 + 5: 5 + 0: 0 + 1: 1 + default: 0 diff --git a/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_system_crypto_policy.var b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_system_crypto_policy.var new file mode 100644 index 00000000000..8b89848d122 --- /dev/null +++ b/tests/unit/ssg-module/data/content_dir/linux_os/guide/test/var_system_crypto_policy.var @@ -0,0 +1,22 @@ +documentation_complete: true + +title: 'The system-provided crypto policies' + +description: |- + Specify the crypto policy for the system. + +type: string + +operator: equals + +interactive: false + +options: + default: DEFAULT + default_policy: DEFAULT + default_nosha1: "DEFAULT:NO-SHA1" + fips: FIPS + fips_ospp: "FIPS:OSPP" + legacy: LEGACY + future: FUTURE + next: NEXT diff --git a/tests/unit/ssg-module/data/content_dir/products/rhel8/product.yml b/tests/unit/ssg-module/data/content_dir/products/rhel8/product.yml new file mode 100644 index 00000000000..ae0ee78ac44 --- /dev/null +++ b/tests/unit/ssg-module/data/content_dir/products/rhel8/product.yml @@ -0,0 +1,109 @@ +product: rhel8 +full_name: Red Hat Enterprise Linux 8 +type: platform + +families: + - rhel + - rhel-like + +major_version_ordinal: 8 + +benchmark_id: RHEL-8 +benchmark_root: "../../linux_os/guide" +components_root: "../../components" + +profiles_root: "./profiles" + +pkg_manager: "yum" + +init_system: "systemd" + +# The fingerprints below are retrieved from https://access.redhat.com/security/team/key +pkg_release: "4ae0493b" +pkg_version: "fd431d51" +aux_pkg_release: "5b32db75" +aux_pkg_version: "d4082792" + +release_key_fingerprint: "567E347AD0044ADE55BA8A5F199E2F91FD431D51" +auxiliary_key_fingerprint: "6A6AA7C97C8890AEC6AEBFE2F76F66C3D4082792" + +groups: + dedicated_ssh_keyowner: + name: ssh_keys + +faillock_path: "/var/log/faillock" + +cpes_root: "../../shared/applicability" +cpes: + - rhel8: + name: "cpe:/o:redhat:enterprise_linux:8" + title: "Red Hat Enterprise Linux 8" + check_id: installed_OS_is_rhel8 + + - rhel8.0: + name: "cpe:/o:redhat:enterprise_linux:8.0" + title: "Red Hat Enterprise Linux 8.0" + check_id: installed_OS_is_rhel8_0 + + - rhel8.1: + name: "cpe:/o:redhat:enterprise_linux:8.1" + title: "Red Hat Enterprise Linux 8.1" + check_id: installed_OS_is_rhel8_1 + + - rhel8.2: + name: "cpe:/o:redhat:enterprise_linux:8.2" + title: "Red Hat Enterprise Linux 8.2" + check_id: installed_OS_is_rhel8_2 + + - rhel8.3: + name: "cpe:/o:redhat:enterprise_linux:8.3" + title: "Red Hat Enterprise Linux 8.3" + check_id: installed_OS_is_rhel8_3 + + - rhel8.4: + name: "cpe:/o:redhat:enterprise_linux:8.4" + title: "Red Hat Enterprise Linux 8.4" + check_id: installed_OS_is_rhel8_4 + + - rhel8.5: + name: "cpe:/o:redhat:enterprise_linux:8.5" + title: "Red Hat Enterprise Linux 8.5" + check_id: installed_OS_is_rhel8_5 + + - rhel8.6: + name: "cpe:/o:redhat:enterprise_linux:8.6" + title: "Red Hat Enterprise Linux 8.6" + check_id: installed_OS_is_rhel8_6 + + - rhel8.7: + name: "cpe:/o:redhat:enterprise_linux:8.7" + title: "Red Hat Enterprise Linux 8.7" + check_id: installed_OS_is_rhel8_7 + + - rhel8.8: + name: "cpe:/o:redhat:enterprise_linux:8.8" + title: "Red Hat Enterprise Linux 8.8" + check_id: installed_OS_is_rhel8_8 + + - rhel8.9: + name: "cpe:/o:redhat:enterprise_linux:8.9" + title: "Red Hat Enterprise Linux 8.9" + check_id: installed_OS_is_rhel8_9 + + - rhel8.10: + name: "cpe:/o:redhat:enterprise_linux:8.10" + title: "Red Hat Enterprise Linux 8.10" + check_id: installed_OS_is_rhel8_10 + +# Mapping of CPE platform to package +platform_package_overrides: + login_defs: "shadow-utils" + +centos_pkg_release: "5ccc5b19" +centos_pkg_version: "8483c65d" +centos_major_version: "8" + +reference_uris: + cis: 'https://www.cisecurity.org/benchmark/red_hat_linux/' + +journald_conf_dir_path: /etc/systemd/journald.conf.d diff --git a/tests/unit/ssg-module/data/content_dir/products/rhel8/profiles/example.profile b/tests/unit/ssg-module/data/content_dir/products/rhel8/profiles/example.profile new file mode 100644 index 00000000000..f2f28a020e8 --- /dev/null +++ b/tests/unit/ssg-module/data/content_dir/products/rhel8/profiles/example.profile @@ -0,0 +1,13 @@ +documentation_complete: true + +title: 'Sample Security Profile for Linux-like OSes' + +description: |- + This profile is an sample for use in documentation and example content. + The selected rules are standard and should pass quickly on most systems. + +selections: + - abcd-levels:all:medium + - file_groupownership_sshd_private_key + - sshd_set_keepalive + - var_sshd_set_keepalive=1 diff --git a/tests/unit/ssg-module/test_profiles.py b/tests/unit/ssg-module/test_profiles.py index c1ac79afd64..8f3649eeb40 100644 --- a/tests/unit/ssg-module/test_profiles.py +++ b/tests/unit/ssg-module/test_profiles.py @@ -1,27 +1,13 @@ import os -import pytest -from ssg.products import ( - get_all, - get_profile_files_from_root, -) +from ssg.products import get_profile_files_from_root from ssg.profiles import ( get_profiles_from_products, _load_product_yaml, ) -# The get_profiles_from_products function interacts with many objects and other functions that -# would be complex to mock. So it will be tested with a real content directory. To make it -# predictable, all existing products will be collected and the first rhel product will be used -# for testing. The decision to use a rhel product is that I am more used to them and I know their -# profiles also use control files. -content_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")) - -def get_first_rhel_product_from_products_dir(): - products = get_all(content_dir) - rhel_products = [product for product in products.linux if "rhel" in product] - return rhel_products[0] +content_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data/content_dir")) def count_profiles_in_products_dir(product): @@ -31,7 +17,7 @@ def count_profiles_in_products_dir(product): def test_get_profiles_from_products(): - products = [get_first_rhel_product_from_products_dir()] + products = ["rhel8"] profiles = get_profiles_from_products(content_dir, products, sorted=True) assert len(profiles) == count_profiles_in_products_dir(products[0])