Rootwrap
架构
目的
root wrapper 的目标是允许服务特定的非特权用户以最安全的方式作为 root 用户运行一些操作。 历史上,Nova 使用了一个特定的 sudoers 文件,列出了 nova 用户允许运行的每个命令,并使用 sudo 以 root 身份运行该命令。 然而,这很难维护。 sudoers 文件是(及其格式取决于)特定打包的一部分。 它不允许对参数进行复杂的过滤(高级过滤器)。 rootwrap 被 设计 用于解决这些问题。
一个 Oslo 孵化项目
Rootwrap 代码现在在 oslo-incubator 中维护。 它在多个 OpenStack 项目(Nova、Cinder、Neutron...)中被重用。 为了保持简单,本文档将讨论 nova 代码的副本(nova-rootwrap)。 要将本文档应用于 $PROJECT,只需将 'nova' 替换为 $PROJECT 在下面的每个提及中即可。
毕业 孵化项目。 git log。(2013 年 12 月 2 日)
rootwrap 的工作原理
Nova 不只是调用 sudo make me a sandwich,而是调用 sudo nova-rootwrap /etc/nova/rootwrap.conf make me a sandwich。 一个通用的 sudoers 条目允许 nova 用户以 root 身份运行 nova-rootwrap。 nova-rootwrap 查找其配置文件中的过滤器定义目录,并从中加载 命令过滤器。 然后,它检查 Nova 请求的命令是否与这些过滤器中的一个匹配,在这种情况下,它将执行该命令(以 root 身份)。 如果没有过滤器匹配,则拒绝该请求。
安全模型
升级路径完全由 root 用户控制。 一个 sudoers 条目(由 root 拥有)允许 nova 运行(作为 root)一个特定的 rootwrap 可执行文件,并且仅使用一个特定的配置文件(也应由 root 拥有)。 nova-rootwrap 从清理后的(和系统默认的)PYTHONPATH 中导入所需的 Python 模块。 配置文件(也由 root 拥有)指向由 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
该行中定义的目录都应存在,并且只能由 root 用户拥有和写入。
过滤器定义
最后,封装需要为每个节点安装与该节点对应的过滤器定义文件。 您不应该在该节点上安装任何其他过滤器文件,否则您将允许额外的未经需要命令以 root 身份由 nova 运行。
与节点对应的过滤器文件必须安装在 filters_path 目录之一中(最好是 /usr/share/nova/rootwrap)。 例如,在计算节点上,您应该只拥有 /usr/share/nova/rootwrap/compute.filters。 该文件应只能由 root 用户拥有和写入。
所有过滤器定义文件都可以在 Nova 源代码的 etc/nova/rootwrap.d 下找到。
插件编写者文档
添加新的以 root 身份运行的命令
插件编写者可能需要让 nova 用户以 root 身份运行额外的命令。 他们应该使用 nova.utils.execute(run_as_root=True) 来实现这一点。 他们应该创建自己的过滤器定义文件并将其安装(只能由 root 用户拥有和写入!)到 filters_path 目录之一(最好是 /etc/nova/rootwrap.d)。 例如,foobar 插件可以将它的额外过滤器定义在 /etc/nova/rootwrap.d/foobar.filters 文件中。
过滤器文件的格式如下,在参考部分中定义。
项目开发者文档
添加新的以 root 身份运行的命令
核心开发者可能需要让 nova 用户以 root 身份运行额外的命令。 他们应该使用 nova.utils.execute(run_as_root=True) 来实现这一点,并在 Nova 源代码的 /etc/nova/rootwrap.d/ 中添加一个过滤器,用于他们需要的命令。 例如,要添加需要在计算节点上运行的命令,他们应该修改 /etc/nova/rootwrap.d/compute.filters 文件。
过滤器文件的格式如下,在参考部分中定义。
添加自己的过滤器类型
默认过滤器类型 CommandFilter 非常基础。 它只检查调用的可执行文件是否匹配,它不会对命令参数执行高级检查。 还有许多其他更特定于命令的过滤器类型可用,请参阅参考部分了解详细信息。
也就是说,您可以轻松定义新的过滤器类型,以进一步控制您实际允许 nova 用户以 root 身份运行的命令。 请参阅 filters.py 代码 了解详细信息。
参考资料
rootwrap.conf
rootwrap.conf 文件用于影响 nova-rootwrap 的工作方式。 由于它位于受信任的安全路径中,因此它需要只能由 root 用户拥有和写入。 它的位置在 sudoers 条目和 Nova 配置文件中都指定了。
它使用带有以下部分和参数的 INI 文件格式
| [DEFAULT] | |
| filters_path | 包含过滤器定义文件的目录的逗号分隔列表。 列出的所有目录都必须由 root 拥有且只能由 root 写入filters_path=/etc/nova/rootwrap.d,/usr/share/nova/rootwrap |
| exec_dirs | 如果过滤器没有显式指定完整路径,则要在其中搜索可执行文件的目录的逗号分隔列表。 如果未指定,则默认为系统 PATH 环境变量。 列出的所有目录都必须由 root 拥有且只能由 root 写入exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin |
| use_syslog | 启用 syslog 记录。 默认值为 Falseuse_syslog=True |
| syslog_log_facility | 用于 syslog 记录的 syslog facility。 有效值包括 auth、authpriv、syslog、user0、user1... 默认值为“syslog”syslog_log_facility=syslog |
| syslog_log_level | 要记录的消息。 INFO 表示记录所有用法,ERROR 表示仅记录未成功的尝试syslog_log_level=ERROR |
.filters 文件
过滤器定义文件包含 nova-rootwrap 将用于允许或拒绝特定命令的过滤器列表。 通常以 .filters 后缀结尾。 由于它们位于受信任的安全路径中,因此它们需要只能由 root 用户拥有和写入。 它们的位置在 rootwrap.conf 文件中指定。
它使用带有 [Filters] 部分和多行 INI 文件格式,每行都有一个唯一的参数名称(对于您定义的每个过滤器不同)
| [Filters] | |
| filter_name(对于每个过滤器不同) | 逗号分隔的列表,首先是使用的 Filter 类,然后是该 Filter 的参数(根据所选 Filter 类而异)。kpartx: CommandFilter, /sbin/kpartx, root |
有关每个 Filter 类的参数,请参见下文。
可用的过滤器类
CommandFilter
基本过滤器,仅检查调用的可执行文件。 参数是
- 允许的可执行文件
- 运行命令的用户
示例:允许以 root 用户身份运行 kpartx,并使用任何参数:kpartx: CommandFilter, kpartx, root
RegExpFilter
通用过滤器,它首先检查调用的可执行文件,然后使用正则表达式列表来检查所有后续参数。 参数是
- 允许的可执行文件
- 运行命令的用户
- (以及以下)用于匹配第一个(和后续)命令参数的正则表达式
示例:允许运行 /usr/sbin/tunctl,但仅使用三个参数,前两个参数为 -b 和 -t:tunctl: /usr/sbin/tunctl, root, tunctl, -b, -t, .*
PathFilter
通用过滤器,允许您检查作为参数提供的路径是否落入给定的目录中。 参数是
- 允许的可执行文件
- 运行命令的用户
- (以及以下)命令参数。
命令参数有三种类型:'pass' 将接受任何参数值,字符串将仅接受相应的字符串作为参数,除非该字符串以 '/' 开头,在这种情况下,它将接受解析为相应目录的任何路径。
示例:允许 chown 到 'nova' 用户,将任何文件 chown 到 /var/lib/images:chown: PathFilter, /bin/chown, root, nova, /var/lib/images
EnvFilter
允许调用代码设置额外的环境变量的过滤器。 参数是
- 'env'
- 运行命令的用户
- (以及以下)可以设置的环境变量的名称,后跟 '='
- 允许的可执行文件
示例:允许以 root 身份运行 CONFIG_FILE=foo NETWORK_ID=bar dnsmasq ...:dnsmasq: EnvFilter, env, root, CONFIG_FILE=, NETWORK_ID=, dnsmasq
ReadFileFilter
特定过滤器,允许您使用 cat 以 root 身份读取文件。 参数是
- 您想要作为 root 用户读取的文件的路径。
示例:允许以 root 身份运行“cat /etc/iscsi/initiatorname.iscsi”:read_initiator: ReadFileFilter, /etc/iscsi/initiatorname.iscsi
KillFilter
特定于 kill 的过滤器,在允许该命令之前,会检查受影响的进程和发送的信号。 参数是
- 运行 kill 的用户
- 仅影响正在运行该可执行文件的进程
- (以及以下)允许发送的信号
示例:允许发送 -9 或 -HUP 信号到 /usr/sbin/dnsmasq 进程:kill_dnsmasq: KillFilter, root, /usr/sbin/dnsmasq, -9, -HUP
IpFilter
特定于 ip 的过滤器,允许运行任何 ip 命令,但 ip netns 除外(在这种情况下,它仅允许 list、add 和 delete 子命令)。 参数是
- 允许的可执行文件('ip')
- 运行 ip 的用户
示例:允许运行任何 ip 命令,但 ip netns exec 和 ip netns monitor 除外:ip: IpFilter, ip, root
IpNetnsExecFilter
特定于 ip 的过滤器,允许在 ip netns exec 下运行任何其他允许的命令。 指定给 ip netns exec 的命令必须匹配另一个过滤器,此过滤器才能接受它。 参数是
- 允许的可执行文件('ip')
- 运行 ip 的用户
示例:允许运行 ip netns exec <namespace> <command>,只要 <command> 匹配另一个过滤器:ip: IpNetnsExecFilter, ip, root