关闭

openstack policy 鉴权过程分析

标签: openstack
707人阅读 评论(0) 收藏 举报
分类:
  1. openstack 鉴权简单介绍
    众所周知,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:[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_or_owner”: “is_admin:True or project_id:%(project_id)s”,
    如果调用这个操作的用户的角色是admin,就返回True,或者返回用户所属的project的id.

  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):
    check_policy(context, action, target, scope=’compute’)函数有四个参数:
    (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’}
    (2) action:表示当前执行的操作是啥,这里就是resize
    (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

3. 总结
之前一直以为修改了policy.json文件,需要重启service才能重新加载policy.json生效,通过分析代码,证明policy.json是动态更新的。另外,通过分析代码,也搞清楚了如何添加自定义的rule,以便实现更细粒度的rule,稍后会给出一个自己实现的例子。

0
0
查看评论

浅谈openstack中鉴权模块keystone

由于工作需要对于研究openstack中鉴权部分已有大半年,从G版本到现在的havana,期待着Icehouse,虽然期间也零零碎碎的接触过别的模块,但是始终keystone才是我的主场,下面废话也不多说,进入正题。     keystone中最容易让人迷惑的不是每个对象的概念...
  • cbaabc321123
  • cbaabc321123
  • 2014-11-07 21:57
  • 668

openstack policy 鉴权过程分析

1. openstack 鉴权简单介绍       众所周知,openstack通过keystone用来完成authenticate(认证),真正的鉴权(authorize)是在各个模块分别做的,具体实现为每个模块都有一个policy文件,叫poli...
  • ustc_dylan
  • ustc_dylan
  • 2014-03-13 09:54
  • 7180

ansible使用注意事项

1、默认情况下,首次登陆一台服务器,系统会提示是否要记住对端的指纹,用ansible也会这样,这样会导致需要手工输入yes或no,ansible 才可以往下执行。如需避免这种情况,需要在 /etc/ansible/ansible.cfg 文件中设置 host_key_checking = ...
  • lixingdefengzi
  • lixingdefengzi
  • 2016-03-24 10:34
  • 1398

在 CentOS 7 中安装并使用自动化工具 Ansible

Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具。它用Python写成,类似于Chef和Puppet,但是有一个不同和优点是我们不需要在节点中安装任何客户端。它使用SSH来和节点进行通信。 本篇中我们将在CentOS7上安装并配置Ansible,并且尝试管理两个节点。 Ans...
  • u019524703
  • u019524703
  • 2015-10-14 08:51
  • 333

ansible常见错误

1、秘钥和playbook中写的remoter_user不对应,即使外部指定了对应的用户也不可以。 [root@ansible src]# ansible-playbook -u"centos" --private-key=/home/rsa.key /home/fsp...
  • lixingdefengzi
  • lixingdefengzi
  • 2016-03-24 18:58
  • 8168

openstack nova 基础知识——policy

http://freedomhui.com/2012/11/openstack-nova-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86-policy/?lang=zh-hans 终于到了可以总结的时候了,policy本身的实现机制并不难,对我来说,难就难在pyt...
  • ztejiagn
  • ztejiagn
  • 2013-04-17 14:13
  • 495

OpenStack J版本 policy.json限制用户action权限

OpenStack J版本 policy.json限制用户action权限
  • zfqiannian
  • zfqiannian
  • 2015-10-21 16:47
  • 2086

Openstack horizon 通过policy进行定制化

Openstack的horzion组件目前只提供了部分的Openstack管理操作,有些功能只能通过命令行完成,命令行对于没有技术背景的客户来说是一种很糟糕的体验。同时,horzion中一些功能的默认权限可能并不完全符合某些客户的应用场景,所有经常有必要对horizon进行一些定制化的处理。 ...
  • allenson1
  • allenson1
  • 2014-12-04 20:01
  • 762

openstack学习指南

学习OpenStack时候,非常全面的学习指南,所以转载过来,和大家分享一下。 原文地址:http://way4ever.com/?p=349 0 阅读指南 希望本文能够解开你心中萦绕已久的心结,假如是死结,请移步到https://wiki.openstack.org/wiki/M...
  • bingxx11
  • bingxx11
  • 2014-02-12 10:14
  • 8353

Openstack修改policy.json后出现问题解决

为了能够自定义制定权限管理,
  • yzg2010a
  • yzg2010a
  • 2014-09-19 10:45
  • 1031
    个人资料
    • 访问:566407次
    • 积分:6796
    • 等级:
    • 排名:第4128名
    • 原创:140篇
    • 转载:220篇
    • 译文:6篇
    • 评论:26条
    文章分类
    最新评论