Skip to content

Commit

Permalink
Move SSH key generation script from pam.d to /etc/profile
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Quentin-M committed Sep 28, 2022
1 parent cb63b87 commit 20cc762
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
------
Expand Down
45 changes: 26 additions & 19 deletions cookbooks/aws-parallelcluster-config/recipes/directory_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand All @@ -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}"
chown ${USER}:$(id -g ${USER}) -R "${user_ssh_dir}"

0 comments on commit 20cc762

Please sign in to comment.