- Have ROS 2 installed, here assumed ROS Crystal located at
/opt/ros/crystal - ROS 2 development tools (
sudo apt install python3-colcon-common-extensions python3-rosdep)
export CONFBOT_WS=$HOME/confbot_ws
mkdir -p $CONFBOT_WS/src && cd $CONFBOT_WS && git clone https://github.com/Karsten1987/roscon2018 src/roscon2018cd $CONFBOT_WS
sed -i s@/Users/karsten/workspace/osrf/roscon2018_ws/@$CONFBOT_WS/@g `grep -lr "/karsten/" --exclude README.md`sudo rosdep init
rosdep update
rosdep install -y --from-paths src --ignore-src --rosdistro crystalsource /opt/ros/crystal/setup.bashcolcon build --merge-install --cmake-args --no-warn-unused-cli -DSECURITY=ONIn each terminal from now on, always assume use a sourced environment:
source $CONFBOT_WS/install/setup.bashTerminal 1:
ros2 launch confbot_bringup confbot_bringup.launch.pyTerminal 2:
$ ros2 node list
/launch_ros
/robot_state_publisher
/confbot_driver
/twist_publisher
/confbot_laser
/safe_zone_publisher$ ros2 topic list -t
/cmd_vel [geometry_msgs/Twist]
/confbot_laser/transition_event [lifecycle_msgs/TransitionEvent]
/danger_zone [visualization_msgs/Marker]
/joint_states [sensor_msgs/JointState]
/parameter_events [rcl_interfaces/ParameterEvent]
/robot_description [std_msgs/String]
/rosout [rcl_interfaces/Log]
/safe_zone [visualization_msgs/Marker]
/tf [tf2_msgs/TFMessage]
/tf_static [tf2_msgs/TFMessage]$ ros2 topic echo /cmd_vel
linear:
x: 0.10000000149011612
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.10000000149011612
linear:
x: 0.10000000149011612
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.10000000149011612
^CTerminal 2:
ros2 run rviz2 rviz2 -d `ros2 pkg prefix confbot_bringup --share`/config/confbot.rvizTerminal 3:
The node /twist_publisher has a speed parameter.
$ ros2 param set /twist_publisher speed 0.2
Set parameter successfulIn Terminal 1 we see:
[INFO] [twist_publisher]: set parameter 'speed' to "0.200000"In RViz: robot goes twice as fast
Terminal 3:
$ ros2 param get /twist_publisher speed
Double value is: 0.2
$ ros2 param set /twist_publisher speed 0.1
Set parameter successful
$ ros2 param get /twist_publisher speed
Double value is: 0.1
Temrinal 3:
$ ros2 lifecycle nodes
/confbot_laser$ ros2 lifecycle list /confbot_laser
- configure [1]
Start: unconfigured
Goal: configuring
- shutdown [5]
Start: unconfigured
Goal: shuttingdown$ ros2 lifecycle set /confbot_laser 1
Transitioning successful$ ros2 lifecycle list /confbot_laser
- cleanup [2]
Start: inactive
Goal: cleaningup
- activate [3]
Start: inactive
Goal: activating
- shutdown [6]
Start: inactive
Goal: shuttingdown$ ros2 lifecycle set /confbot_laser 3In RViz: the laser node is now publishing fake laser data!
Terminal 3: Tempering with the system:
ros2 topic pub /cmd_vel geometry_msgs/Twist "linear: {x: 0}" -r 100Robot stops moving
We will now use ROS2 Security to harden the system.
Prerequisite: Terminate all the running nodes by Ctrl+C them (Terminals 1, 2 and 3).
export ROS_SECURITY_ROOT_DIRECTORY=$CONFBOT_WS/confbot_keystore
cd $CONFBOT_WS
colcon build --merge-install --cmake-args -DSECURITY=ON -DPOLICY_FILE=$CONFBOT_WS/src/roscon2018/confbot_security/safe_zone_publisher_policies.xml --packages-select confbot_security --cmake-force-configureThe confbot_keystore directory content will look similar to:
/tmp/confbot_ws/confbot_keystore
├── 1000.pem
├── 1001.pem
├── 1002.pem
├── 1003.pem
├── 1004.pem
├── 1005.pem
├── 1006.pem
├── ca.cert.pem
├── ca_conf.cnf
├── ca.key.pem
├── confbot_driver
│ ├── cert.pem
│ ├── ecdsaparam
│ ├── governance.p7s
│ ├── identity_ca.cert.pem
│ ├── key.pem
│ ├── permissions_ca.cert.pem
│ ├── permissions.p7s
│ ├── permissions.xml
│ ├── req.pem
│ └── request.cnf
├── confbot_laser
│ ├── cert.pem
│ ├── ecdsaparam
│ ├── governance.p7s
│ ├── identity_ca.cert.pem
│ ├── key.pem
│ ├── permissions_ca.cert.pem
│ ├── permissions.p7s
│ ├── permissions.xml
│ ├── req.pem
│ └── request.cnf
├── ecdsaparam
├── governance.p7s
├── governance.xml
├── index.txt
├── index.txt.attr
├── index.txt.attr.old
├── index.txt.old
├── launch_ros
│ ├── cert.pem
│ ├── ecdsaparam
│ ├── governance.p7s
│ ├── identity_ca.cert.pem
│ ├── key.pem
│ ├── permissions_ca.cert.pem
│ ├── permissions.p7s
│ ├── permissions.xml
│ ├── req.pem
│ └── request.cnf
├── robot_state_publisher
│ ├── cert.pem
│ ├── ecdsaparam
│ ├── governance.p7s
│ ├── identity_ca.cert.pem
│ ├── key.pem
│ ├── permissions_ca.cert.pem
│ ├── permissions.p7s
│ ├── permissions.xml
│ ├── req.pem
│ └── request.cnf
├── rviz
│ ├── cert.pem
│ ├── ecdsaparam
│ ├── governance.p7s
│ ├── identity_ca.cert.pem
│ ├── key.pem
│ ├── permissions_ca.cert.pem
│ ├── permissions.p7s
│ ├── permissions.xml
│ ├── req.pem
│ └── request.cnf
├── safe_zone_publisher
│ ├── cert.pem
│ ├── ecdsaparam
│ ├── governance.p7s
│ ├── identity_ca.cert.pem
│ ├── key.pem
│ ├── permissions_ca.cert.pem
│ ├── permissions.p7s
│ ├── permissions.xml
│ ├── req.pem
│ └── request.cnf
├── serial
├── serial.old
└── twist_publisher
├── cert.pem
├── ecdsaparam
├── governance.p7s
├── identity_ca.cert.pem
├── key.pem
├── permissions_ca.cert.pem
├── permissions.p7s
├── permissions.xml
├── req.pem
└── request.cnfThis means only the following nodes have been allowed to be used in a secured environment:
- confbot_driver
- confbot_laser
- launch_ros
- robot_state_publisher
- rviz
- twist_publisher
- safe_zone_publisher
All terminals are assumed to have the environment setup and security environment variables set
source $CONFBOT_WS/install/setup.bash
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce
export ROS_SECURITY_ROOT_DIRECTORY=$CONFBOT_WS/confbot_keystoreTerminal 1: launch the system
ros2 launch confbot_bringup confbot_bringup_activated.launch.pyTerminal 2: visualize the system
ros2 run rviz2 rviz2 -d `ros2 pkg prefix confbot_bringup --share`/config/confbot.rvizIn RViz we will see the robot with the laser points but no sharks.
$ ros2 topic pub /cmd_vel geometry_msgs/Twist "linear: {x: 0}" -r 100
Unknown error creating node: SECURITY ERROR: unable to find a folder matching the node name in the "ROS_SECURITY_NODE_DIRECTORY" or "ROS_SECURITY_ROOT_DIRECTORY" directories while the requested security strategy requires it, at /tmp/binarydeb/ros-crystal-rcl-0.6.5/src/rcl/node.c:391This fails because the node used by ros2 topic has not been allowed to join the secured network
$ ros2 run confbot_driver twist_publisher __node:=my_hacky_node
terminate called after throwing an instance of 'rclcpp::exceptions::RCLError'
what(): failed to initialize rcl node: SECURITY ERROR: unable to find a folder matching the node name in the "ROS_SECURITY_NODE_DIRECTORY" or "ROS_SECURITY_ROOT_DIRECTORY" directories while the requested security strategy requires it, at /tmp/binarydeb/ros-crystal-rcl-0.6.5/src/rcl/node.c:391This fails because, while the node /twist_publisher is allowed to join the network, the node /my_hacky_node is not.
Let's now see how to specify what actions a given node is allowed to perform.
Here we will look at the /safe_zone_publisher node's permissions.
This node's sole function is to publish the safe zone where the robot is operating (green zone in RViz) and the danger zone (red shark).
Let's have a look at the safe_zone_publisher_policies.xml file
cat $CONFBOT_WS/src/roscon2018/confbot_security/safe_zone_publisher_policies.xml
Imagine an attacker is able to inject code into our /safe_zone_publisher node to make it send velocity commands to the robot.
cd $CONFBOT_WS/src/roscon2018/confbot_tools/confbot_tools
cp safe_zone_publisher_hacked.py safe_zone_publisher.py
git diff safe_zone_publisher.pyLet's try to run this compromised node:
$ python3 safe_zone_publisher.py
2019-03-26 15:53:06.721 [SECURITY Error] Error checking creation of local writer d0.9b.b9.b.37.3.bc.cc.79.5c.ec.3a|0.0.10.3 (rt/cmd_vel topic not found in allow rule. (/tmp/binarydeb/ros-crystal-fastrtps-1.7.0/src/cpp/security/accesscontrol/Permissions.cpp:1111))Here it fails with rt/cmd_vel topic not found in allow rule. meaning that the not is not allowed to publish on the ROS topic /cmd_vel.




