nova分析(10)—— nova-rootwrap
一.nova-rootwrap的作用
部署玩过openstack的都应该知道,它会生成一个nova用户来管理所有服务.nova身份在linux中属于普通用户级别,避免了一些需要root身份运行的操作,提高linux系统的安全性.
但是openstack在实际过程中会调用很多外部命令,例如就network服务而言就有:`ip`,`ovs-vsctl`,`iptables`,`dnsmasq`,`brctl`等等,这些命令在linux中都是需要以root身份来运行的,如果是普通用户通常的做法是在命令前加`sudo`切换到root身份再执行这些命令,但是这个方法在执行命令的时候需要输入密码确认操作,为了避免输入密码,我们需要配置一下sudo.
建议的方法是在/etc/sudoers.d/目录下新建一个文件,例如:
[root@localhost sudoers.d]# pwd/etc/sudoers.d[root@localhost sudoers.d]# echo 'zhengtianbao ALL = (root) NOPASSWD: ALL' > stack_sh[root@localhost sudoers.d]# cat stack_sh zhengtianbao ALL = (root) NOPASSWD: ALL |
这样当我们切换到’zhengtianbao’这个用户的时候,只要在想执行的命令前加’sudo’,不需要输入密码就能以root身份运行.
[root@localhost sudoers.d]# su zhengtianbao[zhengtianbao@localhost sudoers.d]$ lsls: cannot open directory .: Permission denied[zhengtianbao@localhost sudoers.d]$ sudo lsstack_sh |
关于sudoers的配置文件如何定义,这里简单介绍下:
通用格式:
user host run_as command
user:一位或几位用户,在/etc/group中可以用一个%代替它,组对象的名称一定要用百分号%开头.
host:一个或几个主机名.
run_as:作为哪个用户运行,常见选项是root和ALL.
command:想让用户或组运行的一个或几个根级别命令.
例如:
hans ALL=(root) useradd,userdel
授权hans用户在所有计算机上以root身份运行useradd,userdel命令.
%smith ALL=(ALL) NOPASSWD:useradd,userdel
授权smith组全部成员在所有计算机上以所有用户的身份运行useradd,userdel命令;且运行时不必输入密码.
一点点疑问:能否控制命令的参数呢?接下来做个测试:
[root@localhost sudoers.d]# echo 'zhengtianbao ALL = (root) NOPASSWD: /bin/ls -l, /bin/ls -a' > stack_sh[root@localhost sudoers.d]# su zhengtianbao[zhengtianbao@localhost sudoers.d]$ ls -als: cannot open directory .: Permission denied[zhengtianbao@localhost sudoers.d]$ sudo ls -a. .. stack_sh[zhengtianbao@localhost sudoers.d]$ sudo ls -ltotal 8-rw-r--r-- 1 root root 59 Jan 26 14:43 stack_sh[zhengtianbao@localhost sudoers.d]$ sudo ls -a -l[sudo] password for zhengtianbao: |
可见能够控制的命令参数还是很严格的.
放在openstack中这也是可行的,但是随着项目的增大,单纯的修改sudoers影响了openstack的可维护性,因此引入了root warpper来管理命令权限相关的内容.
二.nova-rootwrap工作原理
如果是根据devstack来安装openstack的话,查看devstack中的stack.sh里面有关于root权限的内容:
# root Access# -----------# OpenStack is designed to be run as a non-root user; Horizon will fail to run# as **root** since Apache will not serve content from **root** user).# ``stack.sh`` must not be run as **root**. It aborts and suggests one course of# action to create a suitable user account.if [[ $EUID -eq 0 ]]; then echo "You are running this script as root." echo "Cut it out." echo "Really." echo "If you need an account to run DevStack, do this (as root, heh) to create $STACK_USER:" echo "$TOP_DIR/tools/create-stack-user.sh" exit 1fi# We're not **root**, make sure ``sudo`` is availableis_package_installed sudo || install_package sudo |
好,它这里表示需要先通过脚本tools/create-stack-user.sh来创建一个用户,再通过那个用户来执行,看脚本内容:
# Needed to get ``ENABLED_SERVICES``source $TOP_DIR/stackrc# Give the non-root user the ability to run as **root** via ``sudo``is_package_installed sudo || install_package sudo if ! getent group $STACK_USER >/dev/null; then echo "Creating a group called $STACK_USER" groupadd $STACK_USER fi if ! getent passwd $STACK_USER >/dev/null; then echo "Creating a user called $STACK_USER" useradd -g $STACK_USER -s /bin/bash -d $DEST -m $STACK_USERfiecho "Giving stack user passwordless sudo privileges"# UEC images ``/etc/sudoers`` does not have a ``#includedir``, add onegrep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || echo "#includedir /etc/sudoers.d" >> /etc/sudoers( umask 226 && echo "$STACK_USER ALL=(ALL) NOPASSWD:ALL" \ > /etc/sudoers.d/50_stack_sh ) |
$STACK_USER的值在stackrc文件中定义,当前环境是root身份时则为’stack’:
# Determine stack userif [[ $EUID -eq 0 ]]; then STACK_USER=stackelse STACK_USER=$(whoami)fi |
ok,这里发现它在/etc/sudoers.d/目录下生成了一个50_stack_sh的文件,里面的内容是:
stack ALL=(ALL) NOPASSWD:ALL
显然它创建的stack用户现在可以在使用`sudo`执行任何命令都能省略输入密码的过程了.
接下来继续看nova的安装过程,在devstack/lib/目录下的nova脚本中有configure_nova()的方法,它会在stack.sh中被调用到,正如名字所示,它用来设置nova的config文件,创建一些数据等工作:
# configure_nova() - Set config files, create data dirs, etcfunction configure_nova() { # Put config files in ``/etc/nova`` for everyone to find if [[ ! -d $NOVA_CONF_DIR ]]; then sudo mkdir -p $NOVA_CONF_DIR fi sudo chown $STACK_USER $NOVA_CONF_DIR cp -p $NOVA_DIR/etc/nova/policy.json $NOVA_CONF_DIR configure_nova_rootwrap ... |
注意里面的configure_nova_rootwrap,查看该方法:
# configure_nova_rootwrap() - configure Nova's rootwrapfunction configure_nova_rootwrap() { # Deploy new rootwrap filters files (owned by root). # Wipe any existing rootwrap.d files first if [[ -d $NOVA_CONF_DIR/rootwrap.d ]]; then sudo rm -rf $NOVA_CONF_DIR/rootwrap.d fi # Deploy filters to /etc/nova/rootwrap.d sudo mkdir -m 755 $NOVA_CONF_DIR/rootwrap.d sudo cp $NOVA_DIR/etc/nova/rootwrap.d/*.filters $NOVA_CONF_DIR/rootwrap.d sudo chown -R root:root $NOVA_CONF_DIR/rootwrap.d sudo chmod 644 $NOVA_CONF_DIR/rootwrap.d/* # Set up rootwrap.conf, pointing to /etc/nova/rootwrap.d sudo cp $NOVA_DIR/etc/nova/rootwrap.conf $NOVA_CONF_DIR/ sudo sed -e "s:^filters_path=.*$:filters_path=$NOVA_CONF_DIR/rootwrap.d:" -i $NOVA_CONF_DIR/rootwrap.conf sudo chown root:root $NOVA_CONF_DIR/rootwrap.conf sudo chmod 0644 $NOVA_CONF_DIR/rootwrap.conf # Specify rootwrap.conf as first parameter to nova-rootwrap ROOTWRAP_SUDOER_CMD="$NOVA_ROOTWRAP $NOVA_CONF_DIR/rootwrap.conf *" # Set up the rootwrap sudoers for nova TEMPFILE=`mktemp` echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD" >$TEMPFILE chmod 0440 $TEMPFILE sudo chown root:root $TEMPFILE sudo mv $TEMPFILE /etc/sudoers.d/nova-rootwrap} |
显然,它在/etc/sudoers.d/目录下创建了nova-rootwrap的文件,里面的内容可能是:
nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap /etc/nova/rootwrap.conf *
nova:指用户名.
ALL:指主机名.
root:指运行用户名.
NOPASSWD:指运行下面命令时不需要输入密码.
/usr/bin/nova-rootwrap /etc/nova/rootwrap.conf *:指能够运行的命令.
上面的文件定义就是说:
以nova身份运行命令`sudo /usr/bin/nova-rootwrap /etc/nova/rootwrap.conf * `
时是不需要输入密码的,其中的’*’指的是任意字符串,例如:`ip route show …`.
/usr/bin/nova-rootwrap是一个可执行的脚本文件,/etc/nova/rootwrap.conf则是rootwrap相关的配置,里面定义了filters-path所在路径,以及缺省的可执行命令所在路径,具体的过滤逻辑如下:
1)获取要执行的命令,如:ip
2)通过filters-path加载配置文件中定义的可以执行的命令列表
3)判断命令是否在可执行命令列表中
4)若在则通过python的subprocess模块执行Popen方法;不在则给出错误信息,退出.
这些都可以在nova的bin/nova-rootwrap文件中查看.
三.nova中执行外部命令过程分析
所有的nova代码在执行外部命令的时候都会用到execute函数,这个函数定义在nova顶层目录下的utils.py模块下.
例如:
from nova import utils
utils.execute(‘chmod’, ’777′, tmpdir, run_as_root=True)
execute函数首先根据run_as_root参数进行了一些处理,如下所示:
def _get_root_helper(): return 'sudo nova-rootwrap %s' % CONF.rootwrap_configdef execute(*cmd, **kwargs): """Convenience wrapper around oslo's execute() method.""" if 'run_as_root' in kwargs and not 'root_helper' in kwargs: kwargs['root_helper'] = _get_root_helper() return processutils.execute(*cmd, **kwargs) |
然后丢给processutils中的execute,查看代码:
def execute(*cmd, **kwargs): ... if run_as_root and hasattr(os, 'geteuid') and os.geteuid() != 0: if not root_helper: raise NoRootWrapSpecified( message=_('Command requested root, but did not ' 'specify a root helper.')) cmd = shlex.split(root_helper) + list(cmd) cmd = map(str, cmd) while attempts > 0: ... obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE, close_fds=close_fds, preexec_fn=preexec_fn, shell=shell) ... |
最终执行的命令cmd就是`sudo /usr/bin/nova-rootwrap /etc/nova/rootwrap.conf chmod 777 tmpdir`
这里`chmod`这个命令在rootwrap.d目录下的filters文件中可以找到对应的配置:
chmod: CommandFilter, chmod, root
CommandFilter的定义是在oslo的rootwrap/filters.py中,里面还定义了其他的filter(RegExp,Path,Kill,ReadFile,Ip,Env,Chaining,IpNetnsExec).
更加详细的内容请查看nova/rootwarp目录下的filters.py与wrapper.py.
本文转自http://zhengtianbao.com/?p=224
nova分析(10)—— nova-rootwrap的更多相关文章
- 高可用OpenStack(Queen版)集群-10.Nova计算节点
参考文档: Install-guide:https://docs.openstack.org/install-guide/ OpenStack High Availability Guide:http ...
- 在Openstack H版部署Nova Cell 时 ,终端输入nova service-list 和 nova host-list 命令将报错
关于Cell的基本介绍,可以参考贤哥的一篇文章: [OpenStack]G版中关于Nova的Cell http://blog.csdn.net/lynn_kong/article/details/8 ...
- KVM 介绍(8):使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机 [Nova Libvirt QEMU/KVM Live Migration]
学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...
- Solr4.8.0源码分析(10)之Lucene的索引文件(3)
Solr4.8.0源码分析(10)之Lucene的索引文件(3) 1. .si文件 .si文件存储了段的元数据,主要涉及SegmentInfoFormat.java和Segmentinfo.java这 ...
- openstack私有云布署实践【11.3 计算nova - compute节点-nova用户免密登录(用于云主机冷迁移+扩展云主机大小)】
云主机迁移+扩展云主机大小 ,官方说它依赖nova用户之间的免密登录.确保每个resion区域的compute节点服务器他们可以相互SSH免密 compute1-7 他们相互SSH免密 k ...
- RTMPdump(libRTMP) 源代码分析 10: 处理各种消息(Message)
===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...
- nova分析(7)—— nova-scheduler
Nova-Scheduler主要完成虚拟机实例的调度分配任务,创建虚拟机时,虚拟机该调度到哪台物理机上,迁移时若没有指定主机,也需要经过scheduler.资源调度是云平台中的一个很关键问题,如何做到 ...
- nova分析(6)—— nova service启动过程
Nova project下面具有多个service,api,compute,sceduler等等,他们的启动过程都几乎类似,这一篇博客就详细记录nova-sceduler的启动过程.文章中贴出的源码都 ...
- nova分析(5)—— nova-conductor
nova-conductor是nova-compute之上的一个服务,这个服务比较简单,主要封装了DB访问和动态迁移相关的代码.转来一篇文章看看它是如何工作的. 更新记录:1. 2013.4.19 ...
随机推荐
- 转linux
随着上班的深入,愈来愈感觉到转linux的必要性,最近做实验室的网页,在windows下是好的, 没想到,传到liunx服务器上,居然出了问题,很是郁闷,平时还是用liunx用的少了. 以后操作系统要 ...
- 使用jetty-maven-plugin插件进行测试
为了能够使用maven的jetty插件对项目进行测试,需要进行如下操作: (1)修改maven配置文件 为了能够在命令行中使用jetty命令,需要修改maven的配置文件settings.xml文件, ...
- nginx+tomcat集群配置(1)---根目录设定和多后端分发配置
前言: 对于javaer而言, nginx+tomcat集群配置, 已然成了web应用部署的主流. 大公司如此, 小公司亦然. 对于个人开发者而言, 资源有限, 往往多个web应用混部于一台服务器(云 ...
- 203. Remove Linked List Elements
Remove all elements from a linked list of integers that have value val. ExampleGiven: 1 --> 2 --& ...
- ZOJ 1016 Parencodings
原题链接 题目大意:有两串数字P和W.数组P中,数字P[i]表示第i个右括号之前的左括号个数.数组W中,数字W[i]表示在第i个右括号和与它匹配的左括号之间的右括号的个数(包括本身).给出一个数组P, ...
- android:clipToPadding 和 android:clipChildren 解决ListView设置padding后 padding不跟随改动
clipToPadding就是说控件的绘制区域是否在padding里面的,true的情况下如果你设置了padding那么绘制的区域就往里 缩, clipChildren是指子控件是否超过padding ...
- ehcache 缓存
一:详细配置步骤 1,添加ehcache.xml文件 将ehcache.xml文件添加到src路径下面.ehcache.xml文件内容如下 <ehcache> <diskStore ...
- hdu3033 I love sneakers! 分组背包变形
分组背包要求每一组里面只能选一个,这个题目要求每一组里面至少选一个物品. dp[i, j] 表示前 i 组里面在每组至少放进一个物品的情况下,当花费 j 的时候,所得到的的最大价值.这个状态可以由三个 ...
- UVa 442 矩阵链乘(栈)
Input Specification Input consists of two parts: a list of matrices and a list of expressions. The f ...
- Faster RCNN 运行自己的数据,刚开始正常,后来就报错: Index exceeds matrix dimensions. Error in ori_demo (line 114) boxes_cell{i} = [boxes(:, (1+(i-1)*4):(i*4)), scores(:, i)];
function script_faster_rcnn_demo() close all; clc; clear mex; clear is_valid_handle; % to clear init ...