From 20cc7628221e8a5bd434647aff53e18588d33c29 Mon Sep 17 00:00:00 2001 From: Quentin Machu Date: Tue, 27 Sep 2022 23:40:22 -0400 Subject: [PATCH] Move SSH key generation script from pam.d to /etc/profile When FSx Lustre is configured with the new root_squash feature, and ParallelCluster is configured with Active Directory with home folders within the FSx mount, pam_exec.so is unable to properly run the SSH key generation script. This is because pam_exec.so runs the script as root, but root does not have access to any home folders to manipulate the files due to the fact that root is regarded as nobody/nogroup within the root_squash'd FSx mount point. Using su in the generation script to impersonate the user does not work around the problem, as su itself would trigger pam_exec.so, and trigger a loop, which doesn't look trivial to avoid to me. Instead, I suggest moving the key generation to /etc/profile, which is executed by default for every interactive shells, by the connecting user, and serves the purpose. --- CHANGELOG.md | 1 + .../recipes/directory_service.rb | 45 +++++++++++-------- .../directory_service/generate_ssh_key.sh.erb | 11 ++--- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b3d3da91f..d449f9caf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ This file is used to list changes made in each version of the AWS ParallelCluste - Change the logic to number the routing tables when an instance have multiple NICs. - Upgrade Python from 3.7.13 to 3.9.13. - Upgrade Slurm to version 22.05.3. +- Move SSH key generation from pam.d to /etc/profile to enable root_squash'd FSx 3.2.0 ------ diff --git a/cookbooks/aws-parallelcluster-config/recipes/directory_service.rb b/cookbooks/aws-parallelcluster-config/recipes/directory_service.rb index 69cfc8141b..c0fe0b6b69 100644 --- a/cookbooks/aws-parallelcluster-config/recipes/directory_service.rb +++ b/cookbooks/aws-parallelcluster-config/recipes/directory_service.rb @@ -155,38 +155,45 @@ sensitive true end - pam_services = %w(sudo su sshd) - pam_config_dir = "/etc/pam.d" generate_ssh_key_path = "#{node['cluster']['scripts_dir']}/generate_ssh_key.sh" - ssh_key_generator_pam_config_line = "session optional pam_exec.so log=/var/log/parallelcluster/pam_ssh_key_generator.log #{generate_ssh_key_path}" - if node['cluster']["directory_service"]["generate_ssh_keys_for_users"] == 'true' + ssh_key_generator_profile_config_line = "bash #{generate_ssh_key_path} >> /var/log/parallelcluster/pam_ssh_key_generator.log 2>&1" + if node['cluster']["directory_service"]["generate_ssh_keys_for_users"] == 'true' template generate_ssh_key_path do source 'directory_service/generate_ssh_key.sh.erb' owner 'root' group 'root' mode '0755' end - pam_services.each do |pam_service| - pam_config_file = "#{pam_config_dir}/#{pam_service}" - append_if_no_line "Ensure PAM service #{pam_service} is configured to call SSH key generation script" do - path pam_config_file - line ssh_key_generator_pam_config_line - end + file "/var/log/parallelcluster/pam_ssh_key_generator.log" do + action :touch + mode '0777' + end + append_if_no_line "Ensure /etc/profile is configured to call SSH key generation script" do + path "/etc/profile" + line ssh_key_generator_profile_config_line end else - # Remove script used to generate key if it exists and ensure PAM is not configured to try to call it + # Remove script used to generate key if it exists and ensure /etc/profile is not configured to try to call it file generate_ssh_key_path do action :delete only_if { ::File.exist? generate_ssh_key_path } end - - pam_services.each do |pam_service| - pam_config_file = "#{pam_config_dir}/#{pam_service}" - delete_lines "Ensure PAM service #{pam_service} is not configured to call SSH key generation script" do - path pam_config_file - pattern %r{session\s+optional\s+pam_exec\.so\s+log=/var/log/parallelcluster/pam_ssh_key_generator\.log} - ignore_missing true - end + delete_lines "Ensure /etc/profile is not configured to call SSH key generation script" do + path "/etc/profile" + line ssh_key_generator_profile_config_line + end + end + + # Ensure pam.d based SSH generation is removed + ssh_key_generator_pam_config_line = "session optional pam_exec.so log=/var/log/parallelcluster/pam_ssh_key_generator.log #{generate_ssh_key_path}" + pam_services = %w(sudo su sshd) + pam_config_dir = "/etc/pam.d" + pam_services.each do |pam_service| + pam_config_file = "#{pam_config_dir}/#{pam_service}" + delete_lines "Ensure PAM service #{pam_service} is not configured to call SSH key generation script" do + path pam_config_file + pattern %r{session\s+optional\s+pam_exec\.so\s+log=/var/log/parallelcluster/pam_ssh_key_generator\.log} + ignore_missing true end end else diff --git a/cookbooks/aws-parallelcluster-config/templates/default/directory_service/generate_ssh_key.sh.erb b/cookbooks/aws-parallelcluster-config/templates/default/directory_service/generate_ssh_key.sh.erb index ef2bc3007b..24052cf8b9 100644 --- a/cookbooks/aws-parallelcluster-config/templates/default/directory_service/generate_ssh_key.sh.erb +++ b/cookbooks/aws-parallelcluster-config/templates/default/directory_service/generate_ssh_key.sh.erb @@ -3,16 +3,11 @@ set -ex env # Root does not need SSH key generation -[ ${PAM_USER} == "root" ] && exit 0 - -# The home directory for every user must be determined in the most generic way because -# we should not assume that every user has its home directory in /home/$USER. -user_home_dir="$(getent passwd ${PAM_USER} | cut -d ':' -f 6)" -[ ! -d "${user_home_dir}" ] && echo "ERROR Cannot create SSH key for user ${PAM_USER} if its home directory is not found" && exit 1 +[ ${USER} == "root" ] && exit 0 # Skip SSH key creation if the SSH has been already configured for the user. # We assume that SSH has been already configured if the directory .ssh already exists in the user home. -user_ssh_dir="${user_home_dir}/.ssh" +user_ssh_dir="${HOME}/.ssh" [ -d "${user_ssh_dir}" ] && exit 0 mkdir -m 0700 "${user_ssh_dir}" @@ -22,4 +17,4 @@ cat "${user_ssh_dir}/id_rsa.pub" >> "${user_ssh_dir}/authorized_keys" chmod 0600 "${user_ssh_dir}/authorized_keys" ssh-keyscan <%= node['hostname'] %> > "${user_ssh_dir}/known_hosts" chmod 0600 "${user_ssh_dir}/known_hosts" -chown ${PAM_USER}:$(id -g ${PAM_USER}) -R "${user_ssh_dir}" \ No newline at end of file +chown ${USER}:$(id -g ${USER}) -R "${user_ssh_dir}"