Skip to content

Commit

Permalink
Add basic support for security logging plugin
Browse files Browse the repository at this point in the history
Support setting the security logging properties in Fast RTPS by exposing
three environment variables:

- `ROS_SECURITY_LOG_FILE`: Log security events to the provided file path
- `ROS_SECURITY_LOG_PUBLISH`: Publish security events to DDS topic
- `ROS_SECURITY_LOG_VERBOSITY`: Control verbosity of logged events

Signed-off-by: Kyle Fazzari <kyle@canonical.com>
  • Loading branch information
kyrofa committed Apr 7, 2020
1 parent 48b403a commit 7e7c4cb
Show file tree
Hide file tree
Showing 6 changed files with 472 additions and 0 deletions.
1 change: 1 addition & 0 deletions rmw_fastrtps_shared_cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ add_library(rmw_fastrtps_shared_cpp
src/rmw_publisher.cpp
src/rmw_request.cpp
src/rmw_response.cpp
src/rmw_security_logging.cpp
src/rmw_service.cpp
src/rmw_service_names_and_types.cpp
src/rmw_service_server_is_available.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2020 Canonical Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RMW_FASTRTPS_SHARED_CPP__RMW_SECURITY_LOGGING_HPP_
#define RMW_FASTRTPS_SHARED_CPP__RMW_SECURITY_LOGGING_HPP_

#include "fastrtps/rtps/attributes/PropertyPolicy.h"

bool apply_security_logging_configuration(eprosima::fastrtps::rtps::PropertyPolicy & policy);

#endif // RMW_FASTRTPS_SHARED_CPP__RMW_SECURITY_LOGGING_HPP_
5 changes: 5 additions & 0 deletions rmw_fastrtps_shared_cpp/src/participant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "rmw_fastrtps_shared_cpp/custom_participant_info.hpp"
#include "rmw_fastrtps_shared_cpp/participant.hpp"
#include "rmw_fastrtps_shared_cpp/rmw_common.hpp"
#include "rmw_fastrtps_shared_cpp/rmw_security_logging.hpp"

using Domain = eprosima::fastrtps::Domain;
using IPLocator = eprosima::fastrtps::rtps::IPLocator;
Expand Down Expand Up @@ -230,6 +231,10 @@ rmw_fastrtps_shared_cpp::create_participant(
Property(
"dds.sec.access.builtin.Access-Permissions.permissions", security_files_paths[5]));

if (!apply_security_logging_configuration(property_policy)) {
return nullptr;
}

participantAttrs.rtps.properties = property_policy;
} else if (security_options->enforce_security) {
RMW_SET_ERROR_MSG("couldn't find all security files!");
Expand Down
180 changes: 180 additions & 0 deletions rmw_fastrtps_shared_cpp/src/rmw_security_logging.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright 2020 Canonical Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <tinyxml2.h>

#include <utility>
#include <string>
#include <map>

#include "fastrtps/config.h"
#include "rcutils/filesystem.h"
#include "rcutils/get_env.h"
#include "rmw/error_handling.h"
#include "rmw/qos_profiles.h"
#include "rmw/types.h"

#include "rmw_fastrtps_shared_cpp/rmw_security_logging.hpp"

#if HAVE_SECURITY

namespace
{
// Environment variable names
const char log_file_variable_name[] = "ROS_SECURITY_LOG_FILE";
const char log_publish_variable_name[] = "ROS_SECURITY_LOG_PUBLISH";
const char log_verbosity_variable_name[] = "ROS_SECURITY_LOG_VERBOSITY";

// Logging properties
const char logging_plugin_property_name[] = "dds.sec.log.plugin";
const char log_file_property_name[] = "dds.sec.log.builtin.DDS_LogTopic.log_file";
const char verbosity_property_name[] = "dds.sec.log.builtin.DDS_LogTopic.logging_level";
const char distribute_enable_property_name[] =
"dds.sec.log.builtin.DDS_LogTopic.distribute";

const std::map<std::string, std::string> supported_verbosities {
{"EMERGENCY", "EMERGENCY_LEVEL"},
{"ALERT", "ALERT_LEVEL"},
{"CRITICAL", "CRITICAL_LEVEL"},
{"ERROR", "ERROR_LEVEL"},
{"WARNING", "WARNING_LEVEL"},
{"NOTICE", "NOTICE_LEVEL"},
{"INFORMATIONAL", "INFORMATIONAL_LEVEL"},
{"DEBUG", "DEBUG_LEVEL"},
};

struct security_files_t
{
std::string identity_ca_cert_path;
std::string permissions_ca_cert_path;
std::string governance_path;
std::string cert_path;
std::string key_path;
std::string permissions_path;
};

bool string_to_verbosity(const std::string & str, std::string & verbosity)
{
try {
verbosity = supported_verbosities.at(str);
} catch (std::out_of_range &) {
return false;
}

return true;
}

void add_property(
eprosima::fastrtps::rtps::PropertySeq & properties,
eprosima::fastrtps::rtps::Property && property)
{
// Add property to vector. If property already exists, overwrite it.
std::string property_name = property.name();
for (auto & existing_property : properties) {
if (existing_property.name() == property_name) {
existing_property = property;
return;
}
}

properties.push_back(property);
}

bool get_env(const std::string & variable_name, std::string & variable_value)
{
const char * value;
const char * error_message = rcutils_get_env(variable_name.c_str(), &value);
if (error_message != NULL) {
RMW_SET_ERROR_MSG_WITH_FORMAT_STRING(
"unable to get %s environment variable: %s",
variable_name,
error_message);
return false;
}

variable_value = std::string(value);

return true;
}
} // namespace

#endif

bool apply_security_logging_configuration(eprosima::fastrtps::rtps::PropertyPolicy & policy)
{
#if HAVE_SECURITY
eprosima::fastrtps::rtps::PropertySeq properties;
std::string env_value;

// Handle logging to file
if (!get_env(log_file_variable_name, env_value)) {
return false;
}
if (!env_value.empty()) {
add_property(
properties,
eprosima::fastrtps::rtps::Property(
log_file_property_name, env_value.c_str()));
}

// Handle log distribution over DDS
if (!get_env(log_publish_variable_name, env_value)) {
return false;
}
if (!env_value.empty()) {
add_property(
properties,
eprosima::fastrtps::rtps::Property(
distribute_enable_property_name, env_value.c_str()));
}

// Handle log verbosity
if (!get_env(log_verbosity_variable_name, env_value)) {
return false;
}
if (!env_value.empty()) {
std::string verbosity;
if (!string_to_verbosity(env_value, verbosity)) {
RMW_SET_ERROR_MSG_WITH_FORMAT_STRING(
"failed to set security logging verbosity: %s is not a supported verbosity",
env_value.c_str());
return false;
}

add_property(
properties,
eprosima::fastrtps::rtps::Property(verbosity_property_name, verbosity.c_str()));
}

if (!properties.empty()) {
add_property(
properties,
eprosima::fastrtps::rtps::Property(
logging_plugin_property_name,
"builtin.DDS_LogTopic"));
}

// Now that we're done parsing, actually update the properties
for (auto & item : properties) {
add_property(policy.properties(), std::move(item));
}

return true;
#else
RMW_SET_ERROR_MSG(
"This Fast-RTPS version doesn't have the security libraries\n"
"Please compile Fast-RTPS using the -DSECURITY=ON CMake option");
return false;
#endif
}
6 changes: 6 additions & 0 deletions rmw_fastrtps_shared_cpp/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ if(TARGET test_dds_attributes_to_rmw_qos)
ament_target_dependencies(test_dds_attributes_to_rmw_qos)
target_link_libraries(test_dds_attributes_to_rmw_qos ${PROJECT_NAME})
endif()

ament_add_gmock(test_security_logging test_security_logging.cpp)
if(TARGET test_security_logging)
ament_target_dependencies(test_security_logging)
target_link_libraries(test_security_logging ${PROJECT_NAME})
endif()
Loading

0 comments on commit 7e7c4cb

Please sign in to comment.