From 72af31a420be9b86fc3f2cfa8195c98edcbe20a7 2024-02-26 21:24:32 From: Branko Majic Date: 2024-02-26 21:24:32 Subject: [PATCH] MAR-192: Switch to using NTPsec NTP server for increased security: - This has for some time been a way better option, and it should also provide for compatibility with Debian 12 Bookworm. --- diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml index d06fb9152894621192e2e9ef45e35699c0734546..b32a1d8f973a1be32ea69a488d735ee15899efd8 100644 --- a/roles/common/handlers/main.yml +++ b/roles/common/handlers/main.yml @@ -30,6 +30,6 @@ - name: Restart NTP server service: - name: ntp + name: ntpsec state: restarted when: ntp_servers | length > 0 diff --git a/roles/common/molecule/default/prepare.yml b/roles/common/molecule/default/prepare.yml index cea4db88c576368f5715f7e838eb9cabd3fe02b0..54f2f59d3d2ccf2fce93cc6fcd3a1bb4141c54bd 100644 --- a/roles/common/molecule/default/prepare.yml +++ b/roles/common/molecule/default/prepare.yml @@ -150,6 +150,13 @@ group: root mode: 0644 + - name: Install the deprecated/obsolete NTP-related packages + apt: + name: + - ntp + - ntpdate + state: present + - hosts: parameters-mandatory,parameters-optional become: true tasks: diff --git a/roles/common/molecule/default/tests/test_deprecated.py b/roles/common/molecule/default/tests/test_deprecated.py index a167b2edb407fb7d016194165e5b1459a89788f1..823d66ef22ebdfe6a0a06e6748c741603e96af4e 100644 --- a/roles/common/molecule/default/tests/test_deprecated.py +++ b/roles/common/molecule/default/tests/test_deprecated.py @@ -13,6 +13,7 @@ testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( '/etc/pip_check_requirements_upgrades-py3/', '/var/lib/pipreqcheck/virtualenv-py3/', '/etc/cron.d/check_pip_requirements-py3', + '/etc/ntp.conf', ]) def test_deprecated_paths_are_absent(host, path): """ @@ -21,3 +22,15 @@ def test_deprecated_paths_are_absent(host, path): with host.sudo(): assert not host.file(path).exists + + +@pytest.mark.parametrize('package', [ + 'ntp', + 'ntpdate', +]) +def test_deprecated_packages_are_absent(host, package): + """ + Tests if deprecated pacakges are absent. + """ + + assert not host.package(package).is_installed diff --git a/roles/common/molecule/default/tests/test_parameters_mandatory.py b/roles/common/molecule/default/tests/test_parameters_mandatory.py index 925fcef85a450e87147351c271d4e8172523e6bd..87ad8589c35fa84ef70f26ea87047e1a15abcbec 100644 --- a/roles/common/molecule/default/tests/test_parameters_mandatory.py +++ b/roles/common/molecule/default/tests/test_parameters_mandatory.py @@ -121,8 +121,8 @@ def test_ntp_software_not_installed(host): Tests if NTP packages are absent. """ - assert not host.package('ntp').is_installed - assert not host.package('ntpdate').is_installed + assert not host.package('ntpsec').is_installed + assert not host.package('ntpsec-ntpdate').is_installed def test_ntp_listening_interfaces(host): diff --git a/roles/common/molecule/default/tests/test_parameters_optional.py b/roles/common/molecule/default/tests/test_parameters_optional.py index d5a80b60923965682279c378592d56f1e618b4de..cccc20349a036b4f2e31eed2f2abd02e5859bab7 100644 --- a/roles/common/molecule/default/tests/test_parameters_optional.py +++ b/roles/common/molecule/default/tests/test_parameters_optional.py @@ -269,8 +269,8 @@ def test_ntp_software_installed(host): Tests if NTP packages are installed. """ - assert host.package('ntp').is_installed - assert host.package('ntpdate').is_installed + assert host.package('ntpsec').is_installed + assert host.package('ntpsec-ntpdate').is_installed def test_ntp_server_configuration(host): @@ -280,11 +280,17 @@ def test_ntp_server_configuration(host): with host.sudo(): - # Read the configuration file. - configuration = host.file("/etc/ntp.conf").content_string.split("\n") + # Check for presence of the configuration file. + configuration_file = host.file("/etc/ntpsec/ntp.conf") - # Extract only the relevant sections of files (exculde empty + assert configuration_file.exists + assert configuration_file.user == 'root' + assert configuration_file.group == 'root' + assert configuration_file.mode == 0o644 + + # Extract relevant sections of configuration (exclude empty # lines and comments). + configuration = configuration_file.content_string.split("\n") configuration = [c.strip() for c in configuration if re.match(r'^\s*(|#.*)$', c) is None] # Ensure correct servers have been configured in the pool. @@ -296,10 +302,9 @@ def test_ntp_server_configuration(host): assert sorted(servers) == sorted(expected_servers) - # Ensure querying of server is disable for untrusted clients. + # Ensure querying of server is disabled for untrusted clients. restrictions = [c for c in configuration if c.startswith('restrict')] - expected_restrictions = ["restrict -4 default kod notrap nomodify nopeer noquery", - "restrict -6 default kod notrap nomodify nopeer noquery", + expected_restrictions = ["restrict default kod nomodify nopeer noquery limited", "restrict 127.0.0.1", "restrict ::1"] diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml index 3b7b17abf161cebc27d3d50af31ac92ff703d583..6c00125a9749e19abde4c35e26f74628884b2f40 100644 --- a/roles/common/tasks/main.yml +++ b/roles/common/tasks/main.yml @@ -12,6 +12,14 @@ - "/var/lib/pipreqcheck/virtualenv-py3" - "/etc/cron.d/check_pip_requirements-py3" +- name: Drop deprecated packages + apt: + name: + - ntp + - ntpdate + state: absent + purge: true + # Main implementation # =================== @@ -470,15 +478,15 @@ - name: Install NTP packages apt: name: - - ntp - - ntpdate + - ntpsec + - ntpsec-ntpdate state: present when: ntp_servers | length > 0 - name: Deploy NTP configuration template: src: "ntp.conf.j2" - dest: "/etc/ntp.conf" + dest: "/etc/ntpsec/ntp.conf" owner: root group: root mode: 0644 diff --git a/roles/common/templates/ntp.conf.j2 b/roles/common/templates/ntp.conf.j2 index 441ac250409be6e846fafd1dd8f981ca0db70934..3eded9122bd39d1b52a312e1cc6d61ca559cb211 100644 --- a/roles/common/templates/ntp.conf.j2 +++ b/roles/common/templates/ntp.conf.j2 @@ -1,53 +1,50 @@ -# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help +# /etc/ntpsec/ntp.conf, configuration for ntpd; see ntp.conf(5) for help -driftfile /var/lib/ntp/ntp.drift +driftfile /var/lib/ntpsec/ntp.drift +leapfile /usr/share/zoneinfo/leap-seconds.list +# To enable Network Time Security support as a server, obtain a certificate +# (e.g. with Let's Encrypt), configure the paths below, and uncomment: +# nts cert CERT_FILE +# nts key KEY_FILE +# nts enable -# Enable this if you want statistics to be logged. -#statsdir /var/log/ntpstats/ +# You must create /var/log/ntpsec (owned by ntpsec:ntpsec) to enable logging. +#statsdir /var/log/ntpsec/ +#statistics loopstats peerstats clockstats +#filegen loopstats file loopstats type day enable +#filegen peerstats file peerstats type day enable +#filegen clockstats file clockstats type day enable -statistics loopstats peerstats clockstats -filegen loopstats file loopstats type day enable -filegen peerstats file peerstats type day enable -filegen clockstats file clockstats type day enable +# This should be maxclock 7, but the pool entries count towards maxclock. +tos maxclock 11 +# Comment this out if you have a refclock and want it to be able to discipline +# the clock by itself (e.g. if the system is not connected to the network). +tos minclock 4 minsane 3 -# You do need to talk to an NTP server or two (or three). -#server ntp.your-provider.example +# Specify one or more NTP servers. + +# Public NTP servers supporting Network Time Security: +# server time.cloudflare.com nts # pool.ntp.org maps to about 1000 low-stratum NTP servers. Your server will # pick a different set every time it starts up. Please consider joining the -# pool: +# pool: {% for server in ntp_servers %} server {{ server }} iburst {% endfor %} -# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for -# details. The web page -# might also be helpful. +# Access control configuration; see /usr/share/doc/ntpsec-doc/html/accopt.html +# for details. # # Note that "restrict" applies to both servers and clients, so a configuration # that might be intended to block requests from certain clients could also end # up blocking replies from your own upstream servers. # By default, exchange time with everybody, but don't allow configuration. -restrict -4 default kod notrap nomodify nopeer noquery -restrict -6 default kod notrap nomodify nopeer noquery +restrict default kod nomodify nopeer noquery limited # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 restrict ::1 - -# Clients from this (example!) subnet have unlimited access, but only if -# cryptographically authenticated. -#restrict 192.168.123.0 mask 255.255.255.0 notrust - - -# If you want to provide time to your local subnet, change the next line. -# (Again, the address is an example only.) -#broadcast 192.168.123.255 - -# If you want to listen to time broadcasts on your local subnet, de-comment the -# next lines. Please do this only if you trust everybody on the network! -#disable auth -#broadcastclient