Rootwrap
架构
目的
root 封装器的目标是,允许一个服务特有的非特权用户以可能的最安全的方式去以 root 用户去运行一些命令。曾经,Nova 使用一个特定的 sudoers 文件列出所有的 nova 用户允许运行的命令列表,运行时直接使用 sudo 来以 root 用户执行。然而,这种方式难以管理。sudoers 文件是特定包的一部分(并且格式依赖于特定包)。它不允许复杂的过滤参数(高级过滤)。rootwrap 就是被设计成解决这个问题的。
Oslo 的孵化项目
rootwrap 代码目前是在 oslo 孵化器管理的。它被使用在多个 OpenStack 项目(Nova, Cinder, Neutron)中。为了保持简洁,这个文档将以 nova 代码说明(nova-rootwrap)。要应用文档到项目中,只需要把下面提到的所有的 nova 替换成 $PROJECT。
rootwrap 如何工作
不像直接使用 sudo 工作,Nova 调用 sudo nova-rootwrap /etc/nova/rootwrap.conf 工作。一般的 sudoers 文件让 nova 用户以 root 用户权限执行 nova-rootwrap。nova-rootwrap 在配置文件中查找过滤器定义目录,并且加载这些命令过滤器。然后 nova-rootwrap 检查请求中的命令是否匹配这些过滤器,如果匹配那么就运行(以 root 权限)。如果不匹配,就拒绝该请求。
安全模型
增多的步骤是整个被 root 用户控制的。sudoers 文件入口()允许 nova 运行(以 root 用户)一个特定的 rootwrap 可执行程序,并且必须提供一个特定的配置文件(所有者应该是 root)。nova-rootwrap 从一个干净的 PYTHONPATH (系统默认的)中导入 python 模块。配置文件指定了 root 用户拥有的过滤器定义目录,这些目录中包含一些 root 拥有的过滤器定义文件。这个工作链保证了 nova 用户本身并不控制 nova-rootwrap 使用的配置文件和模块。
终端用户文档
你必须通过在 nova.conf 中进行一下设置,给 Nova 提供一个 rootwrap 配置文件的地址:
rootwrap_config=/etc/nova/rootwrap.conf
这里使用的配置文件必须和 sudoers 入口里定义的配置文件一致(见下面),否则命令会被拒绝!除此之外不需要再制定 root_helper 参数。
分发打包用户文档
Sudoers 入口
打包者需要保证 Nova 节点包含一个 sudoers 入口,让 nova 用户使用 root 身份运行 nova-rootwrap,指定 root 所有的 rootwrap.conf 配置文件,并且允许后面接任意的参数:
nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap /etc/nova/rootwrap.conf *
过滤器路径
Nova 在 rootwrap.conf 中查找 filters_path,在过滤器路径中包含了过滤器定义文件所在的目录。推荐 Nova 提供的过滤器从 /usr/share/nova/rootwrap,其它的用户过滤器从 /etc/nova/rootwrap.d 中加载。
[DEFAULT]
filters_path=/etc/nova/rootwrap.d,/usr/share/nova/rootwrap
过滤器定义
最后,打包者需要在每个节点上安装过滤器定义文件,并且保持一致。你不应该在节点安装任何其它的过滤器文件,否则你将允许了额外的不需要的命令被 nova 以 root 用户执行。
节点相适应的过滤器文件必须被安装在一个 filters_pat 目录下(一个较好的选择是 /usr/share/nova/rootwrap)。比如,在计算节点上,你应该只有一个 /usr/share/nova/rootwrap/compute.filters 过滤器文件。这个文件应该属于 root 并且只有 root 可写。
所有的过滤器定义可以在 Nova 的源代码下的 etc/nova/rootwrap.d 下找到。
插件编写者文档
加入新的以 root 用户执行的命令
插件编写者也许想要让 nova 用户以 root 用户运行一下其他的命令。这些人应该使用 nova.utils.execute(run_as_root=True) 来实现。他们应该创建他们自己定义的过滤器文件(root 所有并且只有 root 可写!)然后安装在其中一个 filters_path 下。比如 foobar 插件可以定义它的过滤器为 /etc/nova/rootwrap.d/foobar.filters。
过滤器文件的格式在后面的篇章中定义了。
项目开发者文档
加入新的以 root 用户执行的命令
核心开发者也许想要让 nova 用户以 root 用户运行一下其他的命令。这些人应该使用 nova.utils.execute(run_as_root=True) 来实现。他们需要在相应 Nova 源码中的 /etc/nova/rootwrap.d/.filters 文件中加入该命令。比如,想要加入一个命令被计算节点使用,他们应该修改文件 /etc/nova/rootwrap.d/compute.filters。
过滤器文件的格式在后面的篇章中定义了。
加入你自己的过滤器类型
默认的过滤器 CommandFilter 是十分基本的。它只检查命令的名字是否匹配,而没有更高级的针对参数的检查。许多其他的特定命令的过滤器类型是可用的,详情见后面的篇章。
这就是说,你可以轻松地定义新的过滤器类型来更好的控制你允许 nova 以 root 用户执行的命令。在filters.py code可以看到详细的信息。
参考
rootwrap.conf
rootwrap.conf 文件被用来配合 nova-rootwrap 工作。因为它是在可信任的安全的路径,它需要是
root 拥有的且只能被 root 用户修改。它同时存在于 sudoers 和 Nova 的配置文件中。
它是用 INI 文件格式,有下面几段和参数:
[DEFAULT] | ::: |
---|---|
filters_path | 逗号分隔的包含过滤器定义文件的目录,所有者都是 root 且仅 root 可写。filters_path=/etc/nova/rootwrap.d,/usr/share/nova/rootwrap |
exec_dirs | 逗号分隔的查找可执行程序的目录,以防过滤器没有明确地指定完整的路径。如果没有,默认使用系统的 PATH 路径。所有的列出来的目录都必须是 root 所有且仅 root 可写。 |
use_syslog | 打开向 syslog 写日志,默认值是 False。 use_syslog=True |
syslog_log_facility | 使用哪一种syslog模式去进行日志记录。合法的值包括,auth,authpriv,syslog,user0,user1…默认值是 syslog。syslog_log_facility=syslog |
syslog_log_level | 记录哪些信息。INFO 表示记录所有,ERROR 表示只记录不成功的尝试。syslog_log_level=ERROR |
.filters 文件
过滤器定义文件包含一些过滤器,nova-rootwrap 将使用这些过滤器来允许或者拒绝特定的命令。这些文件通常以 .filters 为后缀。因为它是在可信任的安全的路径,它需要是 root 拥有的且只能被 root 用户修改。它们在 rootwrap.conf 文件中被指定。
它使用 INI 文件格式,格式中包含 [Filters]段以及几行,每一行都有一个特殊的参数名字(不同于你定义的任何过滤器)。
[Filters] | ::: |
---|---|
filter_name(独特的) | 逗号分隔,第一个表示使用的过滤器类,接下来是过滤器参数(根据选择的过滤器不同而变化) |
看下面的篇幅了解每一个过滤器类的参数。
可用的过滤器类
CommandFilter
基本值只检查调用的可执行程序的基础过滤器,参数是:
+ 允许的可执行程序
+ 用户在什么条件下执行命令
例子:允许使用 root 执行 kpartx,使用任意参数:kpartx: CommandFilter, kpartx, root
RegExpFilter
通用的过滤器检查调用的可执行程序,然后使用一系列的正则表达式来检查所有随后的参数。参数是:
1. 允许的可执行程序
2. 运行程序的用户
3. 用来匹配第一个(以及之后的)命令参数的(以及之后的)正则表达式
例子: 允许运行 /usr/sbin/tunctl,但是仅仅带着三个参数,第一个和第二个分别是 -b 和 -t:
tunctl: /usr/sbin/tunctl, root, tunctl, -b, -t, .*
PathFilter
通用的过滤器,允许你检查提供的路径是否归入到一个给定的目录。参数是:
- 允许的可执行程序
- 运行程序的用户
3.(以及之后的)命令参数
存在着三种命令参数:’pass’ 接受任何参数值,一个 string 值接受匹配到的 string 参数,除非 string 以 ‘/’ 开始,这意味着它将接受任意的该目录匹配到的路径。
例子:允许将 /var/lib/images 下的任意文件 chown 成 ‘nova’ 用户
chown: PathFilter, /bin/chown, root, nova, /var/lib/images
EnvFilter
过滤器允许调用代码设置额外的环境变量。参数是:
1. ‘env’
2. 运行程序的用户
3. (以及之后的)可以设置的环境变量的名字,后缀是’=’
4. 允许的可执行程序
ReadFileFilter
特定的过滤器,允许你以 root 用户使用 cat 读取文件。参数是:
1. 你想用 root 用户读取的文件的路径
例子:允许以 root 执行 “cat /etc/iscsi/initiatorname.iscsi”
KillFilter
Kill 指定的过滤器,允许在执行命令前,检查受影响的进程和发送的信号。参数是:
1. 使用哪个用户去执行 kill
2. 执行命令影响的可执行程序
3. (以及之后的)允许发送的信号
例子:允许发送 -9 或者 -HUB 信号给 /usr/sbin/dnsmasq 进程:
kill_dnsmasq: KillFilter, root, /usr/sbin/dnsmasq, -9, -HUP
IpFilter
ip 指定的过滤器允许运行任何 ip 命令,除了 ip netns (只允许 list, add, delete 子命令)。参数是:
1. 允许的可执行程序(‘ip’)
2. 使用哪个用户去运行 ip
例子:允许运行任意的 ip 命令,除了 ip netsns exec 和 ip netns monitor。
ip: IpFilter, ip, root
IpNetnsExecFilter
特定的 ip 过滤器,它允许运行带一定条件的 ip netns exec 簇的命令。如果要能在 ip netns exec 运行的命令,必须匹配其它的过滤器。参数是:
1. 允许的可执行程序(‘ip’)
2. 使用哪个用户去运行 ip
例子:允许运行 ip netns exec , 只要 匹配其它的过滤器:
ip: IpNetnsExecFilter, ip, root
注:全文翻译自RootWrap官方文档