openstack policy 鉴权过程分析
来源:互联网 发布:八爪鱼软件 编辑:程序博客网 时间:2024/06/05 17:38
1. openstack 鉴权简单介绍
众所周知,openstack通过keystone用来完成authenticate(认证),真正的鉴权(authorize)是在各个模块分别做的,具体实现为每个模块都有一个policy文件,叫policy.json,里面定义了鉴权用的rules。
以nova为例,policy文件的位置在:/etc/nova/policy.json,下面先来看几条rules,了解其基本含义:
语法规则为:rule:[result]
rule:指这条规则是干啥的,通常对应一个action,以类似scope:action的形式给出,scope表示作用范围,action表示执行哪种操作
result: 表示这条rule的判定结果或者如何进行判定,比如"compute:create:forced_host":"is_admin:True",如果执行此操作的用户具有admin角色(role),则这条结果的判定结果就是True。
另外,rule是可以嵌套的,比如"compute:stop":"rule:admin_or_owner",表示compute:stop这条规则的结果为admin_or_owner这条规则的结果,而admin_or_owner规则如下:
如果调用这个操作的用户的角色是admin,就返回True,或者返回用户所属的project的id.
2. policy鉴权代码分析
针对每一个操作,都会经过一个叫@wrap_check_policy的decorator,以nova的resize操作为例,在执行真正的resize代码之前,先要经过一个叫@wrap_check_policy的装饰器来完成policy的check过程,具体参见后面的代码check_policy函数:
check_policy(context, action, target, scope='compute')函数有四个参数:
(1) context: 执行resize操作的上下文,其内容包括project_id, user_id, role,auth_token等信息,具体如下:
(2) action:表示当前执行的操作是啥,这里就是resize
(3) target:操作针对的object是啥,这里就是instance id
(4) scope:当前操作的作用域是啥,主要为了与policy文件中定义的作用域匹配,这里为compute,即nova执行的操作
3. 总结
之前一直以为修改了policy.json文件,需要重启service才能重新加载policy.json生效,通过分析代码,证明policy.json是动态更新的。另外,通过分析代码,也搞清楚了如何添加自定义的rule,以便实现更细粒度的rule,稍后会给出一个自己实现的例子。
众所周知,openstack通过keystone用来完成authenticate(认证),真正的鉴权(authorize)是在各个模块分别做的,具体实现为每个模块都有一个policy文件,叫policy.json,里面定义了鉴权用的rules。
以nova为例,policy文件的位置在:/etc/nova/policy.json,下面先来看几条rules,了解其基本含义:
- "compute:create":"",
- "compute:create:attach_network":"",
- "compute:create:attach_volume":"",
- "compute:create:forced_host":"is_admin:True",
- "compute:get_all":"",
- "compute:get_all_tenants":"",
- "compute:start":"rule:admin_or_owner",
- "compute:stop":"rule:admin_or_owner",
- "compute:unlock_override":"rule:admin_api",
rule:指这条规则是干啥的,通常对应一个action,以类似scope:action的形式给出,scope表示作用范围,action表示执行哪种操作
result: 表示这条rule的判定结果或者如何进行判定,比如"compute:create:forced_host":"is_admin:True",如果执行此操作的用户具有admin角色(role),则这条结果的判定结果就是True。
另外,rule是可以嵌套的,比如"compute:stop":"rule:admin_or_owner",表示compute:stop这条规则的结果为admin_or_owner这条规则的结果,而admin_or_owner规则如下:
- "admin_or_owner":"is_admin:True or project_id:%(project_id)s",
2. policy鉴权代码分析
针对每一个操作,都会经过一个叫@wrap_check_policy的decorator,以nova的resize操作为例,在执行真正的resize代码之前,先要经过一个叫@wrap_check_policy的装饰器来完成policy的check过程,具体参见后面的代码check_policy函数:
- @wrap_check_policy
- @check_instance_lock
- @check_instance_cell
- @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED],
- task_state=[None])
- def resize(self, context, instance, flavor_id=None,
- **extra_instance_updates):
(1) context: 执行resize操作的上下文,其内容包括project_id, user_id, role,auth_token等信息,具体如下:
- {'project_name': u'demo','user_id': u'a51e07e52af24111973dd7e11ece97f3','roles':[u'admin'],'timestamp':'2014-03-10T08:45:56.552624','auth_token':'851012cfd5ad220e02cc3bc61b31c5f5','remote_address':'10.2.45.133','quota_class': None,'is_admin': True,'tenant': u'999c9fb0d7684ce1913cac4cc6122e51','service_catalog':[{u'endpoints':[{u'adminURL': u'http://10.2.45.133:8776/v1/999c9fb0d7684ce1913cac4cc6122e51', u'region': u'RegionOne', u'id': u'0987e932f0a0408ca7a5a31200c8ac51', u'internalURL': u'http://10.2.45.133:8776/v1/999c9fb0d7684ce1913cac4cc6122e51', u'publicURL': u'http://10.2.45.133:8776/v1/999c9fb0d7684ce1913cac4cc6122e51'}], u'endpoints_links':[], u'type': u'volume', u'name': u'cinder'}],'request_id':'req-292b93ac-0a2b-488e-8a51-ea734286b07c','instance_lock_checked': False,'project_id': u'999c9fb0d7684ce1913cac4cc6122e51','user_name': u'admin','read_deleted':'no','user': u'a51e07e52af24111973dd7e11ece97f3'}
(3) target:操作针对的object是啥,这里就是instance id
(4) scope:当前操作的作用域是啥,主要为了与policy文件中定义的作用域匹配,这里为compute,即nova执行的操作
- def check_policy(context, action, target, scope='compute'):
- _action = '%s:%s' % (scope, action) ##这里拼接成policy.json的rule,即_action=compute:resize
- nova.policy.enforce(context, _action, target)
- ------------------------------------------------------------------------------------------------------------------------
- def enforce(context, action, target, do_raise=True):
- """Verifies that the action is valid on the target in this context.
- :param context: nova context
- :param action: string representing the action to be checked
- this should be colon separated for clarity.
- i.e. ``compute:create_instance``,
- ``compute:attach_volume``,
- ``volume:attach_volume``
- :param target: dictionary representing the object of the action
- for object creation this should be a dictionary representing the
- location of the object e.g. ``{'project_id': context.project_id}``
- :param do_raise: if True (the default), raises PolicyNotAuthorized;
- if False, returns False
- :raises nova.exception.PolicyNotAuthorized: if verification fails
- and do_raise is True.
- :return: returns a non-False value (not necessarily "True") if
- authorized, and the exact value False if not authorized and
- do_raise is False.
- """
- init() ##policy.json被cache到cache_info数据结构中,init()函数就是去检查policy.json是否已经被加载或修改过,如果cache_info结构为空,说明policy.json还没有加载过,则执行加载;如果policy.json被修改过,也会重新进行加载
- credentials = context.to_dict() ##将context转化成dictonary,就是上面context给出的内容,以便后面代码使用
- # Add the exception arguments if asked to do a raise
- extra = {}
- if do_raise:
- extra.update(exc=exception.PolicyNotAuthorized, action=action) ##增加no auth hook函数,即如果rule的结果为False,则执行no auth hook函数做一些处理
- return policy.check(action, target, credentials,**extra) ##进行policy的check
- --------------------------------------------------------------------------------------------------------------------
- def init():
- global _POLICY_PATH
- global _POLICY_CACHE
- if not _POLICY_PATH:
- _POLICY_PATH = CONF.policy_file
- if not os.path.exists(_POLICY_PATH):
- _POLICY_PATH = CONF.find_file(_POLICY_PATH)
- if not _POLICY_PATH:
- raise exception.ConfigNotFound(path=CONF.policy_file)
- utils.read_cached_file(_POLICY_PATH, _POLICY_CACHE,
- reload_func=_set_rules) ##加载policy.json文件
- ----------------------------------------------------------------------------------------------------------------------
- def read_cached_file(filename, cache_info, reload_func=None):
- """Read from a file if it has been modified.
- :param cache_info: dictionary to hold opaque cache.
- :param reload_func: optional function to be called with data when
- file is reloaded due to a modification.
- :returns: data from file
- """
- mtime = os.path.getmtime(filename) ###获取policy.json文件的modify time,如果与cache_info中的mtime不同,则说明文件被修改过,则执行重新加载
- if not cache_info or mtime != cache_info.get('mtime'):
- LOG.debug(_("Reloading cached file %s")% filename)
- with open(filename) as fap:
- cache_info['data']= fap.read()
- cache_info['mtime']= mtime
- if reload_func:
- reload_func(cache_info['data'])
- return cache_info['data'] ###返回加载后的policy.json文件的内容
- ---------------------------------------------------------------------------------------------------------------------------
- def check(rule, target, creds, exc=None,*args,**kwargs):
- """
- Checks authorization of a rule against the target and credentials.
- :param rule: The rule to evaluate.
- :param target: As much information about the object being operated
- on as possible, as a dictionary.
- :param creds: As much information about the user performing the
- action as possible, as a dictionary.
- :param exc: Class of the exception to raise if the check fails.
- Any remaining arguments passed to check() (both
- positional and keyword arguments) will be passed to
- the exception class. If exc is not provided, returns
- False.
- :return: Returns False if the policy does not allow the action and
- exc is not provided; otherwise, returns a value that
- evaluates to True. Note: for rules using the "case"
- expression, this True value will be the specified string
- from the expression.
- """
- # Allow the rule to be a Check tree
- if isinstance(rule, BaseCheck):
- result = rule(target, creds)
- elif not _rules:
- # No rules to reference means we're going to fail closed
- result = False
- else:
- try:
- # Evaluate the rule
- result = _rules[rule](target, creds) ##没一条rule执行一个函数,这个对应关系记录在全局变量_rules
- except KeyError:
- # If the rule doesn't exist, fail closed
- result = False
- # If it is False, raise the exception if requested
- if exc and result is False:
- raise exc(*args,**kwargs)
- return result
之前一直以为修改了policy.json文件,需要重启service才能重新加载policy.json生效,通过分析代码,证明policy.json是动态更新的。另外,通过分析代码,也搞清楚了如何添加自定义的rule,以便实现更细粒度的rule,稍后会给出一个自己实现的例子。
0 0
- openstack policy 鉴权过程分析
- openstack policy 鉴权过程分析
- openstack policy 鉴权过程分析
- 【openstack】Nova中的policy
- 谈谈OpenStack的鉴权过程
- Audio Policy 分析
- Audio Policy 分析
- Audio Policy分析
- Audio Policy 分析
- openstack nova 基础知识——policy
- openstack nova 基础知识——policy
- openstack nova 基础知识——policy
- openstack nova 基础知识——policy
- Openstack修改policy.json后出现问题解决
- Openstack horizon 通过policy进行定制化
- openstack nova 基础知识——policy【转载】
- OpenStack建立实例完整过程源码详细分析(1)
- OpenStack建立实例完整过程源码详细分析(2)
- js 获取Gridview textbox 值的问题
- Android权限大全
- 低内存管理lower memory killer
- 关于android SDK更新报错Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-1.xml
- yii crontab 命令使用 经测试
- openstack policy 鉴权过程分析
- 日语学习之沪江N4基础 20141204 -2
- windows bat 批处理脚本基本用法
- 设置 Apache 文件根目录 和 设置Apache 虚拟目录(Virtual Directory)
- class.forname().newInstance()
- MFC俄罗斯方块
- JUnit 测试spring项目
- C++设计模式3————(策略模式)
- vim配置及插件安装管理(超级详细)