From fa35bc99367166345e160f0e04d8830c71c0e2a0 Mon Sep 17 00:00:00 2001
From: Ryan Anderson <ndry@amazon.com>
Date: Fri, 15 Dec 2023 15:53:39 -0500
Subject: [PATCH 1/5] Upgrade EFA to 1.29.1

---
 CHANGELOG.md                                                  | 2 +-
 .../resources/efa/partial/_common.rb                          | 4 ++--
 .../spec/unit/resources/efa_spec.rb                           | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index db6d09ab43..b7dce72934 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,7 +39,7 @@ This file is used to list changes made in each version of the AWS ParallelCluste
 - Upgrade CUDA Toolkit to version 12.2.2.
 - Use Open Source NVIDIA GPU drivers (OpenRM) as NVIDIA kernel module for Linux instead of NVIDIA closed source module.
 - Do not wait for static nodes in maintenance to signal CFN that the head node initialization is complete.
-- Upgrade EFA installer to `1.29.0`.
+- Upgrade EFA installer to `1.29.1`.
   - Efa-driver: `efa-2.6.0-1`
   - Efa-config: `efa-config-1.15-1`
   - Efa-profile: `efa-profile-1.5-1`
diff --git a/cookbooks/aws-parallelcluster-environment/resources/efa/partial/_common.rb b/cookbooks/aws-parallelcluster-environment/resources/efa/partial/_common.rb
index 052e27925b..c61975463e 100644
--- a/cookbooks/aws-parallelcluster-environment/resources/efa/partial/_common.rb
+++ b/cookbooks/aws-parallelcluster-environment/resources/efa/partial/_common.rb
@@ -17,8 +17,8 @@
 # EFA setup: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa-start.html
 #
 
-property :efa_version, String, default: '1.29.0'
-property :efa_checksum, String, default: '836655f87015547e733e7d9f7c760e4e24697f8bbc261bb5f3560abd4206bc36'
+property :efa_version, String, default: '1.29.1'
+property :efa_checksum, String, default: '178b263b8c25845b63dc93b25bcdff5870df5204ec509af26f43e8d283488744'
 
 action :setup do
   if efa_installed? && !::File.exist?(efa_tarball)
diff --git a/cookbooks/aws-parallelcluster-environment/spec/unit/resources/efa_spec.rb b/cookbooks/aws-parallelcluster-environment/spec/unit/resources/efa_spec.rb
index b6943e00a4..b6fda4c58d 100644
--- a/cookbooks/aws-parallelcluster-environment/spec/unit/resources/efa_spec.rb
+++ b/cookbooks/aws-parallelcluster-environment/spec/unit/resources/efa_spec.rb
@@ -2,8 +2,8 @@
 
 # parallelcluster default source dir defined in attributes
 source_dir = '/opt/parallelcluster/sources'
-efa_version = '1.29.0'
-efa_checksum = '836655f87015547e733e7d9f7c760e4e24697f8bbc261bb5f3560abd4206bc36'
+efa_version = '1.29.1'
+efa_checksum = '178b263b8c25845b63dc93b25bcdff5870df5204ec509af26f43e8d283488744'
 
 class ConvergeEfa
   def self.setup(chef_run)

From ef5d05f65adff88be7ac0530fb53f64ea13c4854 Mon Sep 17 00:00:00 2001
From: Himani Anil Deshpande <79726937+himani2411@users.noreply.github.com>
Date: Fri, 12 Jan 2024 13:53:29 -0500
Subject: [PATCH 2/5] [Disable Sudo] Cookbook Resource to handle
 disabling/enabling of Sudo Access for default User (#2613)

[Disable Sudo] Add Kitchen tests for disable_sudo_access resource

Co-authored-by: Himani Deshpande <himanidp@amazon.com>
---
 .../kitchen.platform-config.yml               | 16 +++++
 .../recipes/config.rb                         |  2 +-
 .../partial/_sudo_access_common.rb            | 52 ++++++++++++++
 .../sudo_access/sudo_access_amazon2.rb        | 17 +++++
 .../sudo_access/sudo_access_centos7.rb        | 19 +++++
 .../sudo_access/sudo_access_redhat8.rb        | 19 +++++
 .../sudo_access/sudo_access_rocky8.rb         | 19 +++++
 .../sudo_access/sudo_access_ubuntu20+.rb      | 19 +++++
 .../spec/unit/resources/sudo_access_spec.rb   | 71 +++++++++++++++++++
 .../99-parallelcluster-revoke-sudo.erb        |  1 +
 .../test/controls/sudo_access_spec.rb         | 52 ++++++++++++++
 11 files changed, 286 insertions(+), 1 deletion(-)
 create mode 100644 cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb
 create mode 100644 cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_amazon2.rb
 create mode 100644 cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_centos7.rb
 create mode 100644 cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_redhat8.rb
 create mode 100644 cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_rocky8.rb
 create mode 100644 cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_ubuntu20+.rb
 create mode 100644 cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb
 create mode 100644 cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb
 create mode 100644 cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb

diff --git a/cookbooks/aws-parallelcluster-platform/kitchen.platform-config.yml b/cookbooks/aws-parallelcluster-platform/kitchen.platform-config.yml
index 1687189fb6..3640f9c9e5 100644
--- a/cookbooks/aws-parallelcluster-platform/kitchen.platform-config.yml
+++ b/cookbooks/aws-parallelcluster-platform/kitchen.platform-config.yml
@@ -199,3 +199,19 @@ suites:
     verifier:
       controls:
         - /tag:config_supervisord/
+  - name: sudo_access
+    run_list:
+      - recipe[aws-parallelcluster-tests::setup]
+      - recipe[aws-parallelcluster-tests::test_resource]
+    verifier:
+      controls:
+        - /tag:config_sudo_access/
+    attributes:
+      resource: sudo_access:setup
+      cluster:
+##       Test to check if sudo access for default user is disabled (Disable Action) 
+##       The test runs with default user, it will fail to check the files content as it does not have sudo access anymore if we don't override with pcluster-admin 
+        cluster_user: 'pcluster-admin'
+        disable_sudo_access_for_default_user: 'true'
+#        Test to check if sudo access for default user is enabled (Enable Action) 
+#        disable_sudo_access_for_default_user: 'false'
diff --git a/cookbooks/aws-parallelcluster-platform/recipes/config.rb b/cookbooks/aws-parallelcluster-platform/recipes/config.rb
index f868b21166..153518a128 100644
--- a/cookbooks/aws-parallelcluster-platform/recipes/config.rb
+++ b/cookbooks/aws-parallelcluster-platform/recipes/config.rb
@@ -14,6 +14,7 @@
 include_recipe 'aws-parallelcluster-platform::openssh'
 include_recipe 'aws-parallelcluster-platform::sudo_config'
 include_recipe 'aws-parallelcluster-platform::cluster_user'
+sudo_access "Setup Sudo Access of Default User"
 include_recipe 'aws-parallelcluster-platform::networking'
 include_recipe 'aws-parallelcluster-platform::nvidia_config'
 sticky_bits 'setup sticky bits'
@@ -24,5 +25,4 @@
 # Supervisord configuration must be executed after DCV because dcv external authenticator is part of it
 include_recipe 'aws-parallelcluster-platform::supervisord_config'
 fetch_config 'Fetch and load cluster configs'
-
 include_recipe 'aws-parallelcluster-platform::config_login' if node['cluster']['node_type'] == 'LoginNode'
diff --git a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb
new file mode 100644
index 0000000000..015d1a0720
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+#
+# Copyright:: 2013-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License").
+# You may not use this file except in compliance with the License.
+# A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "LICENSE.txt" file accompanying this file.
+# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
+# See the License for the specific language governing permissions and limitations under the License.
+
+unified_mode true
+default_action :setup
+
+property :sudo_access, String
+
+action :setup do
+  node['cluster']['disable_sudo_access_for_default_user'] == 'true' ? action_disable : action_enable
+end
+
+action :enable do
+  # Enable sudo access for default user
+  template '/etc/sudoers.d/99-parallelcluster-revoke-sudo-access' do
+    only_if { ::File.exist? "/etc/sudoers.d/99-parallelcluster-revoke-sudo-access" }
+    source 'sudo_access/99-parallelcluster-revoke-sudo.erb'
+    cookbook 'aws-parallelcluster-platform'
+    action :delete
+  end
+end
+
+action :disable do
+  replace_or_add "Disable Sudo Access for #{node['cluster']['cluster_user']}" do
+    path "/etc/sudoers"
+    pattern "^#{node['cluster']['cluster_user']}*"
+    line ""
+    remove_duplicates true
+    replace_only true
+  end
+
+  # Disable sudo access for default user
+  template '/etc/sudoers.d/99-parallelcluster-revoke-sudo-access' do
+    source 'sudo_access/99-parallelcluster-revoke-sudo.erb'
+    cookbook 'aws-parallelcluster-platform'
+    owner 'root'
+    group 'root'
+    mode '0600'
+    action :create
+  end
+end
diff --git a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_amazon2.rb b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_amazon2.rb
new file mode 100644
index 0000000000..ab48af0390
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_amazon2.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# Copyright:: 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License").
+# You may not use this file except in compliance with the License.
+# A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "LICENSE.txt" file accompanying this file.
+# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
+# See the License for the specific language governing permissions and limitations under the License.
+
+provides :sudo_access, platform: 'amazon', platform_version: '2'
+
+use 'partial/_sudo_access_common.rb'
diff --git a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_centos7.rb b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_centos7.rb
new file mode 100644
index 0000000000..0b13ca4c03
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_centos7.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# Copyright:: 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License").
+# You may not use this file except in compliance with the License.
+# A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "LICENSE.txt" file accompanying this file.
+# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
+# See the License for the specific language governing permissions and limitations under the License.
+
+provides :sudo_access, platform: 'centos' do |node|
+  node['platform_version'].to_i == 7
+end
+
+use 'partial/_sudo_access_common.rb'
diff --git a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_redhat8.rb b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_redhat8.rb
new file mode 100644
index 0000000000..963fad3a62
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_redhat8.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# Copyright:: 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License").
+# You may not use this file except in compliance with the License.
+# A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "LICENSE.txt" file accompanying this file.
+# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
+# See the License for the specific language governing permissions and limitations under the License.
+
+provides :sudo_access, platform: 'redhat' do |node|
+  node['platform_version'].to_i == 8
+end
+
+use 'partial/_sudo_access_common.rb'
diff --git a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_rocky8.rb b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_rocky8.rb
new file mode 100644
index 0000000000..fbc952e5e8
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_rocky8.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# Copyright:: 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License").
+# You may not use this file except in compliance with the License.
+# A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "LICENSE.txt" file accompanying this file.
+# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
+# See the License for the specific language governing permissions and limitations under the License.
+
+provides :sudo_access, platform: 'rocky' do |node|
+  node['platform_version'].to_i == 8
+end
+
+use 'partial/_sudo_access_common.rb'
diff --git a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_ubuntu20+.rb b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_ubuntu20+.rb
new file mode 100644
index 0000000000..a1496ab6d8
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/sudo_access_ubuntu20+.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# Copyright:: 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License").
+# You may not use this file except in compliance with the License.
+# A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "LICENSE.txt" file accompanying this file.
+# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
+# See the License for the specific language governing permissions and limitations under the License.
+
+provides :sudo_access, platform: 'ubuntu' do |node|
+  node['platform_version'].to_i >= 20
+end
+
+use 'partial/_sudo_access_common.rb'
diff --git a/cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb b/cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb
new file mode 100644
index 0000000000..9ed46edea4
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+class ConvergeDisableSudoAccess
+  def self.setup(chef_run)
+    chef_run.converge_dsl('aws-parallelcluster-platform') do
+      sudo_access 'setup' do
+        action :setup
+      end
+    end
+  end
+end
+
+describe 'sudo_access:setup' do
+  for_all_oses do |platform, version|
+    context "on #{platform}#{version}" do
+      cached(:default_user) { 'ec2-user' }
+      let(:chef_run) do
+        runner(platform: platform, version: version, step_into: ['sudo_access']) do |node|
+          node.override['cluster']['cluster_user'] = default_user
+        end
+      end
+
+      context "when disable_sudo_access_for_default_user is true" do
+        before do
+          chef_run.node.override['cluster']['disable_sudo_access_for_default_user'] = 'true'
+          ConvergeDisableSudoAccess.setup(chef_run)
+        end
+
+        it('it disables sudo access for default user') do
+          is_expected.to edit_replace_or_add("Disable Sudo Access for #{default_user}").with(
+            path: '/etc/sudoers',
+            pattern: "^#{default_user}*",
+            line: "",
+            remove_duplicates: true,
+            replace_only: true
+          )
+        end
+      end
+
+      context "when disable_sudo_access_for_default_user is false" do
+        before do
+          chef_run.node.override['cluster']['disable_sudo_access_for_default_user'] = 'false'
+        end
+
+        context 'and 99-parallelcluster-revoke-sudo-access file doesnt exist' do
+          before do
+            mock_file_exists("/etc/sudoers.d/99-parallelcluster-revoke-sudo-access", false)
+            ConvergeDisableSudoAccess.setup(chef_run)
+          end
+          it('it enables sudo access for default user') do
+            is_expected.not_to delete_template('/etc/sudoers.d/99-parallelcluster-revoke-sudo-access').with(
+              source: "sudo_access/99-parallelcluster-revoke-sudo.erb"
+            )
+          end
+        end
+
+        context 'and 99-parallelcluster-revoke-sudo-access file exists' do
+          before do
+            mock_file_exists("/etc/sudoers.d/99-parallelcluster-revoke-sudo-access", true)
+            ConvergeDisableSudoAccess.setup(chef_run)
+          end
+          it('it enables sudo access for default user') do
+            is_expected.to delete_template('/etc/sudoers.d/99-parallelcluster-revoke-sudo-access').with(
+              source: "sudo_access/99-parallelcluster-revoke-sudo.erb"
+            )
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb b/cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb
new file mode 100644
index 0000000000..178e858ffb
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb
@@ -0,0 +1 @@
+<%= node['cluster']['cluster_user'] %> ALL=(ALL) !ALL
diff --git a/cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb b/cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb
new file mode 100644
index 0000000000..02616919e9
--- /dev/null
+++ b/cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb
@@ -0,0 +1,52 @@
+# Copyright:: 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License").
+# You may not use this file except in compliance with the License. A copy of the License is located at
+#
+# http://aws.amazon.com/apache2.0/
+#
+# or in the "LICENSE.txt" file accompanying this file.
+# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.
+# See the License for the specific language governing permissions and limitations under the License.
+
+control 'tag:config_sudo_access_disable_action' do
+  title 'Check if sudo access for default user is disabled'
+  only_if { node['cluster']["disable_sudo_access_for_default_user"] == 'true' }
+
+  describe file('/etc/sudoers') do
+    it { should exist }
+    its('content') { should_not match /\b\S*(#{node['cluster']['cluster_user']} ALL=(ALL) NOPASSWD:ALL)/ }
+  end
+
+  describe file('/etc/sudoers.d/99-parallelcluster-revoke-sudo-access') do
+    it { should exist }
+    its('owner') { should eq 'root' }
+    its('group') { should eq 'root' }
+    its('mode') { should cmp '0600' }
+    its('content') { should match "#{node['cluster']['cluster_user']} ALL=(ALL) !ALL\n" }
+  end
+
+  describe bash("sudo -l -U #{node['cluster']['cluster_user']} | tail -1 | awk '{$1=$1};1'") do
+    its('exit_status') { should eq 0 }
+    its('stdout') { should match "(ALL) !ALL\n" }
+  end unless os_properties.on_docker?
+end
+
+control 'tag:config_sudo_access_enabled_action' do
+  title 'Check if sudo access for default user is enabled'
+  only_if { [ 'false', nil].include?(node['cluster']["disable_sudo_access_for_default_user"]) }
+
+  describe file('/etc/sudoers.d/99-parallelcluster-revoke-sudo-access') do
+    it { should_not exist }
+  end
+
+  describe file('/etc/sudoers.d/90-cloud-init-users') do
+    it { should exist }
+    its('content') { should match /^[\-#\.,\:\+\w\s]*(rocky ALL=\(ALL\) NOPASSWD:ALL)/ }
+  end unless os_properties.on_docker?
+
+  describe bash("sudo -l -U #{node['cluster']['cluster_user']} | tail -1 | awk '{$1=$1};1'") do
+    its('exit_status') { should eq 0 }
+    its('stdout') { should match "(ALL) NOPASSWD: ALL\n" }
+  end unless os_properties.on_docker?
+end

From b14052936c912119e063f1345f19cd52adb6338d Mon Sep 17 00:00:00 2001
From: Giacomo Marciani <mgiacomo@amazon.com>
Date: Wed, 10 Jan 2024 13:14:05 +0100
Subject: [PATCH 3/5] [DFSM] Make supervisord start cfn-hup on compute nodes.

Signed-off-by: Giacomo Marciani <mgiacomo@amazon.com>
---
 .../spec/unit/recipes/supervisord_config_spec.rb      |  3 +++
 .../supervisord/parallelcluster_supervisord.conf.erb  | 11 ++++++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/supervisord_config_spec.rb b/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/supervisord_config_spec.rb
index b6684808f2..1cfdf54523 100644
--- a/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/supervisord_config_spec.rb
+++ b/cookbooks/aws-parallelcluster-platform/spec/unit/recipes/supervisord_config_spec.rb
@@ -29,6 +29,7 @@
 
         it 'has the correct content' do
           is_expected.to render_file('/etc/parallelcluster/parallelcluster_supervisord.conf')
+            .with_content("[program:cfn-hup]")
             .with_content("[program:clustermgtd]")
             .with_content("[program:clusterstatusmgtd]")
             .with_content("[program:pcluster_dcv_authenticator]")
@@ -69,6 +70,7 @@
 
         it 'has the correct content' do
           is_expected.to render_file('/etc/parallelcluster/parallelcluster_supervisord.conf')
+            .with_content("[program:cfn-hup]")
             .with_content("[program:computemgtd]")
 
           is_expected.not_to render_file('/etc/parallelcluster/parallelcluster_supervisord.conf')
@@ -91,6 +93,7 @@
             .with_content("[program:loginmgtd]")
 
           is_expected.not_to render_file('/etc/parallelcluster/parallelcluster_supervisord.conf')
+            .with_content("[program:cfn-hup]")
             .with_content("[program:pcluster_dcv_authenticator]")
         end
       end
diff --git a/cookbooks/aws-parallelcluster-platform/templates/supervisord/parallelcluster_supervisord.conf.erb b/cookbooks/aws-parallelcluster-platform/templates/supervisord/parallelcluster_supervisord.conf.erb
index fabff543a6..906eaeca2c 100644
--- a/cookbooks/aws-parallelcluster-platform/templates/supervisord/parallelcluster_supervisord.conf.erb
+++ b/cookbooks/aws-parallelcluster-platform/templates/supervisord/parallelcluster_supervisord.conf.erb
@@ -1,8 +1,8 @@
 # Generated by Chef for AWS ParallelCluster <%= node['cluster']['node_type'] -%>
 # Local modifications could be overwritten.
+<%# HeadNode, ComputeFleet -%>
 <% case node['cluster']['node_type'] -%>
-<%# HeadNode -%>
-<% when 'HeadNode' -%>
+<% when 'HeadNode', 'ComputeFleet' -%>
 [program:cfn-hup]
 command = <%= node['cluster']['scripts_dir']%>/cfn-hup-runner.sh
 autorestart = true
@@ -10,8 +10,13 @@ redirect_stderr = true
 stdout_logfile = /var/log/parallelcluster/cfn-hup-runner.log
 stdout_logfile_maxbytes = 1MB
 <% if @region.start_with?('us-iso') -%>
-environment = AWS_CA_BUNDLE="<%= @aws_ca_bundle %>"
+  environment = AWS_CA_BUNDLE="<%= @aws_ca_bundle %>"
 <% end -%>
+<% end -%>
+
+<% case node['cluster']['node_type'] -%>
+<%# HeadNode -%>
+<% when 'HeadNode' -%>
 <% if node['cluster']['scheduler'] == 'slurm' -%>
 [program:clustermgtd]
 command = <%= node_virtualenv_path %>/bin/clustermgtd

From 4886bfc3a8158fe2b6f841e28054a11ce0fecb14 Mon Sep 17 00:00:00 2001
From: Giacomo Marciani <mgiacomo@amazon.com>
Date: Wed, 10 Jan 2024 13:15:31 +0100
Subject: [PATCH 4/5] [DFSM] Add dummy log line to prove that update recipe is
 triggered on compute nodes.

Signed-off-by: Giacomo Marciani <mgiacomo@amazon.com>
---
 cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb b/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb
index e10f157445..a3d695323f 100644
--- a/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb
+++ b/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb
@@ -19,6 +19,11 @@
 # generate the updated shared storages mapping file
 include_recipe 'aws-parallelcluster-environment::update_fs_mapping'
 
+if node["cluster"]["node_type"] == "ComputeFleet"
+  Chef::Log.info("Dummy log line to prove that update is triggered on compute node")
+  return
+end
+
 include_recipe 'aws-parallelcluster-environment::directory_service'
 include_recipe 'aws-parallelcluster-slurm::update' if node['cluster']['scheduler'] == 'slurm'
 

From 517e55de35596205796efca2b7706805819d81c1 Mon Sep 17 00:00:00 2001
From: Himani Anil Deshpande <79726937+himani2411@users.noreply.github.com>
Date: Tue, 16 Jan 2024 14:26:47 -0500
Subject: [PATCH 5/5] [Disable Sudo] Support Update of
 DisableSudoAccessForDefaultUser Config Option (#2616)

* [Disable Sudo]Adding logs in sudo_access resource

* [Disable Sudo]Allowing sudo_access resource to update

* [Disable Sudo]Update tests for Sudo_access resource

* [Code Quality] Ignore bandit rules B038

---------

Co-authored-by: Himani Deshpande <himanidp@amazon.com>
---
 .../recipes/update.rb                                |  2 ++
 .../sudo_access/partial/_sudo_access_common.rb       | 11 ++++++++---
 .../spec/unit/resources/sudo_access_spec.rb          | 12 +++++++++++-
 .../sudo_access/99-parallelcluster-revoke-sudo.erb   |  2 +-
 .../test/controls/sudo_access_spec.rb                |  2 +-
 .../unit/clusterstatusmgtd/test_clusterstatusmgtd.py |  2 +-
 test/unit/health_check/test_health_check_manager.py  |  2 +-
 7 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb b/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb
index a3d695323f..9a61244c43 100644
--- a/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb
+++ b/cookbooks/aws-parallelcluster-entrypoints/recipes/update.rb
@@ -31,3 +31,5 @@
 if is_custom_node?
   include_recipe 'aws-parallelcluster-computefleet::update_parallelcluster_node'
 end
+
+sudo_access "Update Sudo Access" if node['cluster']['scheduler'] == 'slurm'
diff --git a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb
index 015d1a0720..449cb03929 100644
--- a/cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb
+++ b/cookbooks/aws-parallelcluster-platform/resources/sudo_access/partial/_sudo_access_common.rb
@@ -15,13 +15,14 @@
 unified_mode true
 default_action :setup
 
-property :sudo_access, String
+property :user_name, String, default: node['cluster']['cluster_user']
 
 action :setup do
   node['cluster']['disable_sudo_access_for_default_user'] == 'true' ? action_disable : action_enable
 end
 
 action :enable do
+  Chef::Log.info("Enabling Sudo Access for #{new_resource.user_name}")
   # Enable sudo access for default user
   template '/etc/sudoers.d/99-parallelcluster-revoke-sudo-access' do
     only_if { ::File.exist? "/etc/sudoers.d/99-parallelcluster-revoke-sudo-access" }
@@ -32,9 +33,10 @@
 end
 
 action :disable do
-  replace_or_add "Disable Sudo Access for #{node['cluster']['cluster_user']}" do
+  Chef::Log.info("Disabling Sudo Access for #{new_resource.user_name}")
+  replace_or_add "Disable Sudo Access for #{new_resource.user_name}" do
     path "/etc/sudoers"
-    pattern "^#{node['cluster']['cluster_user']}*"
+    pattern "^#{new_resource.user_name}*"
     line ""
     remove_duplicates true
     replace_only true
@@ -47,6 +49,9 @@
     owner 'root'
     group 'root'
     mode '0600'
+    variables(
+      user_name: new_resource.user_name
+    )
     action :create
   end
 end
diff --git a/cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb b/cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb
index 9ed46edea4..4c339ef23d 100644
--- a/cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb
+++ b/cookbooks/aws-parallelcluster-platform/spec/unit/resources/sudo_access_spec.rb
@@ -13,7 +13,7 @@ def self.setup(chef_run)
 describe 'sudo_access:setup' do
   for_all_oses do |platform, version|
     context "on #{platform}#{version}" do
-      cached(:default_user) { 'ec2-user' }
+      cached(:default_user) { 'ubuntu' }
       let(:chef_run) do
         runner(platform: platform, version: version, step_into: ['sudo_access']) do |node|
           node.override['cluster']['cluster_user'] = default_user
@@ -34,6 +34,16 @@ def self.setup(chef_run)
             remove_duplicates: true,
             replace_only: true
           )
+          is_expected.to create_template("/etc/sudoers.d/99-parallelcluster-revoke-sudo-access").with(
+            source: 'sudo_access/99-parallelcluster-revoke-sudo.erb',
+            cookbook: 'aws-parallelcluster-platform',
+            user: 'root',
+            group: 'root',
+            mode: '0600',
+            variables: {
+              user_name: default_user,
+            }
+          )
         end
       end
 
diff --git a/cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb b/cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb
index 178e858ffb..7ff5775814 100644
--- a/cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb
+++ b/cookbooks/aws-parallelcluster-platform/templates/sudo_access/99-parallelcluster-revoke-sudo.erb
@@ -1 +1 @@
-<%= node['cluster']['cluster_user'] %> ALL=(ALL) !ALL
+<%= @user_name %> ALL=(ALL) !ALL
diff --git a/cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb b/cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb
index 02616919e9..c838b718b4 100644
--- a/cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb
+++ b/cookbooks/aws-parallelcluster-platform/test/controls/sudo_access_spec.rb
@@ -42,7 +42,7 @@
 
   describe file('/etc/sudoers.d/90-cloud-init-users') do
     it { should exist }
-    its('content') { should match /^[\-#\.,\:\+\w\s]*(rocky ALL=\(ALL\) NOPASSWD:ALL)/ }
+    its('content') { should match /^[\-#\.,\:\+\w\s]*(#{node['cluster']['cluster_user']} ALL=\(ALL\) NOPASSWD:ALL)/ }
   end unless os_properties.on_docker?
 
   describe bash("sudo -l -U #{node['cluster']['cluster_user']} | tail -1 | awk '{$1=$1};1'") do
diff --git a/test/unit/clusterstatusmgtd/test_clusterstatusmgtd.py b/test/unit/clusterstatusmgtd/test_clusterstatusmgtd.py
index abc61afa85..866de825e9 100644
--- a/test/unit/clusterstatusmgtd/test_clusterstatusmgtd.py
+++ b/test/unit/clusterstatusmgtd/test_clusterstatusmgtd.py
@@ -228,7 +228,7 @@ def test_config_parsing(self, config_file, expected_attributes, test_datadir):
         """Test config_parsing method."""
         sync_config = ClusterstatusmgtdConfig(test_datadir / config_file)
         for key in expected_attributes:
-            assert_that(sync_config.__dict__.get(key)).is_equal_to(expected_attributes.get(key))
+            assert_that(sync_config.__dict__.get(key)).is_equal_to(expected_attributes.get(key))  # noqa: B038
 
     def test_config_comparison(self, test_datadir):
         """Test configs comparison."""
diff --git a/test/unit/health_check/test_health_check_manager.py b/test/unit/health_check/test_health_check_manager.py
index 89cae2f2a3..73743b53ab 100644
--- a/test/unit/health_check/test_health_check_manager.py
+++ b/test/unit/health_check/test_health_check_manager.py
@@ -88,7 +88,7 @@ def test_config_parsing(self, config_file, expected_attributes, test_datadir):
         """Test config_parsing method."""
         sync_config = HealthCheckManagerConfig(test_datadir / config_file)
         for key in expected_attributes:
-            assert_that(sync_config.__dict__.get(key)).is_equal_to(expected_attributes.get(key))
+            assert_that(sync_config.__dict__.get(key)).is_equal_to(expected_attributes.get(key))  # noqa: B038
 
     def test_config_comparison(self, test_datadir):
         """Test configs comparison."""