Neutron 授权策略实施

云计算 专栏收录该内容
40 篇文章 0 订阅

类似大多数的OpenStack projects,Neutron也使用oslo_policy。但是,由于Neutron喜欢与众不同,并使每个开发者的生活复杂化,它还通过以下方式“增强”了oslo_policy的能力:

  • 一个有自身API的封装模块:neutron.policy;
  • 对请求消息体中资源的属性添加细粒度检查的能力;
  • 使用策略引擎过滤响应中属性的能力;
  • 在oslo_policy中定义的规则之外添加一些自定义规则检查;

本文讨论有关策略实施的Neutron特定部分,特别是如何将实施逻辑连接到API处理中。有关其他信息,请参阅oslo_policy的开发人员文档。

授权工作流程

Neutron API控制器在处理API请求期间分两个阶段执行策略检查:

  • 请求授权。在向插件层分派POST, PUT, 和 DELETE请求之前,对于GET请求在由插件层返回之后;
  • 响应过滤。在构建返回给API消费者的响应时.

请求授权

此步骤的目的是授权处理请求或使用错误状态代码拒绝请求。
这一步使用neutron.policy.enforce函数。此函数在策略实施失败时引发oslo_policy.PolicyNotAuthorized。Neutron REST API控制器捕获此异常并返回:

  • 对于POST请求或者PUT请求的属于提交此请求的project拥有的对象的情况,返回403响应码;
  • 授权API操作失败(如 add_router_interface)时,返回403响应码;
  • DELETE, GET 和其它PUT请求失败时返回404响应码.

对于DELETE操作,必须首先获取资源。这是通过调用与处理GET请求所用的相同_item方法来完成的。对于PUT操作也是如此,因为Neutron API实现了PUTsPATCH语义。
评估的标准构建在_build_match_rule例程中。此例程接受以下参数作为输入:

  • 执行的动作,格式为 <operation>_<resource> , 例如:create_network

  • 用于执行检查的数据。对于POST操作,这可能是对象的部分规范,而对于GET, PUT, 和 DELETE请求,它始终是完整的规范,因为在将调用分派到插件层之前会检索资源数据。

  • 在上一个参数中指定的资源的集合名称;例如,对于网络,它将是"networks"。

函数_build_match_rule返回一个按照以下方式构建的oslo_policy.RuleCheck实例:

  • 总是为执行的动作添加检查。这将匹配policy.json中的create_network类似的策略。

  • 返回GET操作;不管怎样在构建响应时执行更详细的检查;

  • 对于每个在请求中明确指定的属性,创建一个匹配策略名称的规则,形式为:<operation>_<resource>:<attribute>,并且将它同前一个的规则进行与(‘And’)连接(使用 oslo_policy.AndCheck); 只有在资源的属性描述符的enforce_policy标志设置为True时(通常位于数据结构`RESOURCE_ATTRIBUTE_MAP``中),此步骤才会执行。

  • 如果属性是一个composite类型,更进一步的规则将创建;这些将匹配策略名称,形式为:<operation>_<resource>:<attribute>:<sub_attribute>。此情况下也使用’And’关系连接。

由于要验证的所有规则都由“And”关系链接,因此所有策略检查都应成功,以便能够授权请求。规则验证由oslo_policy执行,Neutron在此方面没有“定制”。

响应过滤

一些Neutron扩展,比如provider网络,为资源添加了一些属性,但是这些属性并不是所有客户都要使用的。这可能是因为这些属性包含实现细节,或者仅用于在类似Nova和Neutron等服务之间交换信息;

因此,在构建API响应时再次调用策略引擎。这是通过neutron.api.v2.base.Controller中的_exclude_attributes_by_policy方法实现的;

对于插件层返回的响应中的每个属性,此方法首先检查is_visible标志是否为真。在这种情况下,它将继续检查属性的策略;如果策略检查失败,则该属性将被添加到属性列表中,这些属性应在将其返回到API客户端之前从响应中删除。

neutron.policy API

neutron.policy模块开放了一个简单的API,其主要目标是允许REST API控制器实现本文中讨论的授权工作流程。从插件层内调用策略引擎是一个糟糕的实践,因为这将使请求授权依赖于插件本身,这违背了后端不可知的Neutron原则。

neutron.policy API开放了以下的函数:

  • init
    初始化策略引擎,从json策略(文件)加载。此方法可安全的调用多次。
  • reset
    清除当前配置在策略引擎中的所有规则。其在单元测试中和核心API router初始化的最后调用,确保在所有扩展加载之后加载规则。
  • refresh
    init和reset方法的组合。当SIGHUP信号发给API worker时调用。
  • set_rules
    显式的设置策略引擎的规则。仅在单元测试中使用。
  • check
    使用策略引擎执行检查。如本文所描述的构建匹配规则,之后使用oslo_policy的策略引擎评估结果规则。如果检查成功返回True,否则返回False。
  • enforce
    类似以上的check方法,不同点在于,如果oslo_policy检查失败,触发异常.
  • check_is_admin
    执行预定义的context_is_admin规则; 用于决定Neutron上下文的is_admin属性.
  • check_is_advsvc
    执行预定义的context_is_advsvc规则; 用于决定Neutron上下文的is_advsvc属性.

Neutron 特定策略规则

Neutron提供了两个额外的策略规则类,以支持它提供的“增强”授权能力。它们都扩展了oslo_policy.RuleCheck,并注册使用oslo_policy.register修饰符。

OwnerCheck: 对资源所有权的扩展检查

此类注册为匹配tenant_id关键字的规则,并覆写了oslo_policy在此情况下执行的通用检查。它的应用场景为,Neutron需要检查提交新资源请求的project是否拥有被创建资源的父资源。例如,当前的OwnerCheck应用:创建和更新Subnet。此类支持扩展父资源拥有者检查,其中父资源由服务插件引入。例如对router和floatingip拥有者检查的`router服务插件。开发者可注册扩展资源名称和服务插件名称,其已在neutron-lib中注册到neutron.common.constantsEXT_PARENT_RESOURCE_MAPPING``中。

__call__方法中支持的检查,流程如下:

  • 验证目标字段是否已在目标数据中。如果是,那么只需验证目标数据中目标字段的值是否等于凭证中相同字段的值,就像oslo_policy.GeneriCheck那样。这也是最常见的情况,因为目标字段通常是tenant_id

  • 如果以上的检查失败,则从目标字段中提取父资源类型和父字段名称。例如,networks:tenant_id标识network资源的tenant_id属性。对于扩展父资源案例,ext_parent:tenant_id标识EXT_PARENT_RESOURCE_MAPPING中已注册扩展资源的tenant_id属性;

  • 如果无法识别父资源或目标字段,则触发PolicyCheckError异常;

  • neutron.policy中的_RESOURCE_FOREIGN_KEYS 数据结构中获取’parent foreign key’。这个外键(parent key)只是父资源中充当主键的属性。如果无法检索此类’parent foreign key’,将触发PolicyCheckError异常;

  • 使用核心插件,获取具有’parent foreign key’作为标识符的资源实例;

  • 最后,验证此资源中的目标字段是否与初始请求数据中的目标字段匹配。例如,对于端口创建请求,请验证端口数据结构的tenant_id是否与正在创建此端口的网络的tenant_id匹配。

FieldCheck: 验证资源属性

此类在策略引擎中注册,用于匹配’field’关键字的规则,并提供对资源属性执行细粒度检查的方法。例如,使用此类规则可以指定一个规则,用于授予每个project对共享资源的读取访问权。

在policy.json中,使用以下方式指定FieldCheck规则:

 field: <resource>:<field>=<value>

这将导致初始化FieldCheck,其将检查目标资源数据中的<field>,如果等于<value>则返回True,或返回False,条件是<field>不等于<value>或根本不存在。

API开发人员指南

在为Neutron开发REST API时,重要的是要知道策略引擎将如何授权这些请求。这对于Neutron的"core"服务的API和各种Neutron "stadium"服务的API都是如此。

  • 如果某个资源的某个属性可能需要进行授权检查,则enforce_policy属性应设置为True。虽然为每个属性的此标志设置为True是一个可行的策略,但值得注意的是,这需要为每个属性调用策略引擎,从而一定增加完成资源策略检查所需的时间。这可能导致扩展性问题,特别是在列表操作时,需要获得大量资源的情况下;

  • 策略引擎可能仍然需要某些资源属性,即使不直接用于策略检查。例如,tenant_id属性就是这样。对于这些属性,required_by_policy属性应始终设置为True。这将确保属性包含在发送到策略引擎进行评估的资源数据中;

  • tenant_id属性是Neutron API请求授权中的一个基本属性。默认策略admin_or_owner使用它来验证project是否拥有它试图操作的资源。为此目的,如果创建了没有tenant_id的资源,则必须确保为此资源指定ad-hoc authZ策略。

  • 在Neutron的API层中,仍然只有一个检查是硬编码的:此检查验证project是否拥有它正在创建端口的网络。此检查是硬编码的,并且在创建端口时总是执行,除非网络是共享的。不幸的是,尚未找到通过策略引擎以有效方式执行此检查的解决方案。由于其性质,无法使用策略引擎覆盖此检查。

  • 强烈建议不要在插件或数据库管理类中执行策略检查。这可能导致插件之间的API行为不同。此外,如果请求在发送到后端之后未经授权,它可能会使Neutron数据库处于不一致的状态。

注意事项

  • 对于来自AMQP通道的RPC请求,不执行授权检查。对于所有这些请求,都建立了一个Neutron管理上下文,插件也会这样处理它们。

  • 对于PUTDELETE请求,在请求授权失败时返回404错误,而不是403错误,除非提交请求的project拥有要更新或删除的资源。这是为了避免API客户端试图通过发送对随机资源标识符的PUTDELETE请求来查找其他project的资源标识符。

  • 目前无法指定某个资源的两个属性之间的OR关系(例如:port.name == 'meh' or port.status == 'DOWN'),除非将带有或条件的规则显式添加到policy.json文件中。

  • OwnerCheck执行插件访问;这可能需要访问数据库,但由于此行为是一个特定的实现,因此也可能意味着与后端之间的往返。当涉及检索’parent’资源的属性时,此类检查应该非常谨慎地使用。

  • 为了使OwnerCheck规则工作,父资源应该在neutron.policy._RESOURCE_FOREIGN_KEYS中有一个条目;而且资源必须由“core”插件管理(即:在core_plugin配置变量中定义的插件)。

参考

[#] Oslo policy module <http://git.openstack.org/cgit/openstack/oslo.policy/
[#] Oslo policy developer <https://docs.openstack.org/oslo.policy/latest/
[#] API controller item_ method
_item: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/api/v2/base.py?id=2015.1.1#n282

[#] Policy engine’s build_match_rule_ method
_build_match_rule: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/policy.py?id=2015.1.1#n187

[#] exclude_attributes_by_policy_ method
_exclude_attributes_by_policy: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/api/v2/base.py?id=2015.1.1#n132

[#] Policy reset_ in neutron.api.v2.router
_reset: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/api/v2/router.py?id=2015.1.1#n122

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值