Skip to content

Commit

Permalink
Enable use of Cyclone DDS security features
Browse files Browse the repository at this point in the history
Add utility function to insert security settings to the cyclone QOS
object used to create nodes.  Include a utility to find security
files and properly format their location to use with DDS.

Signed-off-by: Sid Faber <[email protected]>
  • Loading branch information
SidFaber committed Mar 20, 2020
1 parent 025762a commit 99d2738
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 4 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,5 @@ DDS directly instead of via the ROS2 abstraction.

## Known limitations

Cyclone DDS doesn't yet implement the DDS Security standard, nor does it fully implement
the Lifespan, Deadline and some of the Liveliness QoS modes. Consequently these features
of ROS2 are also not yet supported when using Cyclone DDS.
Cyclone DDS doesn't yet fully implement the Lifespan, Deadline and some of the Liveliness QoS modes.
Consequently these features of ROS2 are also not yet supported when using Cyclone DDS.
94 changes: 93 additions & 1 deletion rmw_cyclonedds_cpp/src/rmw_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
#include <utility>
#include <regex>

#include "rcutils/filesystem.h"
#include "rcutils/get_env.h"
#include "rcutils/logging_macros.h"
#include "rcutils/strdup.h"
#include "rcutils/format_string.h"

#include "rmw/allocators.h"
#include "rmw/convert_rcutils_ret_to_rmw_ret.h"
Expand Down Expand Up @@ -642,6 +644,80 @@ static std::string get_node_user_data(const char * node_name, const char * node_
std::string(";");
}

/* Returns the full URI of a security file properly formatted for DDS */
char * get_security_file_URI(
const char * security_filename, const char * node_secure_root,
const rcutils_allocator_t allocator)
{
char * ret;

char * file_path = rcutils_join_path(node_secure_root, security_filename, allocator);
if (file_path == nullptr) {
ret = nullptr;
} else if (!rcutils_is_readable(file_path)) {
RCUTILS_LOG_ERROR_NAMED(
"rmw_cyclonedds_cpp", "get_security_file: %s not found", file_path);
ret = nullptr;
allocator.deallocate(file_path, allocator.state);
} else {
/* Cyclone also supports a "data:" URI */
ret = rcutils_format_string(allocator, "file:%s", file_path);
allocator.deallocate(file_path, allocator.state);
}
return ret;
}

void store_security_filepath_in_qos(
dds_qos_t * qos, const char * qos_property_name, const char * file_name,
const rmw_node_security_options_t * security_options)
{
rcutils_allocator_t allocator = rcutils_get_default_allocator();

char * security_file_path = get_security_file_URI(
file_name, security_options->security_root_path, allocator);
if (security_file_path != nullptr) {
dds_qset_prop(qos, qos_property_name, security_file_path);
allocator.deallocate(security_file_path, allocator.state);
}
}

/* Set all the qos properties needed to enable DDS security */
void configure_qos_for_security(
dds_qos_t * qos, const rmw_node_security_options_t * security_options)
{
/* File path is set to nullptr if file does not exist or is not readable */
store_security_filepath_in_qos(
qos, "dds.sec.auth.identity_ca", "identity_ca.cert.pem",
security_options);
store_security_filepath_in_qos(
qos, "dds.sec.auth.identity_certificate", "cert.pem",
security_options);
store_security_filepath_in_qos(
qos, "dds.sec.auth.private_key", "key.pem",
security_options);
store_security_filepath_in_qos(
qos, "dds.sec.access.permissions_ca", "permissions_ca.cert.pem",
security_options);
store_security_filepath_in_qos(
qos, "dds.sec.access.governance", "governance.p7s",
security_options);
store_security_filepath_in_qos(
qos, "dds.sec.access.permissions", "permissions.p7s",
security_options);

dds_qset_prop(qos, "dds.sec.auth.library.path", "libdds_security_auth.so");
dds_qset_prop(qos, "dds.sec.auth.library.init", "init_authentication");
dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_authentication");

dds_qset_prop(qos, "dds.sec.crypto.library.path", "libdds_security_crypto.so");
dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_crypto");
dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_crypto");

dds_qset_prop(qos, "dds.sec.access.library.path", "libdds_security_ac.so");
dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control");
dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control");
}

extern "C" rmw_node_t * rmw_create_node(
rmw_context_t * context, const char * name,
const char * namespace_, size_t domain_id,
Expand All @@ -666,7 +742,13 @@ extern "C" rmw_node_t * rmw_create_node(
static_cast<void>(domain_id);
const dds_domainid_t did = DDS_DOMAIN_DEFAULT;
#endif
(void) security_options;

if (security_options == nullptr) {
RCUTILS_LOG_ERROR_NAMED(
"rmw_cyclonedds_cpp", "rmw_create_node: security options null");
return nullptr;
}

rmw_ret_t ret;
int dummy_validation_result;
size_t dummy_invalid_index;
Expand All @@ -688,8 +770,18 @@ extern "C" rmw_node_t * rmw_create_node(
#endif

dds_qos_t * qos = dds_create_qos();
if (qos == nullptr) {
RCUTILS_LOG_ERROR_NAMED(
"rmw_cyclonedds_cpp", "rmw_create_node: Unable to create qos");
return nullptr;
}
std::string user_data = get_node_user_data(name, namespace_);
dds_qset_userdata(qos, user_data.c_str(), user_data.size());

if (security_options->enforce_security) {
configure_qos_for_security(qos, security_options);
}

dds_entity_t pp = dds_create_participant(did, qos, nullptr);
dds_delete_qos(qos);
if (pp < 0) {
Expand Down

0 comments on commit 99d2738

Please sign in to comment.