跳到主要内容

podmansh - 在 Podman podmansh 容器中执行登录 shell

摘要

用于启动和管理具有特定 SELinux 配置的 Podman 容器。Podman 是一个开源项目,用于管理容器和容器镜像,与 Docker 功能相似,但不需要守护进程运行。

用于以特定用户的身份运行 Podman 容器,并应用特定的 SELinux 策略。

  1. 用户身份管理:脚本以特定用户的身份(在此例中是 fullu)运行容器,可能还保持了这个用户的 ID(UID)和组 ID(GID)。

  2. SELinux 策略配置:通过 PodmanArgs 设置了一系列的 SELinux 安全选项,允许容器在具有 SELinux 嵌套和特定上下文的环境中运行。这确保了容器受到 SELinux 访问控制策略的保护。

  3. 目录挂载:将用户的 $HOME/data 目录挂载到容器内部,并设置适当的 SELinux 上下文。这样,用户可以在容器内访问和修改这个目录的内容。

  4. 容器执行命令:脚本启动容器后,执行 sleep infinity 命令,使容器保持运行状态。

  5. 初始化目录:在容器启动前,确保 $HOME/data 目录存在,这通过 ExecStartPre 指令实现。

使用 podmansh

通常,你需要按照以下步骤操作:

  1. 安装和配置 Podman:确保你的系统上已经安装了 Podman,并且已经进行了必要的配置。

  2. 获取 podmansh 脚本:从项目或文档中获取 podmansh 脚本,并将其放置在适当的位置。

  3. 配置用户和环境:根据需要创建用户,并设置相关的 SELinux 策略。

  4. 运行 podmansh:作为特定用户(例如 fullu)运行 podmansh 脚本或命令,以启动和管理容器。

podmansh

描述

在用户登录系统时,在容器内执行用户 shell。用户将被添加到的容器可以通过 Podman Quadlet 文件进行定义。该用户仅可以访问在 Quadlet 文件中配置的卷和功能。

管理员可以在 /etc/containers/systemd/users 中创建一个 Quadlet,systemd 将在用户登录时为所有用户启动它。管理员可以创建一个包含容器名称 podmansh 的特定 Quadlet,然后允许用户使用登录 shell /usr/bin/podmansh。这些用户登录 shell 会自动通过 Podman 在 podmansh 容器内部执行。

可选地,管理员可以将 Quadlet 文件放置在 /etc/containers/systemd/users/${UID} 目录中,仅当此 UID 用户登录时,才会执行这些 Quadlet 服务。

用户通过所有安全机制(包括 SELinux)被限制在容器环境中。来自系统的唯一可用信息来自泄露到容器中的卷。

当用户会话启动时,systemd 将自动创建容器。当所有到用户会话的连接都被移除时,systemd 将停止容器。这意味着用户可以多次登录到系统,每个会话都连接到相同的容器。

管理员可以使用卷将主机系统上的特定主机数据暴露给用户,而不会使用户暴露于系统的其他部分。

可以使用 containers.conf 文件中的 podmansh_timeout 选项设置 podmansh 的超时时间。

请注意,podmansh 是一种特定于 Podman 的功能,允许管理员通过 systemd 和 Quadlet 文件为用户创建隔离的登录环境。这有助于限制用户对系统资源的访问,同时确保他们的会话在容器化的安全环境中执行。通过配置适当的卷和功能,管理员可以控制用户可以访问哪些系统资源和数据。

设置

以 root 身份运行,使用 useradd 创建用户登录会话。

# useradd -s /usr/bin/podmansh lockedu
# grep lockedu /etc/passwd
lockedu:x:4008:4008::/home/lockedu:/usr/bin/podmansh

创建一个类似于以下内容的 Podman Quadlet 文件。

完全锁定的容器,无法访问主机操作系统。

# USERID=$(id -u lockedu)
# mkdir -p /etc/containers/systemd/users/${USERID}
# cat > /etc/containers/systemd/users/${USERID}/podmansh.container << _EOF
[Unit]
Description=The podmansh container
After=local-fs.target

[Container]
Image=registry.fedoraproject.org/fedora
ContainerName=podmansh-%i
RemapUsers=keep-id
RunInit=yes
DropCapability=all
NoNewPrivileges=true

ExecStart=/bin/bash

[Install]
WantedBy=default.target
_EOF

请注意,上述 Quadlet 示例做了以下几点设置:

  • Image: 指定容器使用的镜像,这里使用了 Fedora 的官方镜像。
  • ContainerName: 容器名称,其中 %i 是一个 systemd 模板单元实例化的占位符,它将被替换为用户的 UID。
  • RemapUsers=keep-id: 这表示容器内的用户 ID 将与主机上的用户 ID 保持一致。
  • RunInit: 启用 systemd 初始化系统,这允许容器内部运行 systemd 管理的服务。
  • DropCapability=all: 删除容器内进程的所有 Linux 功能,增强安全性。
  • NoNewPrivileges=true: 确保容器内进程不会获得新的权限。
  • ExecStart: 容器启动后执行的命令,这里使用 /bin/bash 作为 shell。

此外,请确保 Quadlet 文件的路径和名称与您的设置相匹配。在这个例子中,我们为特定用户创建了一个 Quadlet 文件,并将其放置在 /etc/containers/systemd/users/${USERID}/ 目录下。

创建 Quadlet 文件后,您还需要启用和启动 systemd 用户服务,以便在用户登录时自动运行该容器。这通常涉及使用 systemctl 命令来启用和启动服务。然而,对于使用 podmansh 的情况,您可能不需要手动执行这些步骤,因为 systemd 会在用户登录时自动处理这些操作。

请确保在尝试使用 podmansh 之前,Podman 已经在系统上正确安装和配置,并且用户具有适当的权限来执行所需的操作。同时,也请检查您的发行版是否支持 podmansh 功能,以及是否需要其他特定的配置步骤。

您的要求是在 Podman 容器中允许用户在其用户命名空间内提升为 root 权限,并且能够从其宿主机的实际用户账户中永久读写内容。这通常不是一个推荐的安全做法,因为它破坏了容器化的隔离原则。然而,如果您确实有这样的需求,并且理解潜在的安全风险,可以按照以下步骤进行操作。

首先,确保 Podman 已经安装在您的系统上,并且 podmansh 已经配置为默认的 shell。然后,创建用户并设置相应的 Quadlet 文件。

# useradd -s /usr/bin/podmansh confinedu
# grep confinedu /etc/passwd
confinedu:x:4009:4009::/home/confinedu:/usr/bin/podmansh

接下来,创建 Quadlet 文件,并配置为允许用户在其用户命名空间内获得 root 权限,并且从宿主机的用户目录挂载数据。

# USERID=$(id -u confinedu)
# mkdir -p /etc/containers/systemd/users/${USERID}
# cat > /etc/containers/systemd/users/${USERID}/podmansh.container << '_EOF'
[Unit]
Description=The podmansh container for confinedu
After=local-fs.target

[Container]
Image=registry.fedoraproject.org/fedora
ContainerName=podmansh-%i
RemapUsers=keep-id
RunInit=yes

# Mount the user's home directory from the host into the container
Volume=/home/confinedu:/home/confinedu:Z

# Allow the user to become root within the container
Capability=CAP_SETUID+ep CAP_SETGID+ep CAP_SYS_ADMIN+ep

ExecStart=/bin/bash

[Service]
# Ensure the mount point exists in the container
ExecStartPre=/bin/mkdir -p /home/confinedu/data

[Install]
WantedBy=default.target
_EOF

在这个配置中,Volume 指令挂载了宿主机的 /home/confinedu 到容器的相同位置。这允许用户在容器内直接访问其宿主机的家目录。

Capability 指令赋予了容器内用户一些额外的 Linux 功能,允许用户提升权限。这里包括 CAP_SETUID, CAP_SETGID, 和 CAP_SYS_ADMIN,它们分别允许用户更改进程的用户和组 ID,以及执行某些系统管理任务。

请注意,CAP_SYS_ADMIN 是一个非常强大的功能,它基本上允许用户在容器内执行大多数系统管理任务,包括挂载文件系统、设置网络等。这明显削弱了容器的安全隔离,因此只在完全理解潜在风险的情况下使用。

创建 Quadlet 文件后,您需要重新加载 systemd 的配置,并可能还需要启用和启动相应的 systemd 用户服务。此外,由于这里涉及到敏感操作,请确保仔细审查您的配置,并考虑任何可能的安全影响。在生产环境中,通常不建议允许容器内的用户提升为 root 或拥有过多的 Linux 功能。

在这个例子中,我们创建了一个 Quadlet,其中容器内的用户被允许在具有 SELinux 分离的情况下执行容器,并且能够读取和写入 $HOME/data 目录的内容。SELinux(Security-Enhanced Linux)为 Linux 系统提供了访问控制安全策略,能够限制进程和文件的权限。

首先,我们以 root 用户身份运行,并创建一个新用户 fullu,其 shell 设置为 /usr/bin/podmansh

# useradd -s /usr/bin/podmansh fullu
# grep fullu /etc/passwd
fullu:x:4010:4010::/home/fullu:/usr/bin/podmansh

然后,我们获取该用户的 UID,并创建 Quadlet 文件的目录。

# USERID=$(id -u fullu)
# mkdir -p /etc/containers/systemd/users/${USERID}

接下来,我们创建 Quadlet 文件,并配置 SELinux 相关的选项以及挂载点。

# cat > /etc/containers/systemd/users/${USERID}/podmansh.container << '_EOF'
[Unit]
Description=The podmansh container
After=local-fs.target

[Container]
Image=registry.fedoraproject.org/fedora
ContainerName=podmansh-%i
RemapUsers=keep-id
RunInit=yes

# PodmanArgs 设置了 SELinux 的相关参数,允许嵌套容器和特定的 SELinux 上下文
PodmanArgs=--security-opt=unmask=/sys/fs/selinux \
--security-opt=label=nested \
--security-opt=label=user:container_user_u \
--security-opt=label=type:container_user_t \
--security-opt=label=role:container_user_r \
--security-opt=label=level:s0-s0:c0.c1023

# 挂载用户的 data 目录到容器中
Volume=%h/data:%h:Z

# 设置工作目录为用户的家目录
WorkingDir=%h

# 挂载 SELinux 文件系统到容器中,以便容器内可以访问 SELinux 功能
Volume=/sys/fs/selinux:/sys/fs/selinux

Exec=sleep infinity

[Service]
# 在容器启动前创建 data 目录
ExecStartPre=/usr/bin/mkdir -p %h/data

[Install]
RequiredBy=default.target
_EOF

在这个配置中,PodmanArgs 指令设置了一系列的 SELinux 安全选项,使得容器能够支持 SELinux 嵌套,并指定了特定的 SELinux 用户、类型、角色和级别。这些设置允许容器在 SELinux 的策略控制下运行,同时确保容器内部进程和文件受到适当的访问控制。

Volume 指令用于挂载用户的 data 目录到容器中,并且设置了正确的 SELinux 上下文(:Z 表示重新标记挂载的文件系统以符合容器内的策略)。这允许用户在容器内访问和修改这个目录。

WorkingDir 指令设置了容器的工作目录为用户的家目录,使得用户在容器启动后默认进入该目录。

最后,我们还挂载了宿主机的 /sys/fs/selinux 到容器内,以便容器能够访问 SELinux 的文件系统接口。

创建 Quadlet 文件后,您需要重新加载 systemd 的配置,并可能还需要启用和启动相应的 systemd 用户服务。

注意:SELinux 策略通常需要根据您的具体需求和系统环境进行定制。在实际部署时,您可能需要根据您的 SELinux 策略修改这些选项。此外,SELinux 的配置和管理需要谨慎操作,以避免意外地限制系统或应用程序的功能。

另请参阅

  • podman-container(1): 这个手册页描述了 containers.conf 文件的格式和内容,该文件通常用于配置容器运行时(如 Podman)的全局设置。

  • podman(1): 这是 Podman 容器引擎的手册页。Podman 是一个用于管理容器的工具,类似于 Docker,但是它不需要守护进程,可以直接作为非特权用户运行。

  • podman-exec(1): 这个手册页可能描述了如何使用 podman exec 命令在正在运行的容器内执行命令。

  • quadlet(5): 这可能是描述 Quadlet(可能是某种容器或虚拟化技术的配置或定义文件)的手册页。然而,需要注意的是,“quadlet”并不是一个广泛认可或标准的术语,这可能是特定环境或项目中的自定义术语。

历史

文档于 2023 年 5 月由Dan Walsh编译。是 Red Hat 公司的一位知名 SELinux 专家和贡献者。