diff --git a/install_files/ansible-base/roles/common/defaults/main.yml b/install_files/ansible-base/roles/common/defaults/main.yml index 3850dd42080..d2c3ae7a383 100644 --- a/install_files/ansible-base/roles/common/defaults/main.yml +++ b/install_files/ansible-base/roles/common/defaults/main.yml @@ -38,6 +38,9 @@ sysctl_flags: value: "0" - name: "net.ipv4.conf.default.send_redirects" value: "0" + +# Store IPv6-related sysctl flags separately, for distro-specific handling +sysctl_flags_ipv6: - name: "net.ipv6.conf.all.disable_ipv6" value: "1" - name: "net.ipv6.conf.default.disable_ipv6" diff --git a/install_files/ansible-base/roles/common/tasks/sysctl.yml b/install_files/ansible-base/roles/common/tasks/sysctl.yml index e05adc54159..5c542cb4ea6 100644 --- a/install_files/ansible-base/roles/common/tasks/sysctl.yml +++ b/install_files/ansible-base/roles/common/tasks/sysctl.yml @@ -12,3 +12,16 @@ tags: - sysctl - hardening + +- name: Set sysctl flags for net.ipv6 config. + sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: yes + state: present + reload: yes + with_items: "{{ sysctl_flags_ipv6 }}" + when: ansible_distribution_release == "xenial" + tags: + - sysctl + - hardening diff --git a/install_files/securedrop-grsec-focal/DEBIAN/postinst.j2 b/install_files/securedrop-grsec-focal/DEBIAN/postinst.j2 index 6d251e9b03d..6d7d0d8b87c 100755 --- a/install_files/securedrop-grsec-focal/DEBIAN/postinst.j2 +++ b/install_files/securedrop-grsec-focal/DEBIAN/postinst.j2 @@ -28,7 +28,7 @@ set_grub_default() { # When using CONFIG_PAX_KERNEXEC, the grsecurity team recommends the kernel # is booted with "noefi" on the kernel command line if "CONFIG_EFI" is # enabled, as EFI runtime services are necessarily mapped as RWX. - sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT=/s/=.*/=\"noefi\"/' /etc/default/grub + perl -pi -e 's|^GRUB_CMDLINE_LINUX_DEFAULT=|GRUB_CMDLINE_LINUX_DEFAULT="noefi ipv6.disable=1"|' /etc/default/grub update-grub } diff --git a/molecule/testinfra/common/test_grsecurity.py b/molecule/testinfra/common/test_grsecurity.py index 6b4af061e0f..3bf05d23dfb 100644 --- a/molecule/testinfra/common/test_grsecurity.py +++ b/molecule/testinfra/common/test_grsecurity.py @@ -277,3 +277,15 @@ def test_mds_mitigations_and_smt_disabled(host): grub_config = host.file(grub_config_path) assert grub_config.contains("mds=full,nosmt") + + +def test_kernel_boot_options(host): + """ + Ensure command-line options for currently booted kernel are set. + """ + with host.sudo(): + f = host.file("/proc/cmdline") + boot_opts = f.content_string.split() + assert "noefi" in boot_opts + if host.system_info.codename == "focal": + assert "ipv6.disable=1" in boot_opts diff --git a/molecule/testinfra/common/test_ip6tables.py b/molecule/testinfra/common/test_ip6tables.py index 8f7497731be..ecc6e29c3f6 100644 --- a/molecule/testinfra/common/test_ip6tables.py +++ b/molecule/testinfra/common/test_ip6tables.py @@ -4,11 +4,15 @@ testinfra_hosts = [test_vars.app_hostname, test_vars.monitor_hostname] -def test_ip6tables_drop_everything(host): +def test_ip6tables_drop_everything_xenial(host): """ Ensure that all IPv6 packets are dropped by default. The IPv4 rules are more complicated, and tested separately. + This test is Xenial-specific, given that on Focal we disable + IPv6 functionality completely. """ + if host.system_info.codename != "xenial": + return True desired_ip6tables_output = """ -P INPUT DROP -P FORWARD DROP @@ -18,3 +22,26 @@ def test_ip6tables_drop_everything(host): with host.sudo(): c = host.check_output("ip6tables -S") assert c == desired_ip6tables_output + + +def test_ip6tables_drop_everything_focal(host): + """ + Ensures that IPv6 firewall settings are inaccessible, + due to fully disabling IPv6 functionality at boot-time, + via boot options. + """ + if host.system_info.codename != "focal": + return True + with host.sudo(): + c = host.run("ip6tables -S") + assert c.rc != 0 + assert c.stdout == "" + + +def test_ipv6_addresses_absent(host): + """ + Ensure that no IPv6 addresses are assigned to interfaces. + """ + with host.sudo(): + c = host.check_output("ip -6 addr") + assert c == "" diff --git a/molecule/testinfra/common/test_system_hardening.py b/molecule/testinfra/common/test_system_hardening.py index 283e49a8404..d7825a3bd77 100644 --- a/molecule/testinfra/common/test_system_hardening.py +++ b/molecule/testinfra/common/test_system_hardening.py @@ -33,6 +33,9 @@ def test_sysctl_options(host, sysctl_opt): due to the heavy use of Tor. """ with host.sudo(): + # For Focal, we disable IPv6 entirely, so the IPv6 sysctl options won't exist + if sysctl_opt[0].startswith("net.ipv6") and host.system_info.codename == "focal": + return True assert host.sysctl(sysctl_opt[0]) == sysctl_opt[1]