Skip to content

Commit aa23ecd

Browse files
Add zenoh_security_tools (#595) (#609)
* Added zenoh_security_configuration_tools package written in cpp Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com> * Added domain id Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com> * Update policy_parser to use nlohmann_json.hpp Since we have the dependency now via #583, this is a potential improvement to the current string concatenation. Signed-off-by: Michael Carroll <mjcarroll@intrinsic.ai> * Further json changes Signed-off-by: Michael Carroll <mjcarroll@intrinsic.ai> * Refactor package to zenoh_security_tools Signed-off-by: Yadunund <yadunund@gmail.com> * Inject certificates if enclaves provided Signed-off-by: Yadunund <yadunund@gmail.com> * Replace existing endpoints with tls instead of hardcoded changes Signed-off-by: Yadunund <yadunund@gmail.com> * Update README.md Signed-off-by: Yadunund <yadunund@gmail.com> * Also generate router config with security Signed-off-by: Yadunund <yadunund@gmail.com> * Drop CLI11 dependency Signed-off-by: Yadunund <yadunund@gmail.com> --------- Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com> Signed-off-by: Michael Carroll <mjcarroll@intrinsic.ai> Signed-off-by: Yadunund <yadunund@gmail.com> Co-authored-by: Alejandro Hernandez Cordero <ahcorde@gmail.com> Co-authored-by: Michael Carroll <mjcarroll@intrinsic.ai> (cherry picked from commit 1dca3c3) Co-authored-by: yadunund <yadunund@gmail.com>
1 parent be147e9 commit aa23ecd

File tree

8 files changed

+1138
-3
lines changed

8 files changed

+1138
-3
lines changed

.github/workflows/style.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ jobs:
1919
steps:
2020
- uses: actions/checkout@v4
2121
- name: uncrustify
22-
run: /ros_entrypoint.sh ament_uncrustify rmw_zenoh_cpp/
22+
run: /ros_entrypoint.sh ament_uncrustify rmw_zenoh_cpp/ zenoh_security_tools/
2323
- name: cpplint
24-
run: /ros_entrypoint.sh ament_cpplint rmw_zenoh_cpp/
24+
run: /ros_entrypoint.sh ament_cpplint rmw_zenoh_cpp/ zenoh_security_tools/

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ For example, if another `Zenoh router` is listening on IP address `192.168.1.1`
166166

167167
Then, start the `Zenoh router` after setting the `ZENOH_ROUTER_CONFIG_URI` environment variable to the absolute path of the modified config file.
168168

169+
### Security
170+
171+
Security is available in `rmw_zenoh` by means of access control, authentication and encryption.
172+
The [zenoh_security_tools](./zenoh_security_tools/) package contains a script to generate Zenoh configs with security configured along with documentation on its usage.
173+
169174
### Logging
170175

171176
The core of Zenoh is implemented in Rust and uses a logging library that can be configured via a `RUST_LOG` environment variable.
@@ -221,7 +226,7 @@ Note that composable nodes should *never* call `rclcpp::shutdown()`, as the comp
221226

222227
For more details, see https://github.com/ros2/rmw_zenoh/issues/170.
223228

224-
### rmw_zenoh is incompatible between Humble and newer distributions.
229+
### rmw_zenoh is incompatible between Humble and newer distributions.
225230

226231
Since Iron, ROS 2 introduced type hashes for messages and `rmw_zenoh` includes these type hashes in the Zenoh keyexpressions it constructs for data exchange. While participants will be discoverable, communication between Humble and newer distributions will fail, resulting in messages being silently dropped.
227232

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(zenoh_security_tools)
3+
4+
# Default to C++17
5+
if(NOT CMAKE_CXX_STANDARD)
6+
set(CMAKE_CXX_STANDARD 17)
7+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
8+
endif()
9+
10+
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
11+
add_compile_options(-Wall -Wextra -Wpedantic)
12+
endif()
13+
14+
# find dependencies
15+
find_package(ament_cmake REQUIRED)
16+
find_package(nlohmann_json REQUIRED)
17+
find_package(rcpputils REQUIRED)
18+
find_package(rcutils REQUIRED)
19+
# todo(Yadunund): Remove rmw dependency after https://github.com/ros2/rmw/pull/400 is merged.
20+
find_package(rmw REQUIRED)
21+
find_package(rmw_security_common REQUIRED)
22+
find_package(tinyxml2_vendor REQUIRED)
23+
find_package(TinyXML2 REQUIRED)
24+
find_package(zenoh_cpp_vendor REQUIRED)
25+
26+
add_executable(generate_configs
27+
src/main.cpp
28+
src/config_generator.cpp
29+
)
30+
target_link_libraries(generate_configs PRIVATE
31+
nlohmann_json::nlohmann_json
32+
rcpputils::rcpputils
33+
rcutils::rcutils
34+
rmw::rmw
35+
rmw_security_common::rmw_security_common_library
36+
tinyxml2::tinyxml2
37+
zenohcxx::zenohc
38+
)
39+
40+
if(BUILD_TESTING)
41+
find_package(ament_lint_auto REQUIRED)
42+
ament_lint_auto_find_test_dependencies()
43+
endif()
44+
45+
46+
install(
47+
TARGETS generate_configs
48+
DESTINATION lib/${PROJECT_NAME}
49+
)
50+
51+
ament_package()

zenoh_security_tools/README.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# zenoh_security_tools
2+
3+
The `zenoh_security_tools` package contains the `generate_configs` executable which generates Zenoh session config files with access control, authentication and encryption parameters based on policies and keystores generated using [sros2](https://github.com/ros2/sros2).
4+
5+
## Usage
6+
```bash
7+
ros2 run zenoh_security_tools generate_configs -h
8+
9+
Generate Zenoh session configs with security artifacts.
10+
11+
Options:
12+
-h,--help Print this help message and exit
13+
-p,--policy TEXT REQUIRED The path to the Access Control Policy file.
14+
-e,--enclaves TEXT The directory with the security enclaves for the various nodes in the policy file.
15+
-d,--ros-domain-id UINT REQUIRED The ROS Domain ID.
16+
-c,--session-config TEXT REQUIRED The path to the Zenoh session config file.
17+
-r,--router-config TEXT REQUIRED The path to the Zenoh router config file.
18+
19+
```
20+
21+
## Example of configuring security rmw_zenoh
22+
23+
The process of setting up security is very similar to [this tutorial](https://docs.ros.org/en/rolling/Tutorials/Advanced/Security/Introducing-ros2-security.html) but instead of relying on security environment variables and passing enclaves to nodes, we'll
24+
pass Zenoh session configs with the desired security parameters configured to `rmw_zenoh`.
25+
These modified session configs are generated using the tool above.
26+
27+
### Setup
28+
29+
The steps below will walk us through running rmw_zenoh with security enabled for a simple talker-lister system.
30+
31+
#### First create a directory for security artifacts and configs that will be generated.
32+
33+
```bash
34+
mkdir ~/sros2_demo
35+
```
36+
37+
#### Generate a keystore
38+
39+
```bash
40+
cd ~/sros2_demo
41+
ros2 security create_keystore demo_keystore
42+
```
43+
44+
#### Generate the certificates for authentication and encryption
45+
46+
Generate security files for the `talker` and `listener` nodes, and the `zenohd` router respectively.
47+
48+
```bash
49+
ros2 security create_enclave demo_keystore /talker_listener/talker
50+
ros2 security create_enclave demo_keystore /talker_listener/listener
51+
ros2 security create_enclave demo_keystore /talker_listener/zenohd
52+
```
53+
54+
#### Generate the policy.xml for access control
55+
56+
Launch zenohd
57+
```bash
58+
ros2 run rmw_zenoh_cpp rmw_zenohd
59+
```
60+
61+
Launch the listener
62+
```bash
63+
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
64+
ros2 run demo_nodes_cpp listener
65+
```
66+
67+
Launch the talker
68+
```bash
69+
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
70+
ros2 run demo_nodes_cpp talker
71+
```
72+
73+
Now run the policy generator from sros2
74+
75+
```bash
76+
ros2 security generate_policy policy_listener_talker.xml
77+
```
78+
79+
Finally, terminate all processes.
80+
81+
## Try access control
82+
83+
Generate security configs without enclaves (only access control).
84+
85+
```bash
86+
ros2 run zenoh_security_tools generate_configs \
87+
--policy policy_listener_talker.xml \
88+
--router-config <path to default router config>/DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5 \
89+
--session-config <path to default session config>/DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5 \
90+
--ros-domain-id 0
91+
```
92+
This will generate Zenoh session config files for each node in the `policy_listener_talker.xml` file.
93+
94+
#### Run the talker with the new config file
95+
96+
```bash
97+
export ZENOH_SESSION_CONFIG_URI=talker.json5
98+
ros2 run demo_nodes_cpp talker
99+
[INFO] [1740601932.350808475] [talker]: Publishing: 'Hello World: 1'
100+
[INFO] [1740601933.350487483] [talker]: Publishing: 'Hello World: 2'
101+
```
102+
103+
#### Run the listener with the new config file
104+
```bash
105+
export ZENOH_SESSION_CONFIG_URI=listener.json5
106+
ros2 run demo_nodes_cpp listener
107+
...
108+
[INFO] [1740602312.492840958] [listener]: I heard: [Hello World: 1]
109+
[INFO] [1740602313.492200366] [listener]: I heard: [Hello World: 2]
110+
```
111+
112+
You can validate access control by remapping the `/chatter` topic which should result in no messages being published.
113+
114+
115+
```bash
116+
export ZENOH_SESSION_CONFIG_URI=talker.json5
117+
ros2 rmw_zenoh_cpp rmw_zenohd
118+
```
119+
120+
```bash
121+
export ZENOH_SESSION_CONFIG_URI=talker.json5
122+
ros2 run demo_nodes_cpp talker --ros-args -r chatter:=new_topic
123+
```
124+
125+
```bash
126+
export ZENOH_SESSION_CONFIG_URI=listener.json5
127+
ros2 run demo_nodes_cpp listener --ros-args -r chatter:=new_topic
128+
...
129+
# listener should not receive anything
130+
```
131+
132+
## Try access control, authentication and encryption
133+
134+
This time we generate the configs with authentication and encryption configured using the enclaves generated by sros2.
135+
136+
```bash
137+
ros2 run zenoh_security_tools generate_configs \
138+
--policy policy_listener_talker.xml \
139+
--router-config <path to default router config>/DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5 \
140+
--session-config <path to default session config>/DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5 \
141+
--ros-domain-id 0
142+
--enclaves ~/sros2_demo/demo_keystore/enclaves/talker_listener
143+
```
144+
145+
> [!NOTE]
146+
The executable assumes that the `~/sros2_demo/demo_keystore/enclaves/talker_listener` directory contains folders with names matching node names defined in the `policy_listener_talker.xml` with the security files present.
147+
148+
Start the zenoh router with the `zenohd.json` config file.
149+
```bash
150+
export ZENOH_ROUTER_CONFIG_URI=zenohd.json5
151+
ros2 rmw_zenoh_cpp rmw_zenohd
152+
```
153+
154+
Start the talker
155+
156+
```bash
157+
export ZENOH_SESSION_CONFIG_URI=talker.json5
158+
ros2 rmw_zenoh_cpp rmw_zenohd
159+
```
160+
161+
Start the listener without setting the session config.
162+
```bash
163+
ros2 run demo_nodes_cpp listener
164+
```
165+
166+
The listener will not receive any messages.
167+
168+
Restart the listener with the session config.
169+
170+
```bash
171+
export ZENOH_SESSION_CONFIG_URI=listener.json5
172+
ros2 run demo_nodes_cpp listener
173+
...
174+
[INFO] [1740602312.492840958] [listener]: I heard: [Hello World: 10]
175+
[INFO] [1740602313.492200366] [listener]: I heard: [Hello World: 11]
176+
```
177+
178+
The messages are received by the listener.

zenoh_security_tools/package.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0"?>
2+
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
3+
<package format="3">
4+
<name>zenoh_security_tools</name>
5+
<version>0.5.0</version>
6+
<description>This package generates config files to enforce security with Zenoh</description>
7+
<maintainer email="alejandro@openrobotics.org">Alejandro Hernanadez</maintainer>
8+
<license>Apache License 2.0</license>
9+
10+
11+
<build_depend>nlohmann-json-dev</build_depend>
12+
13+
<depend>rcpputils</depend>
14+
<depend>rcutils</depend>
15+
<depend>rmw</depend>
16+
<depend>rmw_security_common</depend>
17+
<depend>tinyxml2_vendor</depend>
18+
<depend>zenoh_cpp_vendor</depend>
19+
20+
<test_depend>ament_lint_auto</test_depend>
21+
<test_depend>ament_lint_common</test_depend>
22+
23+
<export>
24+
<build_type>ament_cmake</build_type>
25+
</export>
26+
</package>

0 commit comments

Comments
 (0)