From ef495072ce0785845b0380d3eaebc93553c094f9 Mon Sep 17 00:00:00 2001 From: Giacomo Marciani Date: Mon, 19 Feb 2024 12:03:44 +0100 Subject: [PATCH] [Security] Disable unused background services: wpa_supplicant and cups. Signed-off-by: Giacomo Marciani --- CHANGELOG.md | 1 + .../recipes/install/disable_services.rb | 10 +++ .../unit/recipes/disable_services_spec.rb | 12 ++++ .../test/controls/disable_services_spec.rb | 52 ++++++++------- .../config_slurmd_systemd_service_spec.rb | 66 +++++++++++++++++++ 5 files changed, 119 insertions(+), 22 deletions(-) create mode 100644 cookbooks/aws-parallelcluster-slurm/spec/unit/recipes/config_slurmd_systemd_service_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 9525258ef9..3c25c3f96b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This file is used to list changes made in each version of the AWS ParallelCluste ------ **ENHANCEMENTS** +- Disable unused background services wpa_supplicant and cups to improve security. **CHANGES** diff --git a/cookbooks/aws-parallelcluster-platform/recipes/install/disable_services.rb b/cookbooks/aws-parallelcluster-platform/recipes/install/disable_services.rb index 2fb63dd0a7..667add3815 100644 --- a/cookbooks/aws-parallelcluster-platform/recipes/install/disable_services.rb +++ b/cookbooks/aws-parallelcluster-platform/recipes/install/disable_services.rb @@ -27,3 +27,13 @@ service 'log4j-cve-2021-44228-hotpatch' do action %i(disable stop mask) end unless on_docker? + +# Necessary on Ubuntu and Amazon Linux 2 +service 'cups' do + action %i(disable stop mask) +end unless on_docker? + +# Necessary on Ubuntu 22 +service 'wpa_supplicant' do + action %i(disable stop mask) +end unless on_docker? diff --git a/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/disable_services_spec.rb b/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/disable_services_spec.rb index 96d0043d78..15234454fe 100644 --- a/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/disable_services_spec.rb +++ b/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/disable_services_spec.rb @@ -18,6 +18,18 @@ is_expected.to stop_service('log4j-cve-2021-44228-hotpatch') is_expected.to mask_service('log4j-cve-2021-44228-hotpatch') end + + it 'disables cups' do + is_expected.to disable_service('cups') + is_expected.to stop_service('cups') + is_expected.to mask_service('cups') + end + + it 'disables wpa_supplicant' do + is_expected.to disable_service('wpa_supplicant') + is_expected.to stop_service('wpa_supplicant') + is_expected.to mask_service('wpa_supplicant') + end end end end diff --git a/cookbooks/aws-parallelcluster-platform/test/controls/disable_services_spec.rb b/cookbooks/aws-parallelcluster-platform/test/controls/disable_services_spec.rb index a7bc70eb05..967bdfd300 100644 --- a/cookbooks/aws-parallelcluster-platform/test/controls/disable_services_spec.rb +++ b/cookbooks/aws-parallelcluster-platform/test/controls/disable_services_spec.rb @@ -10,38 +10,46 @@ # See the License for the specific language governing permissions and limitations under the License. control 'tag:testami_tag:config_services_disabled_on_debian_family' do - title 'Test that DLAMI multi eni helper is disabled and masked on debian family' + services = %w(aws-ubuntu-eni-helper wpa_supplicant) + + title "Test that #{services.join(',')} are disabled and masked on debian family" only_if { os_properties.debian_family? && !os_properties.on_docker? } - describe service('aws-ubuntu-eni-helper') do - it { should_not be_enabled } - it { should_not be_running } - end + services.each do |service_name| + describe service(service_name) do + it { should_not be_enabled } + it { should_not be_running } + end - describe bash('systemctl list-unit-files --state=masked --no-legend') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match /aws-ubuntu-eni-helper.service\s*masked/ } + describe bash('systemctl list-unit-files --state=masked --no-legend') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match /#{service_name}.service\s*masked/ } + end end end control 'tag:testami_tag:config_services_disabled_on_amazon_family' do - title 'Test that log4j-cve-2021-44228-hotpatch is disabled and masked on amazon family' + services = %w(log4j-cve-2021-44228-hotpatch cups) - only_if { os_properties.amazon_family? && !os_properties.on_docker? } + title "Test that #{services.join(',')} are disabled and masked on amazon family" - describe service('log4j-cve-2021-44228-hotpatch') do - it { should_not be_enabled } - it { should_not be_running } - end - - describe bash('systemctl list-unit-files --state=masked --no-legend') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match /log4j-cve-2021-44228-hotpatch.service\s*masked/ } - end + only_if { os_properties.amazon_family? && !os_properties.on_docker? } - describe bash('systemctl show -p LoadState log4j-cve-2021-44228-hotpatch') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match /LoadState=masked/ } + services.each do |service_name| + describe service(service_name) do + it { should_not be_enabled } + it { should_not be_running } + end + + describe bash('systemctl list-unit-files --state=masked --no-legend') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match /#{service_name}.service\s*masked/ } + end + + describe bash("systemctl show -p LoadState #{service_name}") do + its(:exit_status) { should eq 0 } + its(:stdout) { should match /LoadState=masked/ } + end end end diff --git a/cookbooks/aws-parallelcluster-slurm/spec/unit/recipes/config_slurmd_systemd_service_spec.rb b/cookbooks/aws-parallelcluster-slurm/spec/unit/recipes/config_slurmd_systemd_service_spec.rb new file mode 100644 index 0000000000..f9689df6fe --- /dev/null +++ b/cookbooks/aws-parallelcluster-slurm/spec/unit/recipes/config_slurmd_systemd_service_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper' + +describe 'aws-parallelcluster-slurm::config_head_node' do + for_all_oses do |platform, version| + context "on #{platform}#{version}" do + cached(:chef_run) do + runner = runner(platform: platform, version: version) do + allow_any_instance_of(Object).to receive(:are_mount_or_unmount_required?).and_return(false) + allow_any_instance_of(Object).to receive(:dig).and_return(true) + RSpec::Mocks.configuration.allow_message_expectations_on_nil = true + end + runner.converge(described_recipe) + end + cached(:node) { chef_run.node } + + it 'creates the slurmdbd configuration files' do + slurm_install_dir = "#{node['cluster']['slurm']['install_dir']}" + slurm_user = "#{node['cluster']['slurm']['user']}" + slurm_group = "#{node['cluster']['slurm']['group']}" + is_expected.to create_template_if_missing("#{slurm_install_dir}/etc/slurmdbd.conf").with( + source: 'slurm/slurmdbd.conf.erb', + user: slurm_user, + group: slurm_group, + mode: '0600' + ) + is_expected.to create_file("#{slurm_install_dir}/etc/slurm_parallelcluster_slurmdbd.conf").with( + user: slurm_user, + group: slurm_group, + mode: '0600' + ) + end + + it 'creates the Slurm database password update script' do + is_expected.to create_template("#{node['cluster']['scripts_dir']}/slurm/update_slurm_database_password.sh").with( + source: 'slurm/head_node/update_slurm_database_password.sh.erb', + user: 'root', + group: 'root', + mode: '0700' + ) + end + + it 'executes the Slurm database password update scripts' do + is_expected.to run_execute("update Slurm database password").with( + command: "#{node['cluster']['scripts_dir']}/slurm/update_slurm_database_password.sh", + user: "root", + group: "root" + ) + end + + it 'starts the slurm database daemon' do + is_expected.to enable_service("slurmdbd") + is_expected.to start_service("slurmdbd") + end + + it "waits for the Slurm database to respond" do + is_expected.to run_execute("wait for slurm database").with( + command: "#{node['cluster']['slurm']['install_dir']}/bin/sacctmgr show clusters -Pn" + ) + end + + it "bootstraps the Slurm database idempotently" do + is_expected.to run_bash("bootstrap slurm database") + end + end + end +end