云网牛站
所在位置:首页 > Linux教程 > 使用udica为容器构建SELinux策略

使用udica为容器构建SELinux策略

2019-05-06 21:18:54作者:陈自坚稿源:云网牛站

本文介绍安装并使用udica为容器构建SELinux策略的方法。当现代IT环境转向Linux容器时,保护这些环境的需求与以往一样重要,容器是一种过程隔离技术,虽然容器可以是一种防御机制,但它们只有在与SELinux结合使用时才会出类拔萃。Fedora SELinux工程部门构建了一个新的独立工具udica,通过自动检查容器来生成容器的SELinux策略配置文件,本文重点介绍为什么在容器领域需要udica,以及它如何使SELinux和容器更好地协同工作,你将找到容器的SELinux分离示例,可以避免因为通用SELinux类型container_t而关闭保护,使用udica,可以轻松地使用有限的SELnux策略编写技能自定义策略。

使用udica为容器构建SELinux策略

 

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答案)。

 

相关主题

在RHEL 8/CentOS 8系统中禁用SELinux的方法

精选文章
热门文章