This article specifies the policy format used for access control when securing ROS subsystem.
Authors: Ruffin White, Kyle Fazzari
Date Written: 2019-08
Last Modified: 2021-06
SROS 2 introduces several security properties, including encryption, authentication, and authorization. Authorization is obtained by combining the first two properties with a model for access control. Such models are often referred to as access control policies. A policy serves as a high-level abstraction of privileges associated with attributes that may then be transpiled into low-level permissions for individual identities, such as specific ROS nodes within a secure DDS network.
Before detailing the SROS 2 policy design of the access control, by which the system constrains the ability of a subject to access an object, it is important to establish a few concepts useful in formalizing the design approach in terms of security. In this setting, a subject may be thought of as a participant on a distributed data-bus (e.g. a ROS node in the computation graph), whereas an object may be an instance of a particular subsystem (e.g. a ROS topic), and access is defined as the capability to act upon that object (e.g. publish or subscribe).
Mandatory Access Control (MAC) refers to allowing access to an object if and only if rules exist that allow a given subject to access the resource; the term mandatory denotes this requirement that a subject’s access to an object must always be explicitly provisioned. Most importantly, contrary to discretionary access control (DAC), such policies are enforced by a set of authorization rules that cannot be overridden or modified by the subject either accidentally or intentionally. This could also be referred to as “deny by default”.
Principle of Least Privilege (PoLP) requires that in a particular abstraction layer, every subject must be able to access only the resources necessary for its legitimate purpose. This is also known as the principle of minimal privilege or the principle of least authority. Applying PoLP not only bolsters system security, but can also ease deployment and help improve system stability.
Privilege Separation requires that a subject’s access be divided into parts which are limited to the specific privileges they require in order to perform a specific task. This is used to mitigate the potential damage of a security vulnerability. Systems unable to comply with this requirement may consequently fail to satisfy PoLP as well.
Separation of Concerns (SoC) is a design principle for separating a system into distinct sections, so that each section addresses a separate concern. Separate concerns in this case may be how encryption is governed in a system versus how authorization is given to subjects.
Design criteria for SROS 2 policies and for selecting the Extensible Markup Language (XML) are discussed here.
Prior to interpreting any user configuration input, such as an access control policy, data validation should be applied to ensure inputs are compliant and correctly formatted. Incorrect inputs can affect the soundness of most programs or tools, yet guarding against general malformations may itself require meticulous validation logic. Formalizing the description of the data using a precise schema allows for separate programs to assert inputs are compliant without replicating validation logic across implementations. In XML, this is achieved using XSD; allowing the policy markup to be defined by an extendable standard definition rather than a canonical implementation.
For usability and generalizability, access control policies can be expressed using domain specific abstractions, such as ROS based subjects and objects. However such abstractions may translate into different representations when applied to lower level transports and policy enforcement points. Formalizing this data transformation using a transformation language allows for separate programs to transpile without replicating conversion logic across implementations. In XML, this is achieved using XSLT; allowing the policy markup to be easily transpiled for various transports by simply swapping or extending transforms.
When formulating an access control policy, many subjects may share fundamental privileges for basic access. To avoid unnecessary repetition that could exacerbate human errors or other discrepancies, policies should possess sufficient expressive power to remain DRY. In XML, this is achieved using XInclude; allowing the policy markup to easily include or substitute external reference to particular profiles and permissions that repeat across separate policies or profiles.
The SROS 2 policy schema is defined with XML. The elements and attributes that make up a policy are described below.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.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>
<policy>
TagRoot tag of the policy file.
There must be only one <policy>
tag per policy file.
Attributes:
<enclaves>
TagEncapsulates a sequence of unique enclaves.
This method of nesting sequences allows for additional tags to be extended to the <policy>
root.
<enclave>
TagEncapsulates a collection of profiles. This is specific to an enclave as determined by associative attributes.
Attributes:
Given that multiple nodes can be composed into a single process, an enclave is used to contain the collection of profiles of all respective nodes.
An enclave may therefore be considered the union of contained profiles.
Note that the union of profiles within an enclave will result in denied privileges of any profile to supersede all allowed privileges for every profile.
E.g. if a profile asks for a permission but a matching permission has been explicitly denied by another profile in the enclave, the deny rule will take precedence.
See section <profile>
Tag for more info on how MAC is applied.
<profiles>
TagEncapsulates a sequence of unique profiles and designated metadata.
This method of nesting sequences allows for additional tags to be extended to the <enclave>
root, as well as associating particular metadata or constraints to the contained profile elements.
Attributes:
<profile>
TagEncapsulates a collection of subject privileges. This is specific to a unique node instance as determined by associative attributes.
Attributes:
In accordance with MAC, privileges must be explicitly qualified as allowed. Additionally, as with many other MAC languages, while composed privileges may overlap, any particular denied privilege will suppress any similarly applicable allowed privileges. That is to say the priority of denied privileges conservatively supersedes allowed privileges, avoiding potential lapses in PoLP. This method of flatting privileges enables users to provision general access to a larger set of objects, while simultaneously revoking access to a smaller subset of sensitive objects. Although recursion of qualifiers is subsequently prevented, transformations are subsequently simplified, preventing potential for unintended access.
<metadata>
TagEncapsulates arbitrary metadata or constraints.
This could include transport specific permission details applicable to sibling profile elements.
There can only one metadata
element per profiles
parent element.
Attributes:
Given the use cases for bridge interfaces where an enclave’s credentials may be used to interconnect across multiple transports or to transport specific domains, it may be necessary to qualify certain profile sequences with particular constraints, while doing so multiple times for separate profiles per enclave. This allows advanced users to holistically control the intersect of permissions across transport domains, while retaining accurate model fidelity of security permissions. Given how security sensitive bridge interfaces are and the attack surface they expose, it is vital that information flow control within a bridge remains formally verifiable for safe and secure operation.
Privileges are defined as configuration of rules and permissions for object access. As objects can be categorized by subsystem type, rules and respective permission are identically structured. Given an average profile is likely to reference more unique objects with multiple permissions than number of rules, the subsequent hierarchy of rules/permissions/objects is chosen to minimize verbosity.
rule types | permissions |
---|---|
actions | call, execute |
services | reply, request |
topics | publish, subscribe |
Each subsystem is associated to a given rule type, while permissions are expressed as attributes in their respective respective rule tags. Uniqueness or ordering of rules in this sequence is not required, as this is accounted for by transformation templates. In fact, a profile may contain an empty set of privileges; particularly useful when a node may require no subsystem permissions, but must still be provisioned an identity nonetheless for discovery purposes in DDS.
Each rule includes a sequence of objects that the permissions apply. For some secure transports, such as Secure DDS, matching expressions may also be used to expand the scope further using globbing patterns, specifically those supported by fnmatch as specified in the POSIX standard. However, caution should be taken when using expression matching, as discussed further in the concerns section.
Basic fnmatch-style patterns are supported:
Pattern | Meaning |
---|---|
* | Matches everything |
? | Matches any single character |
[sequence] | Matches any character in sequence |
[!sequence] | Matches any character not in sequence |
<topics>
TagA group of <topic>
tags with the specified permissions.
Attributes:
<services>
TagA group of <service>
tags with the specified permissions.
Attributes:
<actions>
TagA group of <action>
tags with the specified permissions.
Attributes:
To transpile SROS 2 policies into security artifacts for a targeted access controlled transport, XSLT templates can be used to perform this level of document conversion. This may include any number of optimisations or adjustments specific for the target transport. For example, the pipeline stages for targeting Secure DDS is as follows:
This section lists concerns about the proposed design and alternatives that were considered, including different Markup Languages and policy formats.
YAML, a recursive acronym for “YAML Ain’t Markup Language”, was originally adopted for specifying access control policies in the first version of SROS [1]. Although the policy model used in SROS 1 was semantically equivalent, the YAML format lent it being quite verbose due to repetition of permissions per namespaced resource given the lack of clear element attributes. For SROS 2 we decided switched away from YAML to XML for many of the reasons weighed in the following pros and cons:
As an alternative to choosing an existing markup format, it would be possible to define our own formal language for expressing access control permissions for ROS 2 using a custom file syntax. An example of a MAC based policy language would include that which is used in AppArmor. Although affording the flexibility to succinctly express profile permission while minimizing general syntactic overhead, this approach was not pursued for many of the reasons weighed in the following pros and cons:
ComArmor [2], a predecessor and inspiration for the existing XML ROS 2 policy format now used in SROS 2, is itself inspired from AppArmor’s policy language. ComArmor facilitates composition through the use of a nested tree structure of policy/profile/permission primitives. As with AppArmor, it also supports nesting of profiles, i.e. importation of child profiles into that of a parent profile. While this greatly extends the flexibility given the nesting of imported sun-profile hierarchies, it also adds complexity to the transpiling process when converting policies to security transport artifacts.
In an effort to strike a balance between simplicity and flexibility, a flat sequence of single level profiles was opted for SROS 2 instead, allowing the policy format to serve as both a grounded intermediate representation for higher level policy languages and tools to build upon, such as XACML or Keymint, while remaining succinctly expressive of ROS concepts for general use.
ROS 2 subsystems such as topics, services, actions, and parameters must eventually map to transport layer interfaces, such as DDS topic, that can sufficiently enforce the desired access control policy in order to secure the ROS application layer. However, any quirks between mapping of subsystems and separation of privileges can degrade security.
As an example, if granting access to all topics and services starting with /foo
additionally grants access to all actions starting with /foo
, this would be a weak example of privilege separation.
Such can be exacerbated when using globbing expressions that include matching patterns, such as with fnmatch
, leading to innocuous and sound policies being inaccurately applied to the underlying transport security.
While such privilege separation in remains week between ROS 2 and DDS, perhaps it is wise to discourage the use of expression matching for general use in permissions.
Middleware transports, such as DDS, offer a myriad of features and options, such as those for QoS as well as security. Drawing a boundary between many of them when deciding what to expose from a configuration standpoint can be tricky. Still, among the objective for ROS 2 includes remaining as agnostic of transport as reasonable.
Although the SROS 2 policy format was intentionally structured to mimic that of Secure DDS’s permission.xml format, care should be taken when adding extensions to surface non-functional security properties tangential to ROS 2 data flow, such as governance on encryption or discovery.
Yet, if the intended purpose of SROS 2 policy becomes that of an intermediate representation across transports, and is subsequently auto generated from higher level tooling/representations, or composability is adequate preserved, then perhaps this concern is of lesser priority.
ROS 2 allows for the remapping of many namespaced subsystems at runtime, such as when reusing launch files to orchestrate larger applications. While it is perhaps unreasonable to expect this dynamic flexibility from staticky provisioned permissions without allocating such capabilities prior, it should be made possible to infer the necessary capabilities from composed launch files and similar orchestrations.
Static analysis of such remapping in conjunction with the setting of the nominal requirements of respective nodes could be used to auto generate the new satisfactory policies. However, inferring such policies from the source code could be equated to the halting problem. Thus, it stands to reason nodes could instead provide a manifest or IDL defining these nominal requirements so that permission may as easily be remapped, at least at design time.
@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 = {https://doi.org/10.1007/978-3-319-91590-6_11}}
@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 = {https://doi.org/10.1109/IROS.2018.8594462}}