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])