本文介绍安装并使用udica为容器构建SELinux策略的方法。当现代IT环境转向Linux容器时,保护这些环境的需求与以往一样重要,容器是一种过程隔离技术,虽然容器可以是一种防御机制,但它们只有在与SELinux结合使用时才会出类拔萃。Fedora SELinux工程部门构建了一个新的独立工具udica,通过自动检查容器来生成容器的SELinux策略配置文件,本文重点介绍为什么在容器领域需要udica,以及它如何使SELinux和容器更好地协同工作,你将找到容器的SELinux分离示例,可以避免因为通用SELinux类型container_t而关闭保护,使用udica,可以轻松地使用有限的SELnux策略编写技能自定义策略。
SELinux技术 SELinux是一种安全技术,可为Linux系统带来主动安全性,它是一个标签系统,为所有主体(进程和用户)和对象(文件,目录,套接字等)分配标签,然后,这些标签将用于控制整个系统访问的安全策略中,值得一提的是,默认情况下,SELinux安全策略中不允许的内容被拒绝,策略规则由内核强制执行,这种安全技术已经在Fedora上使用了好几年,这种规则的一个真实例子是: allow httpd_t httpd_log_t: file { append create getattr ioctl lock open read setattr }; 该规则允许标记为httpd_t的任何进程创建,追加,读取和锁定标记为httpd_log_t的文件,使用ps命令,你可以列出所有进程及其标签: $ ps -efZ | grep httpd system_u:system_r:httpd_t:s0 root 13911 1 0 Apr14 ? 00:05:14 /usr/sbin/httpd -DFOREGROUND ... 参考:ps命令_Linux ps命令使用详解:报告当前系统的进程状态。 要查看哪些对象标记为httpd_log_t,请使用semanage: # semanage fcontext -l | grep httpd_log_t /var/log/httpd(/.)? all files system_u:object_r:httpd_log_t:s0 /var/log/nginx(/.)? all files system_u:object_r:httpd_log_t:s0 ... Fedora的SELinux安全策略在selinux-policyRPM包中提供。
SELinux与容器 在Fedora中,container-selinux rpm包为podman或docker等引擎启动的所有容器提供了通用的SELinux策略,其主要目的是保护主机系统免受容器过程的影响,并将容器彼此分开,例如,由SELinux限制的容器类型为container_t的容器只能读取执行usr中的文件并写入主机文件系统上的container_file_t文件类型,为防止容器相互攻击,使用多类别安全(MCS)。 由于容器使用的种类繁多,因此仅对容器使用一个通用策略是有问题的,一方面,默认容器类型(container_t)通常过于严格,例如: 1、Fedora SilverBlue需要容器来读/写用户的主目录。 2、Fluentd项目需要容器才能读取/var/log目录中的日志。 另一方面,对于某些用例,默认容器类型不是很严格: 1、它没有SELinux网络控制 - 所有容器进程都可以绑定到任何网络端口。 2、它没有对Linux功能的SELinux控制 - 所有容器进程都可以使用所有功能。 有两种解决方案可以处理这两种用例:为容器编写自定义SELinux安全策略,这可能很棘手,因为需要SELinux专业知识,为此,创建了udica工具。
介绍udica Udica为容器生成SELinux安全配置文件,它的概念基于SELinux用户空间支持的通用中间语言(CIL)中的“块继承”功能,该工具创建了一个组合的策略:从指定的CIL块(模板)继承的规则,以及通过检查容器JSON文件发现的规则,该文件包含挂载点和端口定义。 可以立即加载最终策略,或将其移动到另一个系统以加载到内核中,这是一个例子,使用一个容器: 1、安装/home作为读/写。 2、将/var/spool安装为只读。 3、公开端口tcp/21。 容器以此命令启动: # podman run -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it fedora bash 默认容器类型(container_t)不允许这三个操作中的任何一个,为了证明这一点,可以使用搜索工具来查询系统上是否存在允许规则: # sesearch -A -s container_t -t home_root_t -c dir -p read 没有允许规则允许标记为container_t的进程访问标记为home_root_t的目录(如/home目录),/var/spool也出现相同的情况,标记为var_spool_t: # sesearch -A -s container_t -t var_spool_t -c dir -p read 另一方面,默认策略完全允许网络访问: # sesearch -A -s container_t -t port_type -c tcp_socket allow container_net_domain port_type:tcp_socket { name_bind name_connect recv_msg send_msg }; allow sandbox_net_domain port_type:tcp_socket { name_bind name_connect recv_msg send_msg };
udica安装方法 安装所有依赖项的udica工具: $ sudo dnf install -y podman setools-console git container-selinux $ git clone https://github.com/containers/udica $ cd udica && sudo python3 ./setup.py install 或者,tou可以直接从git运行udica: $ python3 -m udica --help 另一种安装udica的方法是使用fedora存储库: # dnf install udica -y 或者你可以使用Python Package Index(Pypi): # pip install udica 确保SELinux处于执行模式 # setenforce 1 # getenforce Enforcing
固定容器 限制此访问并允许容器仅在TCP 21端口上绑定或使用相同的标签绑定将是很好的,你找到一个使用podman ps的示例容器,其ID为37a3635afb8f: # podman ps -q 37a3635afb8f 现在可以检查容器并将检查文件传递给udica工具,新策略的名称是my_container: # podman inspect 37a3635afb8f > container.json # udica -j container.json my_container Policy my_container with container id 37a3635afb8f created! Please load these modules using: # semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil} Restart the container with: "--security-opt label=type:my_container.process" parameter 刚刚为示例容器创建了自定义SELinux安全策略,现在,可以将此策略加载到内核中并使其处于活动状态,上面的udica输出甚至告诉你使用的命令: # semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil} 现在,必须重新启动容器以允许容器引擎使用新的自定义策略: # podman run --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it fedora bash 参考:安装以使用Podman可以在非root权限中运行Linux容器。 示例容器现在在新创建的my_container.process SELinux进程类型中运行: # ps -efZ | grep my_container.process unconfined_u:system_r:container_runtime_t:s0-s0:c0.c1023 root 2275 434 1 13:49 pts/1 00:00:00 podman run --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it fedora bash system_u:system_r:my_container.process:s0:c270,c963 root 2317 2305 0 13:49 pts/0 00:00:00 bash
看到结果 sesearch命令现在显示允许访问/home和/var/spool的规则: # sesearch -A -s my_container.process -t home_root_t -c dir -p read allow my_container.process home_root_t:dir { getattr ioctl lock open read search }; # sesearch -A -s my_container.process -t var_spool_t -c dir -p read allow my_container.process var_spool_t:dir { add_name getattr ioctl lock open read remove_name search write } 新的自定义SELinux策略还允许my_container.process仅绑定到标记为与TCP 21端口相同的TCP/UDP端口: # semanage port -l | grep 21 | grep ftp ftp_port_t tcp 21, 989, 990 # sesearch -A -s my_container.process -c tcp_socket -p name_bind allow my_container.process ftp_port_t:tcp_socket name_bind;
结语 udica工具可帮助你基于检查文件为容器创建SELinux策略,而无需任何SELinux专业知识(参考:Linux管理员的SELinux安全指南:42个SELinux答案)。
相关主题 |