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]$ ls ls: cannot open directory .: Permission denied [zhengtianbao@localhost sudoers.d]$ sudo ls stack_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 -a ls: cannot open directory .: Permission denied [zhengtianbao@localhost sudoers.d]$ sudo ls -a . .. stack_sh [zhengtianbao@localhost sudoers.d]$ sudo ls -l total 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 1 fi # We're not **root**, make sure ``sudo`` is available is_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_USER fi echo "Giving stack user passwordless sudo privileges" # UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one grep -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 user if [[ $EUID - eq 0 ]]; then STACK_USER=stack else 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, etc function 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 rootwrap function 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_config def 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 ...
随机推荐
- 【题解】【区间】【二分查找】【Leetcode】Insert Interval & Merge Intervals
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...
- js基础知识(pomelo阅读)
0,node.js调试: http://www.noanylove.com/2011/12/node-the-inspector-debugging-node-js/ 1,读取配置文件: var ...
- (实用篇)PHP ftp上传文件操作类
<?php /** * 作用:FTP操作类( 拷贝.移动.删除文件/创建目录 ) */ class class_ftp { public $off; // 返回操作状态(成功/失败) publi ...
- hdu 1542 Atlantis
求矩形的面积之和. 线段树+离散话+扫描线 #include<iostream> #include<cstdio> #include<cstdlib> #inclu ...
- 98. Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- Codeforces Round #260 (Div. 2) A B C 水 找规律(大数对小数取模) dp
A. Laptops time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- ES6 — 字符串String
ES6对字符串新增了一些函数和操作规范.下面我们来看ES6中对字符串新加的特性. 1.模版字符串 (即用反引号定义的字符串) 传统的字符串拼接通过我们使用'+'号与变量连接.例如: let name= ...
- Spring事务配置的五种方式 -- 越往后需要Spring版本越高
第五种 基本零配置 个人感觉第四种也可以 Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式, ...
- JAVA 23种设计模式(转)
1.FACTORY?追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了.麦当劳和肯德基就是生产鸡翅 ...
- PHP 将json的stdClass Object转成数组array
PHP和JS通讯通常都用json,但是PHP要用json的数据,通过json_decode转出来的数组并不是标准的array,所以需要用这个函数进行转换. function object_array( ...