Robotics is full of experimentation: evaluating different hardware and software, pushing ahead with what works, and culling what doesn’t. ROS was designed to be flexible to enable this experimentation; to allow existing components to easily be combined with new ones or swapped with others. In ROS 1, this flexibility was valued above all else, at the cost of security. By virtue of being designed on top of DDS, ROS 2 is able to retain that flexibility while obtaining the ability to be secured by properly utilizing the DDS-Security specification. This article describes how ROS 2 integrates with DDS-Security.
Original Author: Kyle Fazzari
The DDS-Security specification expands upon the DDS specification, adding security enhancements by defining a Service Plugin Interface (SPI) architecture, a set of builtin implementations of the SPIs, and the security model enforced by the SPIs. Specifically, there are five SPIs defined:
ROS 2’s security features currently utilize only the first three. This is due to the fact that neither Logging nor Data Tagging are required in order to be compliant with the DDS-Security spec (see section 2.3), and thus not all DDS implementations support them. Let’s delve a little further into those first three plugins.
The Authentication plugin (see section 8.3 of the DDS-Security spec) is central to the entire SPI architecture, as it provides the concept of a confirmed identity without which further enforcement would be impossible (e.g. it would be awfully hard to make sure a given ROS node could only access specific topics if it was impossible to securely determine which node it was).
The SPI architecture allows for a number of potential authentication schemes, but ROS 2 uses the builtin authentication plugin (called “DDS:Auth:PKI-DH”, see section 9.3 of the DDS-Security spec), which uses the proven Public Key Infrastructure (PKI). It requires a public and private key per domain participant, as well as an x.509 certificate that binds the participant’s public key to a specific name. Each x.509 certificate must be signed by (or have a signature chain to) a specific Certificate Authority (CA) that the plugin is configured to trust.
The rationale for using the builtin plugin as opposed to anything else is twofold:
The Access control plugin (see section 8.4 of the DDS-Security spec) deals with defining and enforcing restrictions on the DDS-related capabilities of a given domain participant. For example, it allows a user to restrict a particular participant to a specific DDS domain, or only allow the participant to read from or write to specific DDS topics, etc.
Again the SPI architecture allows for some flexibility in how the plugins accomplish this task, but ROS 2 uses the builtin access control plugin (called “DDS:Access:Permission”, see section 9.4 of the DDS-Security spec), which again uses PKI. It requires two files per domain participant:
Both of these files must be signed by a CA which the plugin is configured to trust. This may be the same CA that the Authentication plugin trusts, but that isn’t required.
The rationale for using the builtin plugin as opposed to anything else is the same as the Authentication plugin:
The Cryptographic plugin (see section 8.5 of the DDS-Security spec) is where all the cryptography-related operations are handled: encryption, decryption, signing, hashing, etc. Both the Authentication and Access control plugins utilize the capabilities of the Cryptographic plugin in order to verify signatures, etc. This is also where the functionality to encrypt DDS topic communication resides.
While the SPI architecture again allows for a number of possibilities, ROS 2 uses the builtin cryptographic plugin (called “DDS:Crypto:AES-GCM-GMAC”, see section 9.5 of the DDS-Security spec), which provides authenticated encryption using Advanced Encryption Standard (AES) in Galois Counter Mode (AES-GCM).
The rationale for using the builtin plugin as opposed to anything else is the same as the other plugins:
Now that we have established some shared understanding of how security is supported in DDS, let’s discuss how that support is exposed in ROS 2. By default, none of the security features of DDS are enabled in ROS 2. The set of features and tools in ROS 2 that are used to enable them are collectively named “Secure ROS 2” (SROS 2).
Most of the user-facing runtime support for SROS 2 is contained within the ROS Client Library. Once its requirements are satisfied it takes care of configuring the middleware support for each supported DDS implementation. RCL includes the following features for SROS 2:
Let’s discuss each of these in turn.
As stated earlier, the DDS-Security plugins require a set of security files (e.g. keys, governance and permissions files, etc.) per domain participant. Domain participants map to a specific instance of a node in ROS 2, so each node requires a set of these files. RCL supports being pointed at a directory containing security files in two different ways:
Let’s delve further into these.
RCL supports finding security files in one directory that is the root of a directory structure corresponding to the fully-qualified names of every node instance (i.e. namespace + node name).
For example, for the
/front/camera node, the directory structure would look like:
<root> └── front └── camera ├── cert.pem ├── key.pem ├── ...
To be clear: this directory structure needs to reflect the state of the running system. In other words, it does not contain a set of files per node on disk, but per node instance in the ROS graph.
The set of files expected within each node instance directory are:
This can be specified by setting the
$ROS_SECURITY_ROOT_DIRECTORY environment variable to point to the root of the directory tree.
If using the directory tree approach to organize security files, RCL supports two different methods for looking up a given node instance’s security files in the tree:
<root>/foo/bar/baz_123/. This is the default behavior.
<root>/foo/bar/baz_123/. However, if that directory doesn’t exist, find the most specific (i.e. longest) node name that does have security files within that namespace (e.g.
<root>/foo/bar/baz/, etc.). Note that it will not search higher in the namespace hierarchy.
The desired lookup method can be specified by setting the
$ROS_SECURITY_LOOKUP_TYPE environment variable to “MATCH_EXACT” (case-sensitive) for the Exact method, or “MATCH_PREFIX” (case-sensitive) for the Prefix method.
RCL supports specifying the path to a directory containing the set of security files for the exact node instance that needs to be launched. The set of files expected within that directory are the same as outlined in the “Directory tree of all security files” section above for individual node instance directories.
This can be specified by setting the
$ROS_SECURITY_NODE_DIRECTORY environment variable to point to the directory containing the security files.
Note that this setting takes precedence over
Nodes with the security features enabled will not communicate with nodes that don’t, but what should RCL do if one tries to launch a node that has no discernable keys/permissions/etc.? It has two options:
The type of mode desired can be specified by setting the
$ROS_SECURITY_STRATEGY environment variable to “Enforce” (case-sensitive) for strict mode, and anything else for permissive mode.
In addition to the supported features just discussed, RCL also supports a master shutoff for security features for easy experimentation. If it’s turned off (the default), none of the above security features will be enabled.
In order to enable SROS 2, set the
$ROS_SECURITY_ENABLE environment variable to “true” (case-sensitive).
To disable, set to any other value.
Configuring a ROS 2 system to be secure in RCL involves a lot of new technology (PKI, DDS governance and permissions files and their syntax, etc.).
If a user is comfortable with these technologies, the above information should be all that’s necessary to properly lock things down.
However, the SROS 2 CLI should include a tool
ros2 security to help those who don’t want to set it all up themselves, including the following capabilities: