diff --git a/.mailmap b/.mailmap index 18c25954053..b473cf4fd15 100644 --- a/.mailmap +++ b/.mailmap @@ -22,6 +22,7 @@ Ted Brunell Marcus Burghardt Marcus Burghardt <2074099+marcusburghardt@users.noreply.github.com> +Matthew Burket Matthew Burket Frank Caviggia diff --git a/components/chrony.yml b/components/chrony.yml index ae76015a991..bd7d8186c86 100644 --- a/components/chrony.yml +++ b/components/chrony.yml @@ -11,3 +11,4 @@ rules: - file_permissions_etc_chrony_keys - package_chrony_installed - service_chronyd_enabled +- chrony_set_nts diff --git a/components/ntp.yml b/components/ntp.yml index eba55b531f2..ef4ae2efac4 100644 --- a/components/ntp.yml +++ b/components/ntp.yml @@ -11,6 +11,7 @@ rules: - chronyd_or_ntpd_specify_multiple_servers - chronyd_or_ntpd_specify_remote_server - chronyd_run_as_chrony_user +- chrony_set_nts - chronyd_server_directive - chronyd_specify_remote_server - chronyd_sync_clock diff --git a/controls/srg_gpos/SRG-OS-000480-GPOS-00227.yml b/controls/srg_gpos/SRG-OS-000480-GPOS-00227.yml index 2954814b97c..84d8ca01f9f 100644 --- a/controls/srg_gpos/SRG-OS-000480-GPOS-00227.yml +++ b/controls/srg_gpos/SRG-OS-000480-GPOS-00227.yml @@ -244,5 +244,6 @@ controls: - installed_OS_is_vendor_supported - selinux_all_devicefiles_labeled - xwindows_remove_packages + - chrony_set_nts status: automated diff --git a/linux_os/guide/services/ntp/chrony_set_nts/ansible/shared.yml b/linux_os/guide/services/ntp/chrony_set_nts/ansible/shared.yml new file mode 100644 index 00000000000..9a0d7013907 --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/ansible/shared.yml @@ -0,0 +1,48 @@ +# platform = multi_platform_all +# reboot = false +# strategy = restrict +# complexity = low +# disruption = low + +- name: "{{{ rule_title }}} - Check That /etc/ntp.conf Exist" + ansible.builtin.stat: + path: /etc/ntp.conf + register: ntp_conf_exist_result + +- name: "{{{ rule_title }}} - Set the nts Values in /etc/ntp.conf" + ansible.builtin.replace: + path: /etc/ntp.conf + regexp: '(^server\s+((?!nts).)*)$' + replace: '\1 nts\n' + when: ntp_conf_exist_result.stat.exists + +# Chrony, need to hand chrony.conf and any file in chrony.d +# since chrony_conf_path is the full path to chrony.conf +# and includes chrony.conf, that must be handled as well + +- name: "{{{ rule_title }}} - Check That {{{ chrony_conf_path }}} Exist" + ansible.builtin.stat: + path: {{{ chrony_conf_path }}} + register: chrony_conf_exist_result + +- name: "{{{ rule_title }}} - Set the nts Values in {{{ chrony_conf_path }}}" + ansible.builtin.replace: + path: "{{{ chrony_conf_path }}}" + regexp: '(^(?:server|pool|peer)\s+((?!nts).)*)$' + replace: '\1 nts\n' + when: chrony_conf_exist_result.stat.exists + +- name: "{{{ rule_title }}} - Get Conf Files from {{{ chrony_d_path }}}" + ansible.builtin.find: + path: "{{{ chrony_d_path }}}" + patterns: '*.conf' + file_type: file + register: chrony_d_conf_files + +- name: "{{{ rule_title }}} - Set the maxpoll Values in {{{ chrony_d_path }}}" + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: '(^(?:server|pool|peer)\s+((?!maxpoll).)*)$' + replace: '\1 nts\n' + loop: '{{ chrony_d_conf_files.files }}' + when: chrony_d_conf_files.matched diff --git a/linux_os/guide/services/ntp/chrony_set_nts/bash/shared.sh b/linux_os/guide/services/ntp/chrony_set_nts/bash/shared.sh new file mode 100644 index 00000000000..10661cfea63 --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/bash/shared.sh @@ -0,0 +1,23 @@ +# platform = multi_platform_all + +{{% if 'sle' in product or 'ubuntu' in product %}} +pof="/bin/pidof" +{{% else %}} +pof="/usr/sbin/pidof" +{{% endif %}} + +CONFIG_FILES="/etc/ntp.conf" +$pof ntpd || { + CHRONY_D_PATH={{{ chrony_d_path }}} + mapfile -t CONFIG_FILES < <(find ${CHRONY_D_PATH}.* -type f -name '*.conf') + CONFIG_FILES+=({{{ chrony_conf_path }}}) +} + +# get list of ntp files + +for config_file in "${CONFIG_FILES[@]}" ; do + # Add maxpoll to server, pool or peer entries without maxpoll + grep "^\(server\|pool\|peer\)" "$config_file" | grep -v maxpoll | while read -r line ; do + sed -i "s/$line/& nts/" "$config_file" + done +done diff --git a/linux_os/guide/services/ntp/chrony_set_nts/oval/shared.xml b/linux_os/guide/services/ntp/chrony_set_nts/oval/shared.xml new file mode 100644 index 00000000000..84e9cb4fa4b --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/oval/shared.xml @@ -0,0 +1,27 @@ + + + {{{ oval_metadata("Configure the nts setting in /etc/ntp.conf or chrony.conf to use NTS on all time servers.") }}} + + + + + + {{% set filepath_regex = "^(" + chrony_conf_path | replace(".", "\.") + "|" + chrony_d_path | replace(".", "\.") + ".+\.conf)$" %}} + + + + + + + {{{ filepath_regex }}} + ^(?:server|pool|peer)[\s]+[\S]+[\s]+(.*) + 1 + + + + nts + + + diff --git a/linux_os/guide/services/ntp/chrony_set_nts/policy/stig/shared.yml b/linux_os/guide/services/ntp/chrony_set_nts/policy/stig/shared.yml new file mode 100644 index 00000000000..b64ae9d9c4c --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/policy/stig/shared.yml @@ -0,0 +1,17 @@ +srg_requirement: '{{{ full_name }}} must use encryption for NTP communications.' + +vuldiscussion: |- + +checktext: |- + Verify that {{{ full_name }}} uses encryption for NTP communications. + + $ sudo grep nts /etc/ntp.conf /etc/chrony.conf + + server [ntp.server.name] iburst maxpoll 10 nts + + If "nts" is commented out or is missing, this is a finding. + +fixtext: |- + Configure {{{ full_name }}} to use encryption for NTP communications. + + server [ntp.server.name] iburst maxpoll 10 nts diff --git a/linux_os/guide/services/ntp/chrony_set_nts/rule.yml b/linux_os/guide/services/ntp/chrony_set_nts/rule.yml new file mode 100644 index 00000000000..6d1f505980e --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/rule.yml @@ -0,0 +1,23 @@ +documentation_complete: true + +title: 'Configure Time Service to use NTS' + +description: |- + The system should be configured to use time servers that support Network Time Security (NTS). + The specified time server must support NTS and must be configured to use NTS. + To configure NTS for given time server add nts to each server or pool line in {{{ chrony_conf_path }}}. + +rationale: |- + Network Time Security (NTS) uses Transport Layer Security (TLS) to secure Network Time Protocol (NTP) communications. + Not using NTS could allow an attacker to interpret and modify the data sent back from the time server + Inaccurate time stamps make it more difficult to correlate events and can lead to an inaccurate analysis. + Determining the correct time a particular event occurred on a system is critical when conducting forensic analysis and investigating system events. + Sources outside the configured acceptable allowance (drift) may be inaccurate. + +identifiers: + cce@rhel10: CCE-86471-0 + +severity: medium + +platforms: + - package[chrony] diff --git a/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_d_one_pool_missing.fail.sh b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_d_one_pool_missing.fail.sh new file mode 100644 index 00000000000..4963780f8dc --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_d_one_pool_missing.fail.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# packages = chrony +# platform = multi_platform_rhel + +{{{ bash_package_remove("ntp") }}} + +# Remove all server or pool options +sed -i "/^\(server\|pool\).*/d" {{{ chrony_d_path }}}/20-pools.conf + +echo "pool pool.ntp.org iburst" >> {{{ chrony_d_path }}}/20-pools.conf + +systemctl enable chronyd.service + diff --git a/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_d_one_server_missing.fail.sh b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_d_one_server_missing.fail.sh new file mode 100644 index 00000000000..fdfe3896826 --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_d_one_server_missing.fail.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# packages = chrony +# platform = multi_platform_rhel + +{{{ bash_package_remove("ntp") }}} + +# Remove all pool options +sed -i "/^pool.*/d" {{{ chrony_d_path }}}/10-servers.conf + +if ! grep "^server.*maxpoll 10" {{{ chrony_d_path }}}/10-servers.conf ; then + sed -i "s/^server.*/& maxpoll 10/" {{{ chrony_d_path }}}/10-servers.conf +fi + +echo "server test.ntp.org" >> {{{ chrony_d_path }}}/10-servers.conf + +systemctl enable chronyd.service diff --git a/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_no_pool_nor_servers.fail.sh b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_no_pool_nor_servers.fail.sh new file mode 100644 index 00000000000..b858e7f3ce5 --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_no_pool_nor_servers.fail.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# packages = chrony +# remediation = none + +{{{ bash_package_remove("ntp") }}} + +# Remove all pool and server options +sed -i "/^pool.*/d" {{{ chrony_conf_path }}} +sed -i "/^server.*/d" {{{ chrony_conf_path }}} + +systemctl enable chronyd.service diff --git a/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_one_pool_configured.pass.sh b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_one_pool_configured.pass.sh new file mode 100644 index 00000000000..b05fb189269 --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_one_pool_configured.pass.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# packages = chrony + +{{{ bash_package_remove("ntp") }}} + +# Remove all server or pool options +sed -i "/^\(server\|pool\).*/d" {{{ chrony_conf_path }}} + +echo "pool pool.ntp.org iburst nts" >> {{{ chrony_conf_path }}} + +systemctl enable chronyd.service + diff --git a/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_one_pool_missing.fail.sh b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_one_pool_missing.fail.sh new file mode 100644 index 00000000000..402bac2d6c2 --- /dev/null +++ b/linux_os/guide/services/ntp/chrony_set_nts/tests/chrony_one_pool_missing.fail.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# packages = chrony + +{{{ bash_package_remove("ntp") }}} + +# Remove all server or pool options +sed -i "/^\(server\|pool\).*/d" {{{ chrony_conf_path }}} + +echo "pool pool.ntp.org iburst" >> {{{ chrony_conf_path }}} + +systemctl enable chronyd.service + diff --git a/linux_os/guide/services/ntp/chronyd_server_directive/rule.yml b/linux_os/guide/services/ntp/chronyd_server_directive/rule.yml index 968c372931d..de3f82139d8 100644 --- a/linux_os/guide/services/ntp/chronyd_server_directive/rule.yml +++ b/linux_os/guide/services/ntp/chronyd_server_directive/rule.yml @@ -7,6 +7,7 @@ description: |- rationale: |- Depending on the infrastructure being used the pool directive may not be supported. + Using the server directive allows for better control of where the system gets time data from. severity: medium diff --git a/linux_os/guide/services/ntp/file_groupowner_etc_chrony_keys/rule.yml b/linux_os/guide/services/ntp/file_groupowner_etc_chrony_keys/rule.yml index 0dbc4fed2fe..d24259dc98e 100644 --- a/linux_os/guide/services/ntp/file_groupowner_etc_chrony_keys/rule.yml +++ b/linux_os/guide/services/ntp/file_groupowner_etc_chrony_keys/rule.yml @@ -2,13 +2,13 @@ documentation_complete: true title: Verify Group Who Owns /etc/chrony.keys File -description: '{{{ describe_file_group_owner(file="/etc/chrony.keys", group="root") }}}' +description: '{{{ describe_file_group_owner(file="/etc/chrony.keys", group="chrony") }}}' rationale: |- - The ownership of the /etc/chrony.keys file by the root group is important + The ownership of the /etc/chrony.keys file by the chrony group is important because this file hosts chrony cryptographic keys. Protection of this file is critical for system security. Assigning the ownership to - root ensures exclusive control of the chrony cryptography keys. + chrony ensures exclusive control of the chrony cryptography keys. severity: medium @@ -17,17 +17,17 @@ identifiers: cce@rhel9: CCE-86374-6 cce@rhel10: CCE-87112-9 -ocil_clause: '{{{ ocil_clause_file_group_owner(file="/etc/chrony.keys", group="root") }}}' +ocil_clause: '{{{ ocil_clause_file_group_owner(file="/etc/chrony.keys", group="chrony") }}}' ocil: |- - {{{ ocil_file_group_owner(file="/etc/chrony.keys", group="root") }}} + {{{ ocil_file_group_owner(file="/etc/chrony.keys", group="chrony") }}} -fixtext: '{{{ fixtext_file_group_owner(file="/etc/chrony.keys", group="root") }}}' +fixtext: '{{{ fixtext_file_group_owner(file="/etc/chrony.keys", group="chrony") }}}' -srg_requirement: '{{{ srg_requirement_file_group_owner(file="/etc/chrony.keys", group="root") }}}' +srg_requirement: '{{{ srg_requirement_file_group_owner(file="/etc/chrony.keys", group="chrony") }}}' template: name: file_groupowner vars: filepath: /etc/chrony.keys - gid_or_name: root + gid_or_name: chrony diff --git a/linux_os/guide/services/ntp/file_owner_etc_chrony_keys/rule.yml b/linux_os/guide/services/ntp/file_owner_etc_chrony_keys/rule.yml index 113506f1ce4..685943cf9df 100644 --- a/linux_os/guide/services/ntp/file_owner_etc_chrony_keys/rule.yml +++ b/linux_os/guide/services/ntp/file_owner_etc_chrony_keys/rule.yml @@ -5,10 +5,10 @@ title: Verify User Who Owns /etc/chrony.keys File description: '{{{ describe_file_owner(file="/etc/chrony.keys", owner="root") }}}' rationale: |- - The ownership of the /etc/chrony.keys file by the root user is important + The ownership of the /etc/chrony.keys file by the chrony user is important because this file hosts chrony cryptographic keys. Protection of this file is critical for system security. Assigning the ownership to - root ensures exclusive control of the chrony cryptographic keys. + chrony ensures exclusive control of the chrony cryptographic keys. severity: medium diff --git a/shared/references/cce-redhat-avail.txt b/shared/references/cce-redhat-avail.txt index 2925bbf3376..46626ff8f93 100644 --- a/shared/references/cce-redhat-avail.txt +++ b/shared/references/cce-redhat-avail.txt @@ -53,7 +53,6 @@ CCE-86466-0 CCE-86468-6 CCE-86469-4 CCE-86470-2 -CCE-86471-0 CCE-86472-8 CCE-86473-6 CCE-86474-4 diff --git a/shared/schemas/rule_policy_content.json b/shared/schemas/rule_policy_content.json new file mode 100644 index 00000000000..da46f5b4543 --- /dev/null +++ b/shared/schemas/rule_policy_content.json @@ -0,0 +1,20 @@ +{ + "$id": "http://complianceascode.io/schemas/1.0/variable.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "checktext": { + "type": "string" + }, + "fixtext": { + "type": "string" + }, + "srg_requirement": { + "type": "string" + }, + "vuldiscussion": { + "type":"string" + } + }, + "uniqueItems": true +}