We’re pleased to welcome the newest ROS 2 release, Foxy Fitzroy. A long-term support (LTS) release, (supported for three years), Foxy runs on the latest Ubuntu LTS, the also-recently-released Ubuntu 20.04 (supported for five years, or even longer with an ESM subscription).
Putting together a distribution like Foxy is a ton of work. Open Robotics, Canonical, and other members of the ROS 2 Technical Steering Committee would never be able to pull this off without the herculean effort from our awesome community, so thank you! If you’re interested in trying out ROS 2 Foxy on your Raspberry Pi now, check out our installation video:
New in ROS 2 Foxy
A lot of development happened for Foxy, not all of which was code. The set of tutorials was revamped, and a variety of performance improvements landed. Foxy also includes our own NoDL library for defining a static communication interface for nodes, which provides a way to infer the entire communication graph and automatically secure it and detect changes (more about that in a later article, stay tuned). Furthermore, it sees the addition of REP 2006, the ROS 2 Vulnerability Disclosure Policy, providing an easy way to report security vulnerabilities across the ROS 2 ecosystem.
These are all great developments, but my favorite new feature in Foxy is enhanced security monitoring. I might be slightly biased since we’re the ones who added it, but let me share the reasons why I feel this is such an important development for ROS.
Enhanced security monitoring
What do I mean by “enhanced security monitoring”? The robotics team at Canonical approaches monitoring within the context of Situational Awareness (SA). Mica Endsley published the commonly accepted definition of Situation(al) Awareness in 1995:
Situation awareness is the perception of the elements in the environment within a volume of time and space, the comprehension of their meaning, and the projection of their status in the near future.
Canonical’s Sid Faber wrote an article about this while he was at CERT, and he relies heavily on this image introduced by Dr. Endsly that still holds true:
That “near future” projection leads to decisions and actions to influence the environment, and we’re keen on using logs to recommend actions. Angela Horneman at CERT has a useful series on Situational Awareness that breaks this down into actionable components:
- Know what should be
- Track what is
- Infer when “should be” and “is” do not match
- Do something about the difference
This type of complex tracking and analysis doesn’t typically happen on your robot. Rather, it’s offloaded to a “Security Information and Event Management (SIEM)” system like Splunk, Nagios, Sentinel, or GuardDuty. The SIEM provides continuous log monitoring, and uses several different analysis methods to identify concerning activity (i.e. infer when “should be” and “is” don’t match).
Robotics situational awareness
So what does this look like in robotics? What is Robotics SA? Well… that’s not well defined, particularly if that robot builds on top of ROS. ROS provides a decent operational log capability (assuming nodes are properly configured to write to it), but security events are dumped into the same place as everything else in a way that makes it impossible to meaningfully extract. Much like a robot is only as good as its sensors, good situational awareness depends first and foremost on perception: effective logging of activity, both for operational as well as security needs. That is exactly what we at Canonical are taking steps to fix, with a lot of the work completed for Foxy.
The DDS-Security spec includes a security logging plugin, but DDS implementations aren’t required to provide it, which means that out of the three Tier 1 DDS implementations (Fast RTPS, RTI Connext, and Cyclone DDS), only one supports it: RTI Connext. Sadly, despite it being supported in Connext, ROS 2 itself didn’t support security logging, thus this feature wasn’t available to users of ROS 2. So we added that support to ROS 2. That wasn’t quite enough though: Connext isn’t the default DDS implementation– that’s Fast RTPS. So we added the security logging plugin to Fast RTPS, and added the ability to use it in ROS 2 as well.
Using these new features together means that you, dear user, can now extract security events from your ROS 2 system, getting you a huge step closer to proper SA. It means your ROS 2 system can log when a given node is behaving in a way you didn’t expect (e.g. is trying to communicate using an unexpected topic), or when an unauthenticated node is attempting to join a secured ROS 2 graph, and so on.
How do I use security logging in ROS 2?
Assuming you’re using one of the two DDS implementations that supports security logging (RTI Connext and Fast RTPS), you first need to enable ROS 2’s security features. After that, enabling the security log is a simple matter of defining a few environment variables:
ROS_SECURITY_LOG_FILE: Log security events to the specified file
ROS_SECURITY_LOG_PUBLISH: Log security events to DDS as outlined in the DDS-Security spec
ROS_SECURITY_LOG_VERBOSITY: Desired verbosity of the security log (one of “DEBUG”, “INFO”, “WARN”, “ERROR”, or “FATAL”)
Those variables take effect on all the nodes run when they’re defined. If you define them for a single
ros2 run invocation, they will only apply to that node. If you define them for a
ros2 launch invocation, they will apply to all nodes being launched.
Let’s walk through an example. You’ll need Foxy installed– to do that, you can either follow the video above, or follow the documentation.
Example of security logging
Make sure you install at least
ros-foxy-ros-base. Also install the demo nodes that we’ll use in a moment:
$ sudo apt install ros-foxy-demo-nodes-cpp
We’re going to use the SROS2 utilities to set up two different keystores (more information about this can be found in the SROS2 utilities guide):
$ mkdir ~/security_logging_demo $ cd ~/security_logging_demo $ ros2 security create_keystore keystore1 $ ros2 security create_keystore keystore2
Each of these keystores has a different certificate authority (CA). As a result, nodes with keys in one keystore will not be able to communicate with nodes with keys in the other keystore (since they’re signed by different CAs). Such a setup is of limited usefulness, but it’s considered a security issue, and logged as such, which is exactly what I’m trying to show here. We’ll be using the classic talker/listener example, so let’s create an identity (keypair) for the talker in one keystore, and an identity for the listener in the other:
$ ros2 security create_key keystore1 /talker_listener/listener $ ros2 security create_key keystore2 /talker_listener/talker
At this point we have two keystores, each with one identity created, for each party in our example. Open two terminals. In the first, activate keystore1 and run the listener:
$ export ROS_SECURITY_KEYSTORE=~/security_logging_demo/keystore1 $ export ROS_SECURITY_ENABLE=true $ export ROS_SECURITY_STRATEGY=Enforce $ ros2 run demo_nodes_cpp listener --ros-args --enclave /talker_listener/listener
In the second terminal, activate keystore2:
$ export ROS_SECURITY_KEYSTORE=~/security_logging_demo/keystore2 $ export ROS_SECURITY_ENABLE=true $ export ROS_SECURITY_STRATEGY=Enforce
Before we run the talker, we’ll set the environment variables to enable the security log, as well as set the verbosity to WARN:
$ export ROS_SECURITY_LOG_FILE=/tmp/ros-security.log $ export ROS_SECURITY_LOG_VERBOSITY=WARN
Finally, run the talker:
$ ros2 run demo_nodes_cpp talker --ros-args --enclave /talker_listener/talker
The first thing you’ll notice is that the talker appears to be working like normal, but the listener isn’t receiving anything. If you take a look at the security log file, you’ll see why:
$ cat /tmp/ros-security.log ... [1591814520.864581] [WARNING] 1.f.f7.e220.127.116.11.0.1.0.0.0|0.0.1.c1 0 PKIDH::begin_handshake_reply : Error verifying certificate
Because the talker can’t verify the listener’s identity, the handshake fails and the listener doesn’t get any messages. If you saw this in your SIEM you would know that what “is” wasn’t matching what “should be”: there’s either a misconfiguration, or someone unauthorised is poking at your robot.
Foxy is the first ROS release where extracting such events is easy. This feature is still in the early stages of development, and it will continue to see steady improvements (for example, we’d like to get it exposed in a way that is more well-defined than setting environment variables). Please give this a try and let us know what other improvements you’d like to see!