pam_slurm_adopt

该模块的目的是防止用户通过 SSH 登录到没有正在运行作业的节点,并跟踪 SSH 连接和任何其他生成的进程,以便进行计费,并确保在作业完成时进行完全的作业清理。该模块通过确定发起 SSH 连接的作业来实现这一点。用户的连接被“采纳”到作业的“外部”步骤中。当访问被拒绝时,用户将收到相关的错误消息。

内容

安装

源代码:

在您的 Slurm 源代码目录中,导航到 ./contribs/pam_slurm_adopt/ 并运行

make && make install

以 root 身份运行。这将把 pam_slurm_adopt.a、pam_slurm_adopt.la 和 pam_slurm_adopt.so 放置在 /lib/security/(在 Debian 系统上)或 /lib64/security/(在 RedHat/SuSE 系统上)。

RPM:

包含的 slurm.spec 将构建一个 slurm-pam_slurm RPM,该 RPM 将安装 pam_slurm_adopt。请参阅 快速入门管理员指南,以获取有关管理基于 RPM 的安装的说明。

DEB:

包含的 Debian 打包脚本将构建 slurm-smd-libpam-slurm-adopt 包,该包将安装 pam_slurm_adopt。 快速入门管理员指南,以获取有关管理基于 DEB 的安装的说明。

Slurm 配置

PrologFlags=contain 必须在 slurm.conf 中设置。这设置了 SSH 启动的进程将被采纳的“外部”步骤。您还必须在 slurm.conf 中启用任务/cgroup 插件。请参阅 Slurm cgroups 指南。 注意 此选项必须在使用此模块 之前 设置。该模块的检查基于已经启动的本地步骤。未使用此选项启动的作业没有外部步骤,因此 pam_slurm_adopt 将无法访问这些作业。

LaunchParameters=ulimit_pam_adopt 将在由外部步骤采纳的进程中设置 RLIMIT_RSS,类似于在常规步骤中运行的任务。

slurm.conf 中的 UsePAM 选项与 pam_slurm_adopt 无关。

SSH 配置

确保 UsePAM 在 /etc/ssh/sshd_config 中设置为 On(默认情况下应为开启)。

确保在 sshd_config(在计算节点上)中仅启用受支持的 AuthenticationMethods。目前,仅支持 publickeypassword。特别是 keyboard-interactive 明确不支持,必须从 AuthenticationMethods 中移除。如果未遵循此步骤,进程采纳将会中断,SSH 会话将在作业结束后仍然存在。有关更多信息,请参见 限制

PAM 配置

在 /etc/pam.d 中的适当文件中添加以下行,例如 system-auth 或 sshd(您可以使用“required”或“sufficient” PAM 控制标志中的任意一个):

account    required      pam_slurm_adopt.so

插件的顺序非常重要。pam_slurm_adopt.so 应该是账户堆栈中的最后一个 PAM 模块。包含的文件,如 common-account,通常应在 pam_slurm_adopt 之前包含。 您可能在 sshd 中有以下账户堆栈:

account    required      pam_nologin.so
account    include       password-auth
...
-account    required      pam_slurm_adopt.so

注意 pam_slurm_adopt 的账户条目前的“-”。这允许 PAM 在找不到 pam_slurm_adopt.so 文件时优雅地失败。如果 Slurm 在共享文件系统上,例如 NFS,则建议这样做,以避免在共享文件系统挂载或关闭时被锁定在节点之外。

pam_slurm_adopt 必须与任务/cgroup 任务插件和 proctrack/cgroup proctrack 插件一起使用。 pam_systemd 模块将与 pam_slurm_adopt 冲突,因此您需要在所有包含在 sshd 或 system-auth 中的文件中禁用它(例如 password-auth、common-session 等)。

如果您需要 pam_systemd 的用户管理功能,例如处理用户运行时目录 /run/user/$UID,您可以让 prolog 脚本运行 'loginctl enable-linger $SLURM_JOB_USER',并在确保节点上没有来自该用户的其他作业后,epilog 脚本再次禁用它,运行 'loginctl disable-linger $SLURM_JOB_USER'。如果您的软件需要,您还需要导出 XDG_* 环境变量。 您可以在这里看到 prolog 和 epilog 脚本的示例:

Prolog:
loginctl enable-linger $SLURM_JOB_USER
exit 0
TaskProlog:
echo "export XDG_RUNTIME_DIR=/run/user/$SLURM_JOB_UID"
echo "export XDG_SESSION_ID=$(</proc/self/sessionid)"
echo "export XDG_SESSION_TYPE=tty"
echo "export XDG_SESSION_CLASS=user"
Epilog:
#仅在这是该用户正在运行的最后一个作业时禁用 linger。
O_P=0
for pid in $(scontrol listpids | awk -v jid=$SLURM_JOB_ID 'NR!=1 { if ($2 != jid && $1 != "-1"){print $1} }'); do
        ps --noheader -o euser p $pid | grep -q $SLURM_JOB_USER && O_P=1
done
if [ $O_P -eq 0 ]; then
        loginctl disable-linger $SLURM_JOB_USER
fi
exit 0

您还必须确保没有其他 PAM 模块在到达 pam_slurm_adopt.so 之前短路账户堆栈。从上面的示例中,包含的 password-auth 文件中的以下两行已被注释掉:

#account    sufficient    pam_localuser.so
#-session   optional      pam_systemd.so

注意:这可能涉及编辑一个自动生成的文件。 请勿运行生成该文件的配置脚本,否则您的更改将被擦除。

管理访问配置

pam_slurm_adopt 将始终允许 root 用户访问,并且在检查 slurm 配置之前也会这样做。如果您希望其他管理员也可以使用自己的用户帐户访问系统,可以通过与 pam_slurm_adopt 堆叠其他模块来实现。

将 pam_access 与 pam_slurm_adopt 堆叠是一种允许管理访问的方法,有两种可能的实现方式,行为上有细微差别。 这两种方式都需要编辑 pam_access 配置文件 (/etc/security/access.conf)。在以下示例中,access.conf 文件将允许“wheel”组的成员登录。

+:(wheel):ALL
-:ALL:ALL

然后,您需要在 /etc/pam.d/sshd 文件中堆叠这些模块。这里的顺序很重要,每种顺序都有不同的影响。在下面的示例中,pam_slurm_adopt 首先作为“sufficient”列出,随后是 pam_access。 在此配置中,当管理员有作业在运行时,他们的 SSH 会话将被采纳到作业中。如果没有,pam_access 将允许访问,但请注意,pam_slurm_adopt 仍将发出“访问被拒绝”的消息。

account    sufficient    pam_slurm_adopt.so
account    required      pam_access.so

如果将此顺序反转,将 pam_access(sufficient)放在 pam_slurm_adopt(required)之前,管理组的成员将完全绕过 pam_slurm_adopt。

account    sufficient    pam_access.so
account    required      pam_slurm_adopt.so

pam_listfile 模块是另一个可以与 pam_slurm_adopt 堆叠并实现类似结果的模块。在以下示例中,它将允许指定文件中的所有用户登录,跳过 pam_slurm_adopt 模块。与 pam_access 类似,这也可以反转,具有相同的影响。

account    sufficient    pam_listfile.so item=user sense=allow onerr=fail file=/path/to/allowed_users_file
account    required      pam_slurm_adopt.so

pam_listfile 模块还可以配置为查找组的成员资格。在此示例中,插件检查用户是否属于 'groupfile' 中指定的组之一,而不是检查用户。 如果这些用户需要 pam_systemd,您可以在会话阶段将其链接到 pam_listfile.so 模块,如下所示。 如果 pam_listfile 模块成功,则评估将继续(success=ignore)。 否则,下一个模块(pam_systemd)将被忽略(default=1 跳过下一个模块)。在此示例中,pam_systemd 模块仅用于管理员用户。

account    sufficient                    pam_listfile.so item=group sense=allow onerr=fail file=/path/to/allowed_users_file
-account   required                      pam_slurm_adopt.so

session    [default=1 success=ignore]    pam_listfile.so item=group sense=allow onerr=fail file=/etc/groupfile
-session   optional                      pam_systemd.so

有关 pam_access 和 pam_listfile 的功能和配置选项的更多信息,请参阅它们各自的手册页。

pam_slurm_adopt 模块选项

该模块是可配置的。将这些选项添加到 /etc/pam.d/ 中适当文件的 pam_slurm_adopt 行的末尾(例如,sshd 或 system-auth):

account sufficient pam_slurm_adopt.so optionname=optionvalue

该模块具有以下选项:

action_no_jobs
如果用户在节点上没有作业,则执行的操作。可配置的值为:
ignore
不执行任何操作。继续到下一个 pam 模块。
deny (默认)
拒绝连接。
action_unknown
当用户在节点上有多个作业 并且 RPC 无法找到源作业时执行的操作。如果 RPC 机制在您的环境中正常工作,则此选项可能仅在从登录节点连接时相关。可配置的值为:
newest (默认)
在具有 cgroup/v1 的系统上,选择节点上最新的作业。 “最新”作业是根据作业的 step_extern cgroup 的 mtime 选择的; 询问 Slurm 将需要向控制器发出 RPC。因此,必须使用内存 cgroup,以便代码可以检查 cgroup 目录的 mtime。用户可以通过 SSH 登录,但可能会被采纳到比他们打算检查的作业更早退出的作业中。SSH 连接至少将受到适当限制,如果这成为问题,用户可以被告知更好的实现目标的方法。 注意:如果模块无法检索 cgroup mtime,则选择的作业可能不是最新的。 在具有 cgroup/v2 的系统上,最新的作业仅是具有最大 ID 的作业,因此这并不能确保它确实是最新的作业。
allow
允许连接通过而不进行采纳。
deny
拒绝连接。
action_adopt_failure
如果进程无法被采纳到任何作业中,则执行的操作,原因可能是任何原因。如果进程无法被采纳到由 callerid RPC 确定的作业中,它将继续执行 action_unknown 代码并尝试在那里进行采纳。在这一点上的失败或如果只有一个作业将导致采取此操作。可配置的值为:
allow (默认)
允许连接通过而不进行采纳。警告:此值不安全,仅建议用于测试目的。我们建议使用“deny”。
deny
拒绝连接。
action_generic_failure
如果出现某些故障,例如无法与本地 slurmd 通信或内核未提供正确的功能,则执行的操作。可配置的值为:
ignore (默认)
不执行任何操作。继续到下一个 pam 模块。警告:此值不安全,仅建议用于测试目的。我们建议使用“deny”。
allow
允许连接通过而不进行采纳。
deny
拒绝连接。
disable_x11
关闭 Slurm 内置的 X11 转发支持。可配置的值为:
0 (默认)
如果连接被采纳的作业启用了 Slurm 的 X11 转发,则 DISPLAY 变量将被覆盖为 X11 隧道端点详细信息。
1
不检查 Slurm 的 X11 转发支持,并且不更改 DISPLAY 变量。
join_container
控制与 job_container/tmpfs 插件的交互。 可配置的值为:
true (默认)
尝试加入由 job_container/tmpfs 插件创建的容器。
false
不尝试加入容器。
log_level
请参见 SlurmdDebug 在 slurm.conf 中的可用选项。 默认 log_level 为 info
nodename
如果 slurm.conf 中定义的 NodeName 与此节点的主机名(由 hostname -s 报告)不同,则必须将其设置为此主机作为的 slurm.conf 中的 NodeName。
service
此模块应运行的 PAM 服务名称。默认情况下,它仅在为其设计的 sshd 上运行。 可以指定不同的服务名称,如“login”或“*”,以允许该模块在任何服务上下文中运行。对于本地 PAM 登录,此模块可能会导致意外行为或甚至安全问题。因此,如果服务名称不匹配,则此模块将不执行采纳逻辑,并立即返回 PAM_IGNORE。

防火墙、IP 地址等

slurmd 应可从用户可能启动 SSH 的任何 IP 地址访问。确定源作业的 RPC 必须能够访问该特定 IP 地址上的 slurmd 端口。如果源节点上没有 slurmd,例如在 登录节点 上,最好让 RPC 被拒绝,而不是静默丢弃。这将允许 RPC 发起者更好地响应。

SELinux

SELinux 可能与 pam_slurm_adopt 冲突,但通常可以并存。这是一个在相当标准的 Debian 系统上使用的类型强制文件示例。提供此示例是为了提供一些方向,并展示使其工作所需的内容,但可能需要额外的修改。

module pam_slurm_adopt 1.0;

require {
	type sshd_t;
	type var_spool_t;
	type unconfined_t;
	type initrc_var_run_t;
	class sock_file write;
	class dir { read search };
	class unix_stream_socket connectto;
}

#============= sshd_t ==============
allow sshd_t initrc_var_run_t:dir search;
allow sshd_t initrc_var_run_t:sock_file write;
allow sshd_t unconfined_t:unix_stream_socket connectto;
allow sshd_t var_spool_t:dir read;
allow sshd_t var_spool_t:sock_file write;

某些插件可能需要比这更多的权限。 特别是,job_container/tmpfs 将需要更类似于以下内容:

module pam_slurm_adopt 1.0;

require {
	type nsfs_t;
	type var_spool_t;
	type initrc_var_run_t;
	type unconfined_t;
	type sshd_t;
	class sock_file write;
	class dir { read search };
	class unix_stream_socket connectto;
	class fd use;
	class file read;
	class capability sys_admin;
}

#============= sshd_t ==============
allow sshd_t initrc_var_run_t:dir search;
allow sshd_t initrc_var_run_t:sock_file write;
allow sshd_t nsfs_t:file read;
allow sshd_t unconfined_t:fd use;
allow sshd_t unconfined_t:unix_stream_socket connectto;
allow sshd_t var_spool_t:dir read;
allow sshd_t var_spool_t:sock_file write;
allow sshd_t self:capability sys_admin;

限制

在内部,某些 AuthenticationMethods 会导致 sshd 在登录流程中派生一个额外的进程,ssh 会部分卸载身份验证对话。这可能会混淆 PAM 模块,并可能会破坏与 pam_slurm_adopt 的进程采纳。

在使用 Slurm 中的 SELinux 支持时,通过 pam_slurm_adopt 启动的会话不一定与其关联的作业处于相同的上下文中。

最后修改于 2025 年 3 月 26 日