12. ROS 2访问控制策略

本文对用于保护ROS子系统安全的访问控制策略格式进行了设计。

作者:拉芬·怀特(Ruffin White)、凯尔·法扎里(Kyle Fazzari)

撰写日期:2019-08

最后修改时间:2021-06

SROS 2引入了几个安全性能,包括加密、身份验证和授权。授权是通过组合前两个性能及访问控制模型来获得的。此类访问控制模型通常称为访问控制策略。访问控制策略作为对与安全属性相关联的特权(privilege)的一种高级抽象,可能会被转换为用于诸如DDS安全网络中特定ROS节点等个体身份的底层权限(permissions)。

12.1 概念

在详细介绍SROS 2访问控制(系统通过它限制主体访问客体的能力)策略设计之前,重要的是要建立起一些有助于形式化安全设计方法的概念。在本文中,主体可以认为是分布式数据总线上的参与者(例如计算图中的ROS节点),而客体可能是特定子系统实例(例如ROS话题),访问则被定义为对客体采取行动的能力(例如发布或订阅)。

12.1.1 强制访问控制(Mandatory Access Control)

强制访问控制(MAC)是指当且仅当存在允许某个给定主体访问资源的规则时才允许该主体对客体进行访问;术语“强制”表示必须始终明确规定主体对客体的访问权限。最重要的是,与自由访问控制(DAC,Discretionary Access Control)相反,此类强制访问控制策略是由一组授权规则强制执行的,主体不能无意或有意地覆盖或修改这些授权规则。这也可以称为“默认拒绝(deny by default)”策略。

12.1.2 最少特权原则(Principle of Least Privilege)

最少特权原则(PoLP)要求在某个特定的抽象层中,每个主体必须​​只能访问其合法用途所需的资源。这也称为最小特权原则(principle of minimal privilege)或最少权限原则(principle of least authority)。应用PoLP不仅可以增强系统安全性,而且还可以简化系统部署并有助于提高系统稳定性。

12.1.3 特权分离(Privilege Separation)

特权分离要求将某个主体的访问权限划分为多个部分,每个部分仅限于执行特定任务所需的具体权限。特权分离可用于减轻安全漏洞的潜在危害。无法满足特权分离要求的系统因此也可能无法满足PoLP。

12.1.4 关注点分离(Separation of Concerns)

关注点分离(SoC)是一种将某个系统划分成多个不同部分以便让每个部分解决一个单独关注点(separate concern)的设计原则。在本用例中,单独关注点可能是在某个系统中如何管理加密的问题及如何将授权授予主体的问题。

12.2 准则(Criteria)

本节将会讨论SROS 2策略以及选择可扩展标记语言(XML, Extensible Markup Language)的设计准则。

12.2.1 校验(Validation)

在对诸如访问控制策略等任何用户配置输入进行解释之前,应该应用数据校验以确保这些输入合规且格式正确。不正确的输入会影响大多数程序或工具的可靠性(soundness),而防范一般错误本身可能需要细致的校验逻辑。使用精确模式(schema)对数据描述进行形式化可以独立程序来断言这些输入是否合规,而无需跨不同实现重复相同的校验逻辑。在XML中,这是通过使用XSD来实现的;允许通过可扩展的标准定义(XSD,extendable standard definition)而不是某个规范实现来定义该策略标记(markup)。

12.2.2 转换(Transformation)

对于可用性和通用性,访问控制策略可以使用诸如基于ROS的主体和客体等特定于域的抽象来表达。然而,当应用于较低层次的传输和策略执行点时,此类抽象可能会转换成不同的表示。使用某种转换语言形式化这个数据转换可以让独立程序在无需跨不同实现重复转换逻辑的情况下进行转换。在XML中,这是通过使用XSLT来实现的;通过简单地交换或扩展转换,允许为各种传输轻松转换该策略标记。

12.2.3 组合(Composition)

在制定访问控制策略时,许多主体可能会共享一些用于基本访问的基本特权。为避免可能会加剧人为错误或其他出入的不必要重复,这些策略应有足够的表达能力以保持DRY(Don’t Repeat Yourself)。在XML中,这是通过使用XInclude来实现的;XInclude允许策略标记轻松包含或替换对具体配置文件和权限(这些权限会跨不同独立策略或配置文件重复)的外部引用。

12.3 模式(Schema)

SROS 2策略模式是用XML定义的。构成某个策略的元素和属性描述如下:

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema

xmlns:xs="w3.org/2001/XMLSchema"

xmlns:xml="w3.org/XML/1998/namespa"

elementFormDefault="qualified" attributeFormDefault="unqualified">

<xs:import namespace="w3.org/XML/1998/namespa"

schemaLocation="w3.org/2001/03/xml.xsd" />

<xs:element name="policy" type="Policy" />

<xs:complexType name="Policy">

<xs:sequence minOccurs="1" maxOccurs="1">

<xs:element name="enclaves" type="Enclaves" />

</xs:sequence>

<xs:attribute name="version" type="xs:string" use="required" fixed="0.2.0"/>

</xs:complexType>

<xs:complexType name="Enclaves">

<xs:sequence minOccurs="1" maxOccurs="unbounded">

<xs:element name="enclave" type="Enclave" />

</xs:sequence>

</xs:complexType>

<xs:complexType name="Enclave">

<xs:sequence minOccurs="1" maxOccurs="unbounded">

<xs:element name="profiles" type="Profiles" />

</xs:sequence>

<xs:attribute name="path" type="xs:string" use="required" />

</xs:complexType>

<xs:complexType name="Profiles">

<xs:sequence minOccurs="1" maxOccurs="1">

<xs:sequence minOccurs="1" maxOccurs="unbounded">

<xs:element name="profile" type="Profile" />

</xs:sequence>

<xs:sequence minOccurs="0" maxOccurs="1">

<xs:element name="metadata" type="xs:anyType" />

</xs:sequence>

</xs:sequence>

<xs:attribute name="type" type="xs:string" use="optional" />

</xs:complexType>

<xs:complexType name="Profile">

<xs:sequence minOccurs="0" maxOccurs="unbounded">

<xs:choice minOccurs="1" maxOccurs="1">

<xs:element name="topics" minOccurs="1" type="TopicExpressionList" />

<xs:element name="services" minOccurs="1" type="ServicesExpressionList" />

<xs:element name="actions" minOccurs="1" type="ActionsExpressionList" />

</xs:choice>

</xs:sequence>

<xs:attribute name="ns" type="xs:string" use="required" />

<xs:attribute name="node" type="xs:string" use="required" />

<xs:attribute ref="xml:base" />

</xs:complexType>

<xs:complexType name="TopicExpressionList">

<xs:sequence minOccurs="1" maxOccurs="unbounded">

<xs:element name="topic" type="Expression" />

</xs:sequence>

<xs:attribute name="publish" type="RuleQualifier" use="optional" />

<xs:attribute name="subscribe" type="RuleQualifier" use="optional" />

<xs:attribute ref="xml:base" />

</xs:complexType>

<xs:complexType name="ServicesExpressionList">

<xs:sequence minOccurs="1" maxOccurs="unbounded">

<xs:element name="service" type="Expression" />

</xs:sequence>

<xs:attribute name="reply" type="RuleQualifier" use="optional" />

<xs:attribute name="request" type="RuleQualifier" use="optional" />

<xs:attribute ref="xml:base" />

</xs:complexType>

<xs:complexType name="ActionsExpressionList">

<xs:sequence minOccurs="1" maxOccurs="unbounded">

<xs:element name="action" type="Expression" />

</xs:sequence>

<xs:attribute name="call" type="RuleQualifier" use="optional" />

<xs:attribute name="execute" type="RuleQualifier" use="optional" />

<xs:attribute ref="xml:base" />

</xs:complexType>

<xs:simpleType name="Expression">

<xs:restriction base="xs:string" />

</xs:simpleType>

<xs:simpleType name="RuleQualifier">

<xs:restriction base="xs:string">

<xs:enumeration value="ALLOW" />

<xs:enumeration value="DENY" />

</xs:restriction>

</xs:simpleType>

</xs:schema>

12.3.1 <policy> 标签

<policy>标签是策略文件的根标签。每个策略文件只能有一个<policy>标签。

该标签具有以下属性:

 version:正在使用的模式(schema)版本的声明版本

○ 允许推进该模式的未来修订

12.3.2 <enclaves>标签

该标签内可以封装一系列唯一的飞地。这种嵌套序列的方法允许将额外的标签扩展到<policy>根标签中。

12.3.3 <enclave>标签

该标签中可以封装一组配置文件。此标签用于指定由关联属性确定的某个具体飞地。

该标签具有以下属性:

 path:用于指定完全限定的飞地路径

鉴于可以将多个节点组合到一个进程中,所以用一个飞地来包含所有相应节点的配置文件集。因此,一个飞地可以被视作包含多个配置文件的联合体。请注意,一个飞地内的配置文件联合体将会导致任何配置文件的“拒绝”权限取代每个配置文件的全部“允许”权限。例如,如果某个配置文件请求一个权限,但该飞地中的另一个配置文件明确拒绝了这个相同的权限,则拒绝规则将具有优先权。有关如何应用MAC的更多信息,请参阅<profile>标签部分。

12.3.4 <profiles>标签

该标签可以封装一系列唯一的配置文件和指定的元数据。这种嵌套序列的方法允许将额外的标签扩展到<enclave>根标签中,以及将具体元数据或约束关联到这些被包含的配置文件元素中。

该标签具有以下属性:

 type:用于指定配置文件和元数据的传输类型

12.3.5 <profile>标签

该标签中可以封装一组主体的权限。这个标签用于指定由关联属性确定的某个唯一节点实例。

该标签具有以下属性:

 ns:用于指定该节点的命名空间

 node:用于指定该节点名称

根据MA​​C,各项特权必须明确限定为允许。此外,与许多其他MAC语言一样,虽然组合特权可能会重叠,但任何具体“拒绝”特权都会抑制任何类似适用的“允许”特权。也就是说,“拒绝”特权的优先级保守地取代了“允许”特权,从而可以避免PoLP中的潜在失误。这种扁平化特权的方法使得用户能够提供对较大客体集的一般访问权限,同时撤销对较小敏感客体子集的访问权限。尽管这样会阻止对限定符的递归,但其结果是简化了转换,从而可以防止意外访问的潜在可能性。

12.3.6 <metadata>标签

该标签可以封装任意元数据或约束。这可能包括可应用于同级配置文件元素的传输特定权限详细信息。每个<profiles>父元素只能有一个<metadata>元素。

该标签具有以下属性:

● 待定义(即该标签目前尚无任何属性)

考虑到桥接接口用例,在这种接口中一个飞地的凭据可能会用于跨多个传输进行互连或者用于传输特定的一些域,因此可能有必要使用具体约束来限定某些配置文件序列,虽然会为每个飞地的各个配置文件多次这样做。这允许高级用户全面控制跨不同传输域的权限交叉,同时保持安全权限的准确模型保真度。考虑到桥接接口的安全敏感性及其暴露的攻击面,网桥内的信息流控制保持对安全可靠操作形式上的可验证性至关重要。

(1)特权

特权被定义为对客体访问规则和权限的配置。由于客体可以按照子系统类型进行分类,因此各项规则及其相应的权限具有相同的结构。鉴于一个平均配置文件可能会引用比规则数量更多的具有多项权限的多个唯一客体,因此会选择规则/权限/客体层次结构以最小化文字细节。

规则类型 权限
动作 调用,执行
服务 响应,请求
话题 发布,订阅

每个子系统都与一个给定的规则类型相关联,而权限则被表示为其各自规则标签中的属性。并不要求这个序列中的规则具有唯一性或对规则进行排序,因为这是由转换模板进行解释的。实际上,配置文件可能可以包含一组空的权限;这在节点可能不需要子系统权限,但仍然必须为DDS中的发现目的提供身份时特别有用。

每个规则都包含一系列应用权限的客体。对于诸如Secure DDS等某些安全传输而言,匹配表达式也可用于使用通配模式进一步扩展作用范围,特别是POSIX标准中规定的fnmatch支持的那些通配模式。但是,在使用表达式匹配时应该保持谨慎小心,正如在后文“几点顾虑(Concerns)”一节中进一步讨论的那样。

支持的基本fnmatch模式如下表所示:

模式(Pattern) 意义(Meaning)
* 匹配一切
匹配任何单个字符
[sequence] 匹配序列中的任意字符
[!sequence] 匹配不在序列中的任意字符

12.3.7 <topics>标签

该标签可以封装一组具有指定权限的<topic>标签。

该标签具有以下两个属性:

 publish:用于指定是否允许该节点在这组话题上发布消息

○ 即该节点是否可以是某个话题的发布者

○ 有效值为“允许(ALLOW)”或“拒绝(DENY)”

 subscribe:用于指定是否允许该节点订阅这组话题

○ 即该节点是否可以是某个话题的订阅者

○ 有效值为“允许(ALLOW)”或“拒绝(DENY)”

12.3.8 <services>标签

该标签可以封装一组具有指定权限的<service>标签。

该标签具有以下2个属性:

 request:用于指定是否允许该节点请求该服务

○ 即该节点是否可以为一个服务客户端

○ 有效值为“允许(ALLOW)”或“拒绝(DENY)”

 reply:用于指定是否允许该节点对这些服务请求进行响应

○ 即该节点是否可以为一个服务服务器

○ 有效值为“允许(ALLOW)”或“拒绝(DENY)”

12.3.9 <actions>标签

该标签可以封装一组具有指定权限的<action>标签。

该标签具有以下2个属性:

 call:用于指定是否允许该节点调用该动作

○ 即该节点是否可以为一个动作客户端

○ 有效值为“允许(ALLOW)”或“拒绝(DENY)”

 execute:用于指定是否允许该节点执行该动作

○ 即该节点是否可以为一个动作服务器

○ 有效值为“允许(ALLOW)”或“拒绝(DENY)”

12.4 模板(Templating)

要将SROS 2策略转换为目标访问控制传输的安全工件,可以使用XSLT模板来执行这个层次的文档转换。这可能包括对目标传输任意次数的优化或调整。例如,Secure DDS的流水线步骤如下所示:

1. 指定一个具有SROS 2策略根标签的XML文档

2. 使用XInclude完全扩展该文档以引用外部元素

3. 然后使用等效模式(schema)版本验证该扩展后的文档

4. 这时可能会也可能不会对该文档树修剪至某个具体配置文件

5. 然后使用转换模板对该有效文档进行转换

6. 对于每个配置文件,一个匹配的DDS授权会被追加到许可文件中

○ 特权和命名空间被重映射到某个以DDS为中心的表示中

○ 合并具有相同属性的特权以减少有效负载大小

○ 修剪同一个特权中的重复对象以减少有效负载大小

○ 对各项权限进行排序,排序时“拒绝(deny)”类特权优先,当使用DDS时遵守限定符(qualifiers)优先级

○ 对象也按字母顺序排序以提高可读性和变化差异性

12.5 替代方案

本节主要关注考虑过的各个提议设计和替代方案,包括不同的标记语言和策略格式。

12.5.1 YAML标记语言

YAML是“YAML Ain’t Markup Language”递归首字母缩写词,最初在SROS第一个版本中用于指定访问控制策略[1]。尽管SROS 1中使用的策略模型在语义上是等效的,但归因于缺乏清晰的元素属性而导致每个命名空间资源的权限重复,YAML格式让该策略模型变得非常冗长。对于SROS 2,我们决定将标记语言从YAML切换到XML,原因有多方面的,对其优缺点权衡如下:

● 优点

○ 人类可读方面:最小行噪声(Minimal Line Noise)

■ YAML具有非常少的语法,且其目标就是面向人工可编辑的配置文件,这使得YAML的人工读写很简单。

○ 数据模型:直观解释(Intuitive Interpretation)

■ YAML具有非常简单的数据模型,使用键值对字典和列表构成树结构,使其非常易于使用。

● 缺点

○ 可解析性:隐式类型转换(Implicit Type Casting)

■ 鉴于YAML是一种数据序列化语言,它可能会尝试在所有可能之处进行类型转换。但是,这并不总是具有期望的效果,而且可能会导致意外行为。对布尔值与字符串的解析就是存在歧义的显著例子。

○ 解释器(Interpreters):验证和转换

■ 尽管许多编程语言都支持YAML,但YAML本身并没有提供执行文档结构的模式。

■ 必须为每个解释器实现重复进行验证,这使得其与所使用的编程语言无关。

■ 类似地,将策略转换为传输安全工件的转换跨各个实现的通用性较差。

○ 可组合性:配置文件的重用

■ 尽管YAML通过锚点(Anchors)、别名和扩展支持一定程度的可组合性,允许文档更加DRY(Don’t Repeat Yourself),但这些可组合性并没有扩展到单独的文件或外部资源。

○ 表达能力:简洁的表示

■ 鉴于YAML的继承(inherit)数据模型,其表达能力非常有限,需要冗长的文件结构或者不直观的选项来实现类似的访问控制配置。

12.5.2 自定义标记语言

作为选择现有标记格式的替代方案,可以定义我们自己的形式化语言,以使用自定义文件语法来表达ROS 2的访问控制权限。基于MAC的策略语言的一个示例就包括在AppArmor中使用的语言。尽管这种自定义标记语言在最小化一般语法开销的同时还提供了简洁表达配置文件权限的灵活性,但鉴于对以下多方面优缺点的权衡,并没有采用这种方法:

● 优点

○ 表达能力:简洁的表示

■ 完全控制语法和解释,允许对SROS策略表示进行领域特定的优化。

● 缺点

○ 解释器:验证和转换

■ 解析和解释自定义策略格式的规范和实现将被视为承诺。

■ 必须为每个解释器实现重复进行验证,这使得其与所使用的编程语言无关。

■ 类似地,将策略转换为传输安全工件的转换跨各个实现的通用性较差。

○ 正确性:维持策略可靠

■ 跨多种编程语言维护和同步解析支持可能会影响策略的可靠性。

12.5.3 ComArmor

ComArmor[2]是SROS 2中现在使用的已有XML ROS 2策略格式的前身和灵感来源,其本身的灵感来自AppArmor的策略语言。 ComArmor通过使用策略/配置文件/权限原语(primitives)的嵌套树结构来促进组合。与AppArmor一样,ComArmor也支持配置文件嵌套,即把配置子文件导入到配置父文件中。虽然由于嵌套导入配置文件层次结构极大地扩展了其灵活性,但在将策略转换为安全传输工件时,这也会增加转换过程的复杂性。

为了在简单性和灵活性之间取得平衡,SROS 2反而选择了单层配置文件的扁平序列,从而允许策略格式既可以用作更高层次策略语言的基础中间表示和在其其上进行构建的工具,例如XACMLKeymint,同时保持对ROS一般用途概念的简洁表达。

12.6 几点顾虑

12.6.1 特权分离

诸如话题、服务、动作和参数等ROS 2子系统最终必须映射到传输层接口,如DDS话题,该接口可以充分执行所需的访问控制策略以便保护ROS应用层的安全。然而,子系统映射和特权分离之间的任何怪癖(quirks)都会降低安全性。

例如,如果授予对所有以/foo开头的话题和服务的访问权限,此外还授予对所有以/foo开头的动作的访问权限,这会是特权分离的一个坏示例。当使用包含诸如fnmatch等匹配模式的通配(globbing)表达式时,这种情况可能会变得更糟,会导致无害且可靠的策略被不准确地应用于底层传输安全。虽然这种特权分离在ROS 2和DDS之间仍然存在弱点,但不鼓励将表达式匹配用于一般用途权限也许是明智的。

12.6.2 关注点分离

诸如DDS等中间件传输都会提供无数的功能和选项,例如那些用于服务质量QoS和安全的功能和选项。在决定从配置的角度公开什么内容时,在许多这些功能之间划定界限可能会很棘手。尽管如此,ROS 2 的目标中仍然包括保持传输尽可能合理的不可知。

虽然SROS 2策略格式有意模仿Secure DDS的permission.xml格式,但在向与ROS 2数据流相切的表面非功能性安全属性(例如加密或发现治理)添加扩展时应小心谨慎。

然而,如果SROS 2策略的预期用途是跨不同传输的中间表示,并且随后从更高层次的工具/表示中自动生成,或者可组合性得到了充分保留,那么这种顾虑可能不太重要。

12.6.3 可组合性

ROS 2允许在运行时重映射许多命名空间子系统,例如在重用启动文件来编排更大的应用程序时。虽然在没有事先分配此类功能的情况下期望从静态配置权限中获得这种动态灵活性可能不合理,但应该可以从组合的启动文件和类似编排中推断出需要的功能。

这种重映射的静态分析结合各个节点的名义要求设置可用于自动生成新的令人满意的策略。但是,从源代码推断此类策略可能等同于停机问题(halting problem)。因此,理所当然地,节点可以提供定义这些名义要求的清单或 IDL,以便至少在设计时可以轻松地对权限进行重映射。

参考文献

1. SROS1: Using and Developing Secure ROS1 Systems

@inbook{White2019,

title = {SROS1: Using and Developing Secure ROS1 Systems},

author = {White, Ruffin and Caiazza, Gianluca and Christensen, Henrik and Cortesi, Agostino},

year = 2019,

booktitle = {Robot Operating System (ROS): The Complete Reference (Volume 3)},

doi = {10.1007/978-3-319-91590-6_11},

isbn = {978-3-319-91590-6},

url = {doi.org/10.1007/978-3-3}}

2. Procedurally Provisioned Access Control for Robotic Systems

@inproceedings{White2018,

title = {Procedurally Provisioned Access Control for Robotic Systems},

author = {White, Ruffin and Caiazza, Gianluca and Christensen, Henrik and Cortesi, Agostino},

year = 2018,

booktitle = {2018 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS)},

doi = {10.1109/IROS.2018.8594462},

issn = {2153-0866},

url = {doi.org/10.1109/IROS.20}}

*英语原文网址:design.ros2.org/article...