openstack policy 鉴权过程分析

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情
1. openstack 鉴权简单介绍   
    众所周知,openstack通过keystone用来完成authenticate(认证),真正的鉴权(authorize)是在各个模块分别做的,具体实现为每个模块都有一个policy文件,叫policy.json,里面定义了鉴权用的rules。
    以nova为例,policy文件的位置在:/etc/nova/policy.json,下面先来看几条rules,了解其基本含义:
  1. "compute:create": "",                                              
  2. "compute:create:attach_network": "",
  3. "compute:create:attach_volume": "",
  4. "compute:create:forced_host": "is_admin:True",
  5. "compute:get_all": "",
  6. "compute:get_all_tenants": "",
  7. "compute:start": "rule:admin_or_owner",
  8. "compute:stop": "rule:admin_or_owner",
  9. "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规则如下:
  1. "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函数:
  1.     @wrap_check_policy
  2.     @check_instance_lock
  3.     @check_instance_cell
  4.     @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED],
  5.                           task_state=[None])
  6.     def resize(self, context, instance, flavor_id=None,
  7.                **extra_instance_updates):
check_policy(context, action, target, scope='compute')函数有四个参数:
(1) context: 执行resize操作的上下文,其内容包括project_id, user_id, role,auth_token等信息,具体如下:
  1. {'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执行的操作

  1. def check_policy(context, action, target, scope='compute'):
  2.         _action = '%s:%s' % (scope, action)  ##这里拼接成policy.json的rule,即_action=compute:resize
  3.         nova.policy.enforce(context, _action, target
  4. ------------------------------------------------------------------------------------------------------------------------
  5.     def enforce(context, action, target, do_raise=True):
  6.         """Verifies that the action is valid on the target in this context.

  7.            :param context: nova context
  8.            :param action: string representing the action to be checked
  9.                this should be colon separated for clarity.
  10.                i.e. ``compute:create_instance``,
  11.                ``compute:attach_volume``,
  12.                ``volume:attach_volume``
  13.            :param target: dictionary representing the object of the action
  14.                for object creation this should be a dictionary representing the
  15.                location of the object e.g. ``{'project_id': context.project_id}``
  16.            :param do_raise: if True (the default), raises PolicyNotAuthorized;
  17.                if False, returns False

  18.            :raises nova.exception.PolicyNotAuthorized: if verification fails
  19.                and do_raise is True.

  20.            :return: returns a non-False value (not necessarily "True") if
  21.                authorized, and the exact value False if not authorized and
  22.                do_raise is False.
  23.         """
  24.         init()   ##policy.json被cache到cache_info数据结构中,init()函数就是去检查policy.json是否已经被加载或修改过,如果cache_info结构为空,说明policy.json还没有加载过,则执行加载;如果policy.json被修改过,也会重新进行加载

  25.         credentials = context.to_dict()  ##将context转化成dictonary,就是上面context给出的内容,以便后面代码使用

  26.         # Add the exception arguments if asked to do a raise
  27.         extra = {}
  28.         if do_raise:
  29.             extra.update(exc=exception.PolicyNotAuthorized, action=action)  ##增加no auth hook函数,即如果rule的结果为False,则执行no auth hook函数做一些处理

  30.         return policy.check(action, target, credentials, **extra)  ##进行policy的check
  31. --------------------------------------------------------------------------------------------------------------------
  32. def init():
  33.     global _POLICY_PATH
  34.     global _POLICY_CACHE
  35.     if not _POLICY_PATH:
  36.         _POLICY_PATH = CONF.policy_file
  37.         if not os.path.exists(_POLICY_PATH):
  38.             _POLICY_PATH = CONF.find_file(_POLICY_PATH)
  39.         if not _POLICY_PATH:
  40.             raise exception.ConfigNotFound(path=CONF.policy_file)
  41.     utils.read_cached_file(_POLICY_PATH, _POLICY_CACHE,
  42.                            reload_func=_set_rules) ##加载policy.json文件
  43. ----------------------------------------------------------------------------------------------------------------------

  44. def read_cached_file(filename, cache_info, reload_func=None):
  45.     """Read from a file if it has been modified.

  46.     :param cache_info: dictionary to hold opaque cache.
  47.     :param reload_func: optional function to be called with data when
  48.                         file is reloaded due to a modification.

  49.     :returns: data from file

  50.     """
  51.     mtime = os.path.getmtime(filename)  ###获取policy.json文件的modify time,如果与cache_info中的mtime不同,则说明文件被修改过,则执行重新加载
  52.     if not cache_info or mtime != cache_info.get('mtime'):
  53.         LOG.debug(_("Reloading cached file %s") % filename)
  54.         with open(filename) as fap:
  55.             cache_info['data'] = fap.read()
  56.         cache_info['mtime'] = mtime
  57.         if reload_func:
  58.             reload_func(cache_info['data'])
  59.     return cache_info['data']            ###返回加载后的policy.json文件的内容
  60. ---------------------------------------------------------------------------------------------------------------------------
  61. def check(rule, target, creds, exc=None, *args, **kwargs):
  62.     """
  63.     Checks authorization of a rule against the target and credentials.

  64.     :param rule: The rule to evaluate.
  65.     :param target: As much information about the object being operated
  66.                    on as possible, as a dictionary.
  67.     :param creds: As much information about the user performing the
  68.                   action as possible, as a dictionary.
  69.     :param exc: Class of the exception to raise if the check fails.
  70.                 Any remaining arguments passed to check() (both
  71.                 positional and keyword arguments) will be passed to
  72.                 the exception class. If exc is not provided, returns
  73.                 False.

  74.     :return: Returns False if the policy does not allow the action and
  75.              exc is not provided; otherwise, returns a value that
  76.              evaluates to True. Note: for rules using the "case"
  77.              expression, this True value will be the specified string
  78.              from the expression.
  79.     """

  80.     # Allow the rule to be a Check tree
  81.     if isinstance(rule, BaseCheck):
  82.         result = rule(target, creds)
  83.     elif not _rules:
  84.         # No rules to reference means we're going to fail closed
  85.         result = False
  86.     else:
  87.         try:
  88.             # Evaluate the rule
  89.             result = _rules[rule](target, creds)  ##没一条rule执行一个函数,这个对应关系记录在全局变量_rules
  90.         except KeyError:
  91.             # If the rule doesn't exist, fail closed
  92.             result = False

  93.     # If it is False, raise the exception if requested
  94.     if exc and result is False:
  95.         raise exc(*args, **kwargs)

  96.     return result
3. 总结 
    之前一直以为修改了policy.json文件,需要重启service才能重新加载policy.json生效,通过分析代码,证明policy.json是动态更新的。另外,通过分析代码,也搞清楚了如何添加自定义的rule,以便实现更细粒度的rule,稍后会给出一个自己实现的例子。
别再只导TOP/BOTTOM了!Allegro Gerber导出详解:阻焊、钢网、丝印层到底该怎么设置才不出错? 本文详细解析了Allegro Gerber导出中阻焊、钢网和丝印层的专业配置方法,帮助工程师避免常见错误。通过实例说明各层的工业意义和Allegro中的精准设置,确保PCB设计到制造的顺利过渡,提升生产效率和产品质量。 阅读详情

相关推荐

openstack】Nova中的policy

Nova中的policy 本博客欢迎转发,但请保留原作者信息!内容系本人学习、研究和总结,如有雷同,实属荣幸! 任何对外暴露接口的系统,都必须有分分域以及认证的功能。在openstack中,keystone组件用来对用户进行认证,说白了就是看用户是否是系统的合法用户,而policy机制则主要看用户的操作是否满足特定的条件,比如一些接口是特接口(仅限管理员使用),普通用户不允许调

代码改变世界 1913

openstack-dashboard启动超时

由于环境问题,我们在搭建完dashboard后重启httpd服务,会发生httpd超时的问题,在这里我为大家做个解答。 首先,关于这个问题的原因是由于启动httpd服务的时候他会首先执行以下两个命令: /usr/bin/python /usr/share/openstack-dashboard/manage.py collectstatic --noinput --clear -...

qq_41898592的博客 1738

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

为了能够自定义制定限管理,

yzg2010a的专栏 2276

openstack的 oslo_policy限验证简单分析

openstack中,限校验的是通过oslo_policy的进行限的校验,本文主要基于 newton版本的olso_policy进行简单的说明。 policy配置文件内容 { "context_is_admin": "role:admin", "admin_or_owner": "is_admin:True or project_id:%(project_id)s",

linyonghui1213的专栏 1856

Openstack登录时验证错误

由于没有正常关闭Openstack机器,导致出现了验证错误,查看错误日志发现: openstack_auth.backend Authorization Failed: An unexpected error prevented the server from fulfilling your request. (OperationalError) (2003, "Can't connect

changzhi的专栏 1万+

openstack 简单介绍

1. openstack 简单介绍        众所周知,openstack通过keystone用来完成authenticate(认证),真正的(authorize)是在各个模块分别做的,具体实现为每个模块都有一个policy文件,叫policy.json,里面定义了用的rules。     以nova为例,policy文件的位置在:/etc/nova/policy.json,下

sksmyy6的专栏 1030

openstack policy机制

一、什么是policy policy策略,是OpenStack用来约束不同等级用户的操作限,用于自定义限管理的一种机制。 二、为什么要用policy 1、基于keystone理解policy Keystone中有User(用户)、Project(租户)、role(角色)三个概念,使用基本流程为: 1)创建租户 2)创建用户 3)创建角色 4)给用户和租户赋予角色 赋予角色之后,角色还只是一个空的概念定义,没有实际意义。真正限制用户角色执行具体action操作的,是policy.json.

wuyongpeng的专栏 2766

openstack-policy

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33863087的博客 282

OpenStack公共组件oslo之十二——oslo.policy

        众所周知,OpenStack使用基于角色的限访问控制(RBAC),在RBAC中,限与角色相关联,用户通过成为适当角色的成员而得到这些角色的限。这就极大地简化了限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。角色可依新的需求和系统的合并而赋予新的限,而限也可根据需要而从某角色中...

上善若水的木偶戏 4126

openstack nova 基础知识——policy【转载】

深度好文,值得一看,原文链接如下: http://blog.csdn.net/hackerain/article/details/8241691 1. 首先还是先来了解一下什么是policy,它是用来做什么的 在openstack的用户管理中,有三个概念:Users, Tenants, Roles。简单来说,policy就是用来控制某一个User在某个Tenant

mathsYouth的专栏 642

openstack nova 基础知识——policy

终于到了可以总结的时候了,policy本身的实现机制并不难,对我来说,难就难在python语法上,policy用到了很多高级的语法,逻辑性比较复杂,要理清其中的关系,还是要费一番功夫的。为此,还总结了另一篇blog,介绍了一下policy中用到的较为经典的语法。 1. 首先还是先来了解一下什么是policy,它是用来做什么的 在openstack的用户管理中,有三个概念:Users

成长的足迹 1万+

OpenStack Oslo.Policy 项目教程

OpenStack Oslo.Policy 项目教程 项目介绍 OpenStack Oslo.Policy 是一个用于在 OpenStack 服务中实施基于角色的访问控制(RBAC)策略的开源库。它提供了一个灵活的规则引擎,允许开发者定义和管理复杂的访问控制策略。Oslo.PolicyOpenStack 项目的一部分,旨在确保所有 OpenStack 服务之间的策略一致性和可维护性。 项目快...

gitblog_00386的博客 504

OpenStack之keystone

keystone的功能及认证流程

weixin_45039547的博客 1762

openstack 之 novnc流程分析

noVNC是一个支持HTML5的VNC客户端,主要作用就是与远端的vnc server进行互通,从而实现对于远端主机的控制。说白了,我们可以通过VNC客户端或者支持HTML5的浏览器访问远端安装了vnc server的服务器桌面从而进行控制。......

qq_40115163的博客 3116
上一篇: RedHat 7.0 beta release notes总结及个人分析
下一篇: OpenStack压力测试(批量创建200个instance)--结果非常失望
刘军卫
博客等级 码龄19年 1141粉丝 245原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值