├── src ├── runner │ ├── README.md │ ├── main.cpp │ ├── runner.hpp │ └── runner.cpp ├── attacks │ ├── noop │ │ ├── README.md │ │ └── component.cpp │ ├── resources │ │ ├── disk │ │ │ ├── README.md │ │ │ └── component.cpp │ │ ├── memory │ │ │ ├── README.md │ │ │ └── component.cpp │ │ └── cpu │ │ │ ├── test_results.png │ │ │ ├── README.md │ │ │ └── component.cpp │ ├── factory_utils.cpp │ └── periodic_attack_component.cpp └── utilities │ ├── service_utils.hpp │ ├── service_utils.cpp │ ├── client_utils.hpp │ ├── client_utils.hxx │ ├── lifecycle_service_client.cpp │ └── lifecycle_service_client.hpp ├── NOTICE ├── examples └── params.yaml ├── .github └── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md ├── include └── ros_sec_test │ └── attacks │ ├── factory_utils.hpp │ ├── resources │ ├── disk │ │ └── component.hpp │ ├── cpu │ │ └── component.hpp │ └── memory │ │ └── component.hpp │ ├── noop │ └── component.hpp │ └── periodic_attack_component.hpp ├── test ├── ros_sec_test │ ├── utilities │ │ ├── test_service_utils.cpp │ │ └── test_client_utils.cpp │ ├── runner │ │ └── test_runner.cpp │ └── attacks │ │ ├── noop │ │ └── test_component.cpp │ │ └── resources │ │ ├── cpu │ │ └── test_component.cpp │ │ ├── disk │ │ └── test_component.cpp │ │ └── memory │ │ └── test_component.cpp ├── include │ └── test_utilities │ │ ├── periodic_attack_component_mock.hpp │ │ └── utility_fixtures.hpp └── test_utilities │ └── utility_fixtures.cpp ├── package.xml ├── README.md ├── CONTRIBUTING.md ├── CMakeLists.txt └── LICENSE /src/runner/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/attacks/noop/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/attacks/resources/disk/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/attacks/resources/memory/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | ROS2 SecTest 2 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | -------------------------------------------------------------------------------- /examples/params.yaml: -------------------------------------------------------------------------------- 1 | attacker_node: 2 | ros__parameters: 3 | attack_nodes: 4 | - 'noop' 5 | attack_duration: 1 6 | -------------------------------------------------------------------------------- /src/attacks/resources/cpu/test_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-robotics/ROS2-SecTest/HEAD/src/attacks/resources/cpu/test_results.png -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /src/attacks/resources/cpu/README.md: -------------------------------------------------------------------------------- 1 | # CPU Abuse Attack 2 | This attack demonstrates a node that consumes all of the compute resources. 3 | 4 | Attack node name: `resources_cpu` 5 | 6 | 7 | ## Validation 8 | This validation was run on an a1.xlarge EC2 instance with 4vCPUs and 8GB of memory running Ubuntu18.04. 9 | 10 | 11 | Setup the ApexAI performance testing tool, available [here](https://github.com/ApexAI/performance_test). 12 | 13 | Run with 14 | ``` 15 | ros2 run performance_test perf_test -c ROS2 -l log -t Array2m -r 0 --max_runtime 200 16 | ``` 17 | 18 | Launch the attack: 19 | ``` 20 | ros2 run ros_sec_test ros_sec_test __params:= 21 | ``` 22 | 23 | This leads to a graph like below: 24 | ![](./test_results.png) 25 | 26 | The attack is launched 25 seconds into the experiment and spawns threads until 100% cpu is consumed. 27 | The latency increases from about 24 ms up to a peak around 70 ms before the attack ends and the 28 | latency returns to normal. 29 | 30 | 31 | ## Mitigation 32 | TODO 33 | -------------------------------------------------------------------------------- /src/runner/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | #include 16 | 17 | #include "rclcpp/utilities.hpp" 18 | #include "runner/runner.hpp" 19 | 20 | using ros_sec_test::runner::Runner; 21 | 22 | int main(int argc, char * argv[]) 23 | { 24 | setvbuf(stdout, NULL, _IONBF, BUFSIZ); // Force flush of the stdout buffer. 25 | rclcpp::init(argc, argv); 26 | Runner runner; 27 | runner.spin(); 28 | rclcpp::shutdown(); 29 | return EXIT_SUCCESS; 30 | } 31 | -------------------------------------------------------------------------------- /include/ros_sec_test/attacks/factory_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef ROS_SEC_TEST__ATTACKS__FACTORY_UTILS_HPP_ 15 | #define ROS_SEC_TEST__ATTACKS__FACTORY_UTILS_HPP_ 16 | #include 17 | 18 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 19 | 20 | namespace ros_sec_test 21 | { 22 | namespace attacks 23 | { 24 | 25 | /// Instantiates a lifecycle attack node based on its name. 26 | rclcpp_lifecycle::LifecycleNode::SharedPtr build_attack_node_from_name( 27 | const std::string & attack_node_name); 28 | 29 | } // namespace attacks 30 | } // namespace ros_sec_test 31 | 32 | #endif // ROS_SEC_TEST__ATTACKS__FACTORY_UTILS_HPP_ 33 | -------------------------------------------------------------------------------- /src/utilities/service_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef UTILITIES__SERVICE_UTILS_HPP_ 15 | #define UTILITIES__SERVICE_UTILS_HPP_ 16 | 17 | #include 18 | 19 | namespace ros_sec_test 20 | { 21 | namespace utilities 22 | { 23 | 24 | /// Build change_state service name given a particular target node. 25 | std::string build_change_state_service_name(const std::string & target_node_name); 26 | 27 | /// Build get_state service name given a particular target node. 28 | std::string build_get_state_service_name(const std::string & target_node_name); 29 | 30 | } // namespace utilities 31 | } // namespace ros_sec_test 32 | 33 | #endif // UTILITIES__SERVICE_UTILS_HPP_ 34 | -------------------------------------------------------------------------------- /test/ros_sec_test/utilities/test_service_utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | 16 | #include 17 | 18 | #include "utilities/service_utils.hpp" 19 | 20 | using ros_sec_test::utilities::build_change_state_service_name; 21 | using ros_sec_test::utilities::build_get_state_service_name; 22 | 23 | TEST(build_change_state_service_name, non_empty) { 24 | EXPECT_NE(build_change_state_service_name("node"), ""); 25 | } 26 | 27 | TEST(build_get_state_service_name, non_empty) { 28 | EXPECT_NE(build_get_state_service_name("node"), ""); 29 | } 30 | 31 | int main(int argc, char ** argv) 32 | { 33 | ::testing::InitGoogleTest(&argc, argv); 34 | return RUN_ALL_TESTS(); 35 | } 36 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ros_sec_test 5 | 0.0.1 6 | Package for executing attacks against a ROS systems 7 | AWS RoboMaker 8 | Apache License 2.0 9 | 10 | ament_cmake 11 | 12 | class_loader 13 | lifecycle_msgs 14 | rclcpp 15 | rclcpp_components 16 | rclcpp_lifecycle 17 | rcutils 18 | 19 | class_loader 20 | lifecycle_msgs 21 | rclcpp 22 | rclcpp_lifecycle 23 | rcutils 24 | ros2run 25 | 26 | ament_cmake_gmock 27 | ament_cmake_gtest 28 | ament_lint_auto 29 | ament_lint_common 30 | 31 | 32 | ament_cmake 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/utilities/service_utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "utilities/service_utils.hpp" 15 | 16 | #include 17 | #include 18 | 19 | static std::string build_service_name( 20 | const std::string & target_node_name, 21 | const std::string & topic_name) 22 | { 23 | std::ostringstream ss; 24 | ss << "/"; 25 | ss << target_node_name; 26 | ss << "/"; 27 | ss << topic_name; 28 | return ss.str(); 29 | } 30 | 31 | namespace ros_sec_test 32 | { 33 | namespace utilities 34 | { 35 | 36 | std::string build_change_state_service_name(const std::string & target_node_name) 37 | { 38 | return build_service_name(target_node_name, "change_state"); 39 | } 40 | 41 | std::string build_get_state_service_name(const std::string & target_node_name) 42 | { 43 | return build_service_name(target_node_name, "get_state"); 44 | } 45 | 46 | } // namespace utilities 47 | } // namespace ros_sec_test 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ROS2 SecTest 2 | 3 | **This code is experimental and uses features from ROS2 D** 4 | 5 | ROS2 has minimal security or limitations on node permissions by default. This package is meant 6 | to demonstrate ways a malicious or misconfigured node could harm the operations of a ROS2 system 7 | and demonstrate mitigations for those "attacks". 8 | The initial attacks come from the 9 | [ROS2 Threat Model](http://design.ros2.org/articles/ros2_threat_model.html). 10 | 11 | More details can be found in the design doc in this [PR](https://github.com/ros2/design/pull/235). 12 | 13 | 14 | 15 | ## Example Noop Attack 16 | To run the demo: 17 | Create a ROS2 workspace 18 | ```bash 19 | mkdir -p security_ws/src 20 | cd security_ws 21 | ``` 22 | 23 | Clone the repository 24 | 25 | ```bash 26 | cd src 27 | git clone https://github.com/aws-robotics/ROS2-SecTest 28 | cd .. 29 | ``` 30 | 31 | Install dependencies and build 32 | ```bash 33 | rosdep install --from-paths src --ignore-src -r -y 34 | colcon build 35 | source install/local_setup.sh 36 | ``` 37 | 38 | Run the noop demo 39 | ```bash 40 | ros2 run ros_sec_test ros_sec_test __params:=`ros2 pkg prefix ros_sec_test`/share/ros_sec_test/examples/params.yaml 41 | ``` 42 | 43 | You should see something like the following output which demonstrates that 44 | the Noop node was configured and activated. 45 | ``` 46 | [INFO] [Runner]: Initializing Runner 47 | [INFO] [Runner]: Adding attack node 'noop' 48 | [INFO] [Runner]: Spinning started 49 | [INFO] [Runner]: Configuring attack node 'noop' 50 | [INFO] [noop]: on_configure() is called. 51 | [INFO] [Runner]: Enabling attack node 'noop' 52 | [INFO] [noop]: on_activate() is called. 53 | [INFO] [Runner]: Shutting-down attack node 'noop' 54 | [INFO] [noop]: on_deactivate() is called. 55 | [INFO] [Runner]: Spinning finished 56 | ``` 57 | 58 | To enable or disable attacks, you can create you own params.yaml. 59 | 60 | ## License 61 | 62 | This library is licensed under the Apache 2.0 License. 63 | -------------------------------------------------------------------------------- /test/include/test_utilities/periodic_attack_component_mock.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef TEST_UTILITIES__PERIODIC_ATTACK_COMPONENT_MOCK_HPP_ 15 | #define TEST_UTILITIES__PERIODIC_ATTACK_COMPONENT_MOCK_HPP_ 16 | #include 17 | 18 | #include "gmock/gmock.h" 19 | 20 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 21 | 22 | #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" 23 | #include "rclcpp_lifecycle/state.hpp" 24 | 25 | 26 | using PeriodicAttackComponent = ros_sec_test::attacks::PeriodicAttackComponent; 27 | using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; 28 | 29 | class MockPeriodicAttackComponent : public PeriodicAttackComponent 30 | { 31 | public: 32 | explicit MockPeriodicAttackComponent(std::string node_name) 33 | : PeriodicAttackComponent(node_name) {} 34 | MOCK_METHOD1(on_configure, CallbackReturn(const rclcpp_lifecycle::State &)); 35 | MOCK_METHOD1(on_activate, CallbackReturn(const rclcpp_lifecycle::State &)); 36 | MOCK_METHOD1(on_deactivate, CallbackReturn(const rclcpp_lifecycle::State &)); 37 | MOCK_METHOD1(on_cleanup, CallbackReturn(const rclcpp_lifecycle::State &)); 38 | MOCK_METHOD1(on_shutdown, CallbackReturn(const rclcpp_lifecycle::State &)); 39 | }; 40 | 41 | #endif // TEST_UTILITIES__PERIODIC_ATTACK_COMPONENT_MOCK_HPP_ 42 | -------------------------------------------------------------------------------- /test/include/test_utilities/utility_fixtures.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef TEST_UTILITIES__UTILITY_FIXTURES_HPP_ 16 | #define TEST_UTILITIES__UTILITY_FIXTURES_HPP_ 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "rclcpp/executors/single_threaded_executor.hpp" 24 | #include "rclcpp/node.hpp" 25 | 26 | namespace ros_sec_test 27 | { 28 | namespace test 29 | { 30 | namespace test_utilities 31 | { 32 | 33 | class ROSTestingFixture : public ::testing::Test 34 | { 35 | public: 36 | ROSTestingFixture() 37 | { 38 | rclcpp::init(0, nullptr); 39 | } 40 | 41 | ~ROSTestingFixture() 42 | { 43 | rclcpp::shutdown(); 44 | } 45 | }; 46 | 47 | 48 | class NodeConfigurationFixture : public ROSTestingFixture 49 | { 50 | protected: 51 | rclcpp::executors::SingleThreadedExecutor executor_; 52 | rclcpp::Node::SharedPtr node_; 53 | std::promise thread_promise_; 54 | std::shared_future future_; 55 | 56 | public: 57 | void SetUp() override; 58 | void add_node_to_executor(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node); 59 | void spin_executor_until(std::shared_future & future); 60 | void start_executor(); 61 | void stop_executor(); 62 | void TearDown() override; 63 | }; 64 | } // namespace test_utilities 65 | } // namespace test 66 | } // namespace ros_sec_test 67 | #endif // TEST_UTILITIES__UTILITY_FIXTURES_HPP_ 68 | -------------------------------------------------------------------------------- /test/test_utilities/utility_fixtures.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "test_utilities/utility_fixtures.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "rclcpp/executors/single_threaded_executor.hpp" 21 | #include "rclcpp/node.hpp" 22 | 23 | namespace ros_sec_test 24 | { 25 | namespace test 26 | { 27 | namespace test_utilities 28 | { 29 | 30 | void NodeConfigurationFixture::SetUp() 31 | { 32 | node_ = rclcpp::Node::make_shared("test_node"); 33 | executor_.add_node(node_); 34 | future_ = thread_promise_.get_future(); 35 | } 36 | 37 | void NodeConfigurationFixture::add_node_to_executor( 38 | rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node) 39 | { 40 | executor_.add_node(node); 41 | } 42 | 43 | void NodeConfigurationFixture::spin_executor_until(std::shared_future & future) 44 | { 45 | using namespace std::chrono_literals; 46 | std::thread thread_spin([this, &future]() { 47 | RCLCPP_INFO(this->node_->get_logger(), "Spin thread started."); 48 | this->executor_.spin_until_future_complete(future, 100ms); 49 | RCLCPP_INFO(this->node_->get_logger(), "Spin thread ended."); 50 | }); 51 | thread_spin.join(); 52 | } 53 | void NodeConfigurationFixture::start_executor() 54 | { 55 | spin_executor_until(future_); 56 | } 57 | void NodeConfigurationFixture::stop_executor() 58 | { 59 | thread_promise_.set_value(); 60 | } 61 | 62 | void NodeConfigurationFixture::TearDown() 63 | { 64 | stop_executor(); 65 | } 66 | } // namespace test_utilities 67 | } // namespace test 68 | } // namespace ros_sec_test 69 | -------------------------------------------------------------------------------- /include/ros_sec_test/attacks/resources/disk/component.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef ROS_SEC_TEST__ATTACKS__RESOURCES__DISK__COMPONENT_HPP_ 15 | #define ROS_SEC_TEST__ATTACKS__RESOURCES__DISK__COMPONENT_HPP_ 16 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 17 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 18 | #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" 19 | #include "rclcpp_lifecycle/state.hpp" 20 | 21 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 22 | 23 | namespace ros_sec_test 24 | { 25 | namespace attacks 26 | { 27 | namespace resources 28 | { 29 | namespace disk 30 | { 31 | 32 | /// This attack tries to fill the local disk with data. 33 | /** 34 | * WARNING: this attack will try to fill your disk completely! 35 | * 36 | * The attack will slowly grow a single file by chunk of 100 MiB until 37 | * the disk is full. 38 | * 39 | * When the node shutdowns, the node will attempt to delete the created 40 | * file to restore the system to its initial state. 41 | */ 42 | class Component : public ros_sec_test::attacks::PeriodicAttackComponent 43 | { 44 | public: 45 | Component(); 46 | Component(const Component &) = delete; 47 | Component & operator=(const Component &) = delete; 48 | 49 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 50 | on_activate(const rclcpp_lifecycle::State & /* state */) final; 51 | 52 | private: 53 | /// Grow the file size by 100MiB. 54 | void run_periodic_attack() final; 55 | 56 | /// File descriptor to the large file this attack tries to allocate. 57 | int fd_; 58 | }; 59 | 60 | } // namespace disk 61 | } // namespace resources 62 | } // namespace attacks 63 | } // namespace ros_sec_test 64 | 65 | #endif // ROS_SEC_TEST__ATTACKS__RESOURCES__DISK__COMPONENT_HPP_ 66 | -------------------------------------------------------------------------------- /include/ros_sec_test/attacks/noop/component.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef ROS_SEC_TEST__ATTACKS__NOOP__COMPONENT_HPP_ 15 | #define ROS_SEC_TEST__ATTACKS__NOOP__COMPONENT_HPP_ 16 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 17 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 18 | #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" 19 | #include "rclcpp_lifecycle/state.hpp" 20 | 21 | namespace ros_sec_test 22 | { 23 | namespace attacks 24 | { 25 | namespace noop 26 | { 27 | 28 | /// Attack node which does not do anything for testing purposes. 29 | /** 30 | * If you would like to create your own attack, forking this no-op node 31 | * is a good strategy. 32 | */ 33 | class Component : public rclcpp_lifecycle::LifecycleNode 34 | { 35 | public: 36 | Component(); 37 | Component(const Component &) = delete; 38 | Component & operator=(const Component &) = delete; 39 | 40 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 41 | on_configure(const rclcpp_lifecycle::State & /* state */) final; 42 | 43 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 44 | on_activate(const rclcpp_lifecycle::State & /* state */) final; 45 | 46 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 47 | on_deactivate(const rclcpp_lifecycle::State & /* state */) final; 48 | 49 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 50 | on_cleanup(const rclcpp_lifecycle::State & /* state */) final; 51 | 52 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 53 | on_shutdown(const rclcpp_lifecycle::State & /* state */ state) final; 54 | }; 55 | 56 | 57 | } // namespace noop 58 | } // namespace attacks 59 | } // namespace ros_sec_test 60 | 61 | #endif // ROS_SEC_TEST__ATTACKS__NOOP__COMPONENT_HPP_ 62 | -------------------------------------------------------------------------------- /src/attacks/factory_utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "ros_sec_test/attacks/factory_utils.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "ros_sec_test/attacks/noop/component.hpp" 22 | #include "ros_sec_test/attacks/resources/cpu/component.hpp" 23 | #include "ros_sec_test/attacks/resources/disk/component.hpp" 24 | #include "ros_sec_test/attacks/resources/memory/component.hpp" 25 | 26 | using LifecycleNodeShPtr = std::shared_ptr; 27 | using LifecycleNodeConstructorCallback = std::function; 28 | 29 | using CPUNode = ros_sec_test::attacks::resources::cpu::Component; 30 | using DiskNode = ros_sec_test::attacks::resources::disk::Component; 31 | using MemoryNode = ros_sec_test::attacks::resources::memory::Component; 32 | using NoopNode = ros_sec_test::attacks::noop::Component; 33 | 34 | static const std::map 35 | kNodeNameToFactoryCallback = { 36 | {"noop", []() -> LifecycleNodeShPtr {return std::make_shared();}}, 37 | {"resources_disk", []() -> LifecycleNodeShPtr {return std::make_shared();}}, 38 | {"resources_cpu", []() -> LifecycleNodeShPtr {return std::make_shared();}}, 39 | {"resources_memory", []() -> LifecycleNodeShPtr {return std::make_shared();}}, 40 | }; 41 | 42 | namespace ros_sec_test 43 | { 44 | namespace attacks 45 | { 46 | 47 | rclcpp_lifecycle::LifecycleNode::SharedPtr build_attack_node_from_name( 48 | const std::string & attack_node_name) 49 | { 50 | const auto it = kNodeNameToFactoryCallback.find(attack_node_name); 51 | if (it != kNodeNameToFactoryCallback.end()) { 52 | return it->second(); 53 | } 54 | return rclcpp_lifecycle::LifecycleNode::SharedPtr(); 55 | } 56 | 57 | } // namespace attacks 58 | } // namespace ros_sec_test 59 | -------------------------------------------------------------------------------- /test/ros_sec_test/runner/test_runner.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 23 | 24 | #include "runner/runner.hpp" 25 | #include "test_utilities/utility_fixtures.hpp" 26 | #include "test_utilities/periodic_attack_component_mock.hpp" 27 | 28 | using LifecycleNodeShPtr = std::shared_ptr; 29 | using ros_sec_test::test::test_utilities::ROSTestingFixture; 30 | using ros_sec_test::runner::Runner; 31 | using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; 32 | using ::testing::Return; 33 | using ::testing::_; 34 | 35 | TEST_F(ROSTestingFixture, test_multiple_attack_lifecycle) { 36 | std::vector nodes; 37 | auto node1 = std::make_shared("first_attack_node"); 38 | auto node2 = std::make_shared("second_attack_node"); 39 | nodes.push_back(node1); 40 | nodes.push_back(node2); 41 | Runner runner(nodes); 42 | 43 | EXPECT_CALL(*node1, on_configure(_)) 44 | .Times(1) 45 | .WillOnce(Return(CallbackReturn::SUCCESS)); 46 | EXPECT_CALL(*node1, on_activate(_)) 47 | .Times(1) 48 | .WillOnce(Return(CallbackReturn::SUCCESS)); 49 | EXPECT_CALL(*node1, on_shutdown(_)) 50 | .Times(1) 51 | .WillOnce(Return(CallbackReturn::SUCCESS)); 52 | 53 | 54 | EXPECT_CALL(*node2, on_configure(_)) 55 | .Times(1) 56 | .WillOnce(Return(CallbackReturn::SUCCESS)); 57 | EXPECT_CALL(*node2, on_activate(_)) 58 | .Times(1) 59 | .WillOnce(Return(CallbackReturn::SUCCESS)); 60 | EXPECT_CALL(*node2, on_shutdown(_)) 61 | .Times(1) 62 | .WillOnce(Return(CallbackReturn::SUCCESS)); 63 | 64 | runner.spin(); 65 | } 66 | 67 | int main(int argc, char ** argv) 68 | { 69 | ::testing::InitGoogleMock(&argc, argv); 70 | return RUN_ALL_TESTS(); 71 | } 72 | -------------------------------------------------------------------------------- /include/ros_sec_test/attacks/resources/cpu/component.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef ROS_SEC_TEST__ATTACKS__RESOURCES__CPU__COMPONENT_HPP_ 15 | #define ROS_SEC_TEST__ATTACKS__RESOURCES__CPU__COMPONENT_HPP_ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 22 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 23 | #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" 24 | #include "rclcpp_lifecycle/state.hpp" 25 | #include "rcpputils/thread_safety_annotations.hpp" 26 | 27 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 28 | 29 | namespace ros_sec_test 30 | { 31 | namespace attacks 32 | { 33 | namespace resources 34 | { 35 | namespace cpu 36 | { 37 | 38 | /// This attack tries to use all available CPU resources. 39 | /** 40 | * WARNING: this attack will try to use all of your CPU resources! 41 | * 42 | * The attack will spawn threads doing arbitrary work. 43 | * 44 | * When the node shutdowns, the node will attempt to kill 45 | * the threads it is using. 46 | */ 47 | class Component : public ros_sec_test::attacks::PeriodicAttackComponent 48 | { 49 | public: 50 | Component(); 51 | explicit Component(std::size_t max_num_threads); 52 | Component(const Component &) = delete; 53 | Component & operator=(const Component &) = delete; 54 | 55 | private: 56 | /// Spawn another thread. 57 | void run_periodic_attack() final; 58 | 59 | /// Run an infinite loop of arbitrary work 60 | static void consume_cpu_resources(); 61 | 62 | /// Join threads, clear vector, reset timer 63 | void terminate_attack_and_cleanup_resources() final; 64 | 65 | /// Maximum number of threads to spawn 66 | const std::size_t max_num_threads_; 67 | 68 | /// Threads used to occupy CPU resources 69 | std::vector threads_ RCPPUTILS_TSA_GUARDED_BY(mutex_); 70 | }; 71 | 72 | } // namespace cpu 73 | } // namespace resources 74 | } // namespace attacks 75 | } // namespace ros_sec_test 76 | 77 | #endif // ROS_SEC_TEST__ATTACKS__RESOURCES__CPU__COMPONENT_HPP_ 78 | -------------------------------------------------------------------------------- /include/ros_sec_test/attacks/resources/memory/component.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef ROS_SEC_TEST__ATTACKS__RESOURCES__MEMORY__COMPONENT_HPP_ 15 | #define ROS_SEC_TEST__ATTACKS__RESOURCES__MEMORY__COMPONENT_HPP_ 16 | #include 17 | #include 18 | 19 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 20 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 21 | #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" 22 | #include "rclcpp_lifecycle/state.hpp" 23 | #include "rcpputils/thread_safety_annotations.hpp" 24 | 25 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 26 | 27 | namespace ros_sec_test 28 | { 29 | namespace attacks 30 | { 31 | namespace resources 32 | { 33 | namespace memory 34 | { 35 | 36 | /// This attack tries to allocate as much physical memory as possible. 37 | /** 38 | * WARNING: this attack will try to fill your RAM. 39 | * 40 | * The attack will slowly allocate memory until 41 | * the RAM is full. 42 | * 43 | * When the node is killed it will attempt to free all 44 | * allocated memory 45 | */ 46 | class Component : public ros_sec_test::attacks::PeriodicAttackComponent 47 | { 48 | public: 49 | Component(); 50 | explicit Component(std::size_t max_memory); 51 | ~Component(); 52 | Component(const Component &) = delete; 53 | Component & operator=(const Component &) = delete; 54 | 55 | private: 56 | /// Allocate 10MiB of memory. 57 | void run_periodic_attack() final; 58 | 59 | /// Stop allocaing new memory and free already allocated memory 60 | void terminate_attack_and_cleanup_resources() final; 61 | 62 | /// Amount of memory currently allocated in bytes 63 | size_t num_bytes_allocated_; 64 | 65 | /// Maximum amount of memory to allocate in bytes 66 | const std::size_t max_num_bytes_allocated_; 67 | 68 | /// Allocated memory block locked to physical memory 69 | void * memory_block_; 70 | }; 71 | 72 | } // namespace memory 73 | } // namespace resources 74 | } // namespace attacks 75 | } // namespace ros_sec_test 76 | 77 | #endif // ROS_SEC_TEST__ATTACKS__RESOURCES__MEMORY__COMPONENT_HPP_ 78 | -------------------------------------------------------------------------------- /src/utilities/client_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef UTILITIES__CLIENT_UTILS_HPP_ 15 | #define UTILITIES__CLIENT_UTILS_HPP_ 16 | 17 | #include 18 | #include 19 | 20 | #include "rclcpp/client.hpp" 21 | #include "rclcpp/node.hpp" 22 | 23 | namespace ros_sec_test 24 | { 25 | namespace utilities 26 | { 27 | 28 | /// Wait for a service to exist and invoke it. 29 | /** 30 | * \param[in] node Node invoking the service. 31 | * \param[in] client Client invoking the service. 32 | * \param[in] request Request object passed during service invocation. 33 | * \param[in] time_out maximum duration this method will block. 34 | * 35 | * \tparam Request Service request type 36 | * \tparam Rep Timeout argument Rep type (see STL documentation) 37 | * \tparam Period Timeout argument Period type (see STL documentation) 38 | */ 39 | template 40 | typename rclcpp::Client::SharedResponse invoke_service_once_ready( 41 | rclcpp::Node * node, 42 | rclcpp::Client * client, 43 | typename rclcpp::Client::SharedRequest request, 44 | const std::chrono::duration & time_out); 45 | 46 | /// Identical to std::future::wait_for except but waiting will be interrupting if ROS 2 shutdowns. 47 | /* 48 | * Using std::future::wait_for has one inconvenient: if ROS 2 is shutting down, the future 49 | * result may never be delivered and wait_for will hang until the timeout is reached. 50 | * There is no way in the STL C++11 to wait on ROS 2 shutdown and a future result simultaneously. 51 | * 52 | * This method simulates this behavior by waking up the thread regularly to check on ROS 2 status. 53 | * 54 | * \param[in] future Future to wait on. 55 | * \param[in] time_out maximum duration this method will block. 56 | * \return Future status (same behavior than std::future::wait_for). 57 | */ 58 | template 59 | std::future_status 60 | wait_for_result( 61 | FutureT & future, const std::chrono::duration & timeout_duration); 63 | 64 | } // namespace utilities 65 | } // namespace ros_sec_test 66 | 67 | #include "utilities/client_utils.hxx" 68 | #endif // UTILITIES__CLIENT_UTILS_HPP_ 69 | -------------------------------------------------------------------------------- /src/attacks/resources/disk/component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "ros_sec_test/attacks/resources/disk/component.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "lifecycle_msgs/msg/transition.hpp" 27 | #include "rclcpp/publisher.hpp" 28 | #include "rclcpp/rclcpp.hpp" 29 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 30 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 31 | #include "rcutils/logging_macros.h" 32 | 33 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 34 | 35 | using namespace std::chrono_literals; 36 | 37 | using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; 38 | using PeriodicAttackComponent = ros_sec_test::attacks::PeriodicAttackComponent; 39 | 40 | namespace ros_sec_test 41 | { 42 | namespace attacks 43 | { 44 | namespace resources 45 | { 46 | namespace disk 47 | { 48 | 49 | Component::Component() 50 | : PeriodicAttackComponent("resources_disk") {} 51 | 52 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 53 | Component::on_activate(const rclcpp_lifecycle::State & /* state */) 54 | { 55 | RCLCPP_INFO(get_logger(), "on_activate() is called."); 56 | fd_ = open("attack.dat", O_WRONLY | O_CREAT); 57 | return CallbackReturn::SUCCESS; 58 | } 59 | 60 | void 61 | Component::run_periodic_attack() 62 | { 63 | // Get file size 64 | struct stat stat_buf; 65 | int rc = fstat(fd_, &stat_buf); 66 | RCLCPP_INFO(get_logger(), "Current disk size %d", stat_buf.st_size); 67 | if (rc == 0) { 68 | // Allocate an additonal 100MB 69 | posix_fallocate(fd_, stat_buf.st_size, 100 * 1024 * 1024); 70 | } 71 | // we should stop the attack if the call fails. 72 | } 73 | 74 | } // namespace disk 75 | } // namespace resources 76 | } // namespace attacks 77 | } // namespace ros_sec_test 78 | 79 | #include "class_loader/register_macro.hpp" 80 | 81 | // Register the component with class_loader. 82 | // This acts as a sort of entry point, allowing the component to be discoverable when its library 83 | // is being loaded into a running process. 84 | CLASS_LOADER_REGISTER_CLASS(ros_sec_test::attacks::resources::disk::Component, 85 | rclcpp_lifecycle::LifecycleNode) 86 | -------------------------------------------------------------------------------- /include/ros_sec_test/attacks/periodic_attack_component.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef ROS_SEC_TEST__ATTACKS__PERIODIC_ATTACK_COMPONENT_HPP_ 15 | #define ROS_SEC_TEST__ATTACKS__PERIODIC_ATTACK_COMPONENT_HPP_ 16 | #include 17 | #include 18 | #include 19 | 20 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 21 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 22 | #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" 23 | #include "rclcpp_lifecycle/state.hpp" 24 | #include "rcpputils/thread_safety_annotations.hpp" 25 | 26 | 27 | namespace ros_sec_test 28 | { 29 | namespace attacks 30 | { 31 | 32 | /** 33 | * Base blass for attacks that follow a pattern of executing 34 | * an attack periodicially base on a timer 35 | */ 36 | class PeriodicAttackComponent : public rclcpp_lifecycle::LifecycleNode 37 | { 38 | public: 39 | explicit PeriodicAttackComponent(std::string node_name); 40 | PeriodicAttackComponent(const PeriodicAttackComponent &) = delete; 41 | PeriodicAttackComponent & operator=(const PeriodicAttackComponent &) = delete; 42 | virtual ~PeriodicAttackComponent() = default; 43 | 44 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 45 | on_configure(const rclcpp_lifecycle::State & /* state */); 46 | 47 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 48 | on_activate(const rclcpp_lifecycle::State & /* state */); 49 | 50 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 51 | on_deactivate(const rclcpp_lifecycle::State & /* state */); 52 | 53 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 54 | on_cleanup(const rclcpp_lifecycle::State & /* state */); 55 | 56 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 57 | on_shutdown(const rclcpp_lifecycle::State & /* state */ state); 58 | 59 | protected: 60 | /// Execute the attack. 61 | virtual void run_periodic_attack(); 62 | 63 | /// Stop the attack timer and free any resources. 64 | virtual void terminate_attack_and_cleanup_resources(); 65 | 66 | // Manages thread safety for attacks. 67 | mutable std::mutex mutex_; 68 | 69 | /// Timer controlling how often the attack is run. 70 | rclcpp::TimerBase::SharedPtr timer_ RCPPUTILS_TSA_GUARDED_BY(mutex_); 71 | }; 72 | 73 | } // namespace attacks 74 | } // namespace ros_sec_test 75 | 76 | #endif // ROS_SEC_TEST__ATTACKS__PERIODIC_ATTACK_COMPONENT_HPP_ 77 | -------------------------------------------------------------------------------- /src/attacks/noop/component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "ros_sec_test/attacks/noop/component.hpp" 15 | 16 | #include "rclcpp/logging.hpp" 17 | #include "rclcpp/node_options.hpp" 18 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 19 | #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" 20 | #include "rclcpp_lifecycle/state.hpp" 21 | 22 | using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; 23 | 24 | namespace ros_sec_test 25 | { 26 | namespace attacks 27 | { 28 | namespace noop 29 | { 30 | 31 | Component::Component() 32 | : rclcpp_lifecycle::LifecycleNode("noop", "", rclcpp::NodeOptions().use_intra_process_comms(true)) 33 | { 34 | } 35 | 36 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 37 | Component::on_configure(const rclcpp_lifecycle::State & /* state */) 38 | { 39 | RCLCPP_INFO(get_logger(), "on_configure() is called."); 40 | return CallbackReturn::SUCCESS; 41 | } 42 | 43 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 44 | Component::on_activate(const rclcpp_lifecycle::State & /* state */) 45 | { 46 | RCLCPP_INFO(get_logger(), "on_activate() is called."); 47 | return CallbackReturn::SUCCESS; 48 | } 49 | 50 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 51 | Component::on_deactivate(const rclcpp_lifecycle::State & /* state */) 52 | { 53 | RCLCPP_INFO(get_logger(), "on_deactivate() is called."); 54 | return CallbackReturn::SUCCESS; 55 | } 56 | 57 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 58 | Component::on_cleanup(const rclcpp_lifecycle::State & /* state */) 59 | { 60 | RCLCPP_INFO(get_logger(), "on_cleanup() is called."); 61 | return CallbackReturn::SUCCESS; 62 | } 63 | 64 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 65 | Component::on_shutdown(const rclcpp_lifecycle::State & /* state */) 66 | { 67 | RCLCPP_INFO(get_logger(), "on_shutdown() is called."); 68 | return CallbackReturn::SUCCESS; 69 | } 70 | 71 | } // namespace noop 72 | } // namespace attacks 73 | } // namespace ros_sec_test 74 | 75 | #include "class_loader/register_macro.hpp" 76 | 77 | // Register the component with class_loader. 78 | // This acts as a sort of entry point, allowing the component to be discoverable when its library 79 | // is being loaded into a running process. 80 | CLASS_LOADER_REGISTER_CLASS(ros_sec_test::attacks::noop::Component, rclcpp_lifecycle::LifecycleNode) 81 | -------------------------------------------------------------------------------- /src/utilities/client_utils.hxx: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef UTILITIES__CLIENT_UTILS_HXX_ 15 | #define UTILITIES__CLIENT_UTILS_HXX_ 16 | 17 | #include 18 | #include 19 | 20 | #include "rclcpp/client.hpp" 21 | #include "rclcpp/logging.hpp" 22 | #include "rclcpp/node.hpp" 23 | #include "rclcpp/utilities.hpp" 24 | 25 | namespace ros_sec_test 26 | { 27 | namespace utilities 28 | { 29 | 30 | template 31 | typename rclcpp::Client::SharedResponse invoke_service_once_ready( 32 | rclcpp::Node * node, 33 | rclcpp::Client * client, 34 | typename rclcpp::Client::SharedRequest request, 35 | const std::chrono::duration & time_out 36 | ) 37 | { 38 | if (!client->wait_for_service(time_out)) { 39 | RCLCPP_ERROR(node->get_logger(), "Service %s is not available.", 40 | client->get_service_name()); 41 | return typename rclcpp::Client::SharedResponse(); 42 | } 43 | auto future_result = client->async_send_request(request); 44 | auto future_status = wait_for_result(future_result, time_out); 45 | if (future_status != std::future_status::ready) { 46 | RCLCPP_ERROR( 47 | node->get_logger(), "Server time out while calling service %s", 48 | node->get_name()); 49 | return typename rclcpp::Client::SharedResponse(); 50 | } 51 | if (future_result.get()) { 52 | return future_result.get(); 53 | } else { 54 | RCLCPP_ERROR(node->get_logger(), "Failed to call service %s", node->get_name()); 55 | return typename rclcpp::Client::SharedResponse(); 56 | } 57 | } 58 | 59 | template 60 | std::future_status 61 | wait_for_result( 62 | FutureT & future, 63 | const std::chrono::duration & timeout_duration) 64 | { 65 | const auto end = std::chrono::steady_clock::now() + timeout_duration; 66 | const std::chrono::milliseconds wait_period(100); 67 | std::future_status status = std::future_status::timeout; 68 | do { 69 | const auto now = std::chrono::steady_clock::now(); 70 | const auto time_left = end - now; 71 | if (time_left <= std::chrono::seconds(0)) { 72 | return status; 73 | } 74 | status = future.wait_for((time_left < wait_period) ? time_left : wait_period); 75 | } while (rclcpp::ok() && status != std::future_status::ready); 76 | return status; 77 | } 78 | 79 | } // namespace utilities 80 | } // namespace ros_sec_test 81 | 82 | #endif // UTILITIES__CLIENT_UTILS_HXX_ 83 | -------------------------------------------------------------------------------- /src/utilities/lifecycle_service_client.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "utilities/lifecycle_service_client.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "lifecycle_msgs/msg/state.hpp" 22 | #include "lifecycle_msgs/msg/transition.hpp" 23 | #include "lifecycle_msgs/srv/change_state.hpp" 24 | #include "lifecycle_msgs/srv/get_state.hpp" 25 | 26 | #include "rclcpp/rclcpp.hpp" 27 | 28 | #include "rcutils/logging_macros.h" 29 | 30 | #include "utilities/client_utils.hpp" 31 | #include "utilities/service_utils.hpp" 32 | 33 | using namespace std::chrono_literals; 34 | 35 | using ChangeStateSrv = lifecycle_msgs::srv::ChangeState; 36 | using GetStateSrv = lifecycle_msgs::srv::GetState; 37 | 38 | namespace ros_sec_test 39 | { 40 | namespace utilities 41 | { 42 | 43 | LifecycleServiceClient::LifecycleServiceClient( 44 | rclcpp::Node * parent_node, 45 | const std::string & target_node_name) 46 | : target_node_name_(target_node_name), 47 | parent_node_(parent_node), 48 | client_change_state_(parent_node->create_client(build_change_state_service_name( 49 | target_node_name))), 50 | client_get_state_(parent_node->create_client(build_get_state_service_name( 51 | target_node_name))) 52 | {} 53 | 54 | rclcpp_lifecycle::State 55 | LifecycleServiceClient::get_state(std::chrono::seconds time_out) 56 | { 57 | auto request = std::make_shared(); 58 | auto result = invoke_service_once_ready(parent_node_, client_get_state_.get(), request, time_out); 59 | return rclcpp_lifecycle::State(result->current_state.id, result->current_state.label); 60 | } 61 | 62 | bool 63 | LifecycleServiceClient::change_state( 64 | rclcpp_lifecycle::Transition transition, 65 | std::chrono::seconds time_out) 66 | { 67 | auto request = std::make_shared(); 68 | request->transition.id = transition.id(); 69 | auto result = invoke_service_once_ready(parent_node_, 70 | client_change_state_.get(), request, time_out); 71 | return !!result; 72 | } 73 | 74 | bool LifecycleServiceClient::activate() 75 | { 76 | return change_state(rclcpp_lifecycle::Transition(lifecycle_msgs::msg::Transition:: 77 | TRANSITION_ACTIVATE)); 78 | } 79 | 80 | bool LifecycleServiceClient::configure() 81 | { 82 | return change_state(rclcpp_lifecycle::Transition(lifecycle_msgs::msg::Transition:: 83 | TRANSITION_CONFIGURE)); 84 | } 85 | 86 | bool LifecycleServiceClient::shutdown() 87 | { 88 | return change_state(rclcpp_lifecycle::Transition(lifecycle_msgs::msg::Transition:: 89 | TRANSITION_ACTIVE_SHUTDOWN)); 90 | } 91 | 92 | } // namespace utilities 93 | } // namespace ros_sec_test 94 | -------------------------------------------------------------------------------- /src/attacks/periodic_attack_component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "lifecycle_msgs/msg/transition.hpp" 27 | #include "rclcpp/publisher.hpp" 28 | #include "rclcpp/rclcpp.hpp" 29 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 30 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 31 | #include "rcutils/logging_macros.h" 32 | 33 | using namespace std::chrono_literals; 34 | 35 | using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; 36 | 37 | namespace ros_sec_test 38 | { 39 | namespace attacks 40 | { 41 | PeriodicAttackComponent::PeriodicAttackComponent(std::string node_name) 42 | : rclcpp_lifecycle::LifecycleNode( 43 | node_name, "", rclcpp::NodeOptions().use_intra_process_comms( 44 | true)), 45 | mutex_(), 46 | timer_() {} 47 | 48 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 49 | PeriodicAttackComponent::on_configure(const rclcpp_lifecycle::State & /* state */) 50 | RCPPUTILS_TSA_REQUIRES(!mutex_) 51 | { 52 | RCLCPP_INFO(get_logger(), "on_configure() is called."); 53 | auto callback = [this] {run_periodic_attack();}; 54 | { 55 | std::lock_guard lock(mutex_); 56 | timer_ = this->create_wall_timer(1s, std::move(callback)); 57 | } 58 | return CallbackReturn::SUCCESS; 59 | } 60 | 61 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 62 | PeriodicAttackComponent::on_activate(const rclcpp_lifecycle::State & /* state */) 63 | { 64 | RCLCPP_INFO(get_logger(), "on_activate() is called."); 65 | return CallbackReturn::SUCCESS; 66 | } 67 | 68 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 69 | PeriodicAttackComponent::on_deactivate(const rclcpp_lifecycle::State & /* state */) 70 | { 71 | RCLCPP_INFO(get_logger(), "on_deactivate() is called."); 72 | return CallbackReturn::SUCCESS; 73 | } 74 | 75 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 76 | PeriodicAttackComponent::on_cleanup(const rclcpp_lifecycle::State & /* state */) 77 | { 78 | RCLCPP_INFO(get_logger(), "on_cleanup() is called."); 79 | terminate_attack_and_cleanup_resources(); 80 | return CallbackReturn::SUCCESS; 81 | } 82 | 83 | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn 84 | PeriodicAttackComponent::on_shutdown(const rclcpp_lifecycle::State & /* state */) 85 | { 86 | RCLCPP_INFO(get_logger(), "on_shutdown() is called."); 87 | terminate_attack_and_cleanup_resources(); 88 | return CallbackReturn::SUCCESS; 89 | } 90 | 91 | void 92 | PeriodicAttackComponent::terminate_attack_and_cleanup_resources() 93 | { 94 | timer_.reset(); 95 | } 96 | 97 | void 98 | PeriodicAttackComponent::run_periodic_attack() 99 | {} 100 | } // namespace attacks 101 | } // namespace ros_sec_test 102 | -------------------------------------------------------------------------------- /src/attacks/resources/cpu/component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "ros_sec_test/attacks/resources/cpu/component.hpp" 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "lifecycle_msgs/msg/state.hpp" 28 | #include "lifecycle_msgs/msg/transition.hpp" 29 | #include "rclcpp/publisher.hpp" 30 | #include "rclcpp/rclcpp.hpp" 31 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 32 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 33 | #include "rcutils/logging_macros.h" 34 | #include "rcpputils/thread_safety_annotations.hpp" 35 | 36 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 37 | 38 | using namespace std::chrono_literals; 39 | 40 | using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; 41 | using PeriodicAttackComponent = ros_sec_test::attacks::PeriodicAttackComponent; 42 | 43 | namespace ros_sec_test 44 | { 45 | namespace attacks 46 | { 47 | namespace resources 48 | { 49 | namespace cpu 50 | { 51 | // By default start with twice the maximum supported number of threads. Hardware concurrency 52 | // isn't guaranteed to be accurate so the maximum number of threads is doubled to avoid 53 | // the attack failing. 54 | Component::Component() 55 | : Component(2 * std::thread::hardware_concurrency()) {} 56 | 57 | Component::Component(std::size_t max_num_threads) 58 | : PeriodicAttackComponent("resources_cpu"), 59 | max_num_threads_(max_num_threads), 60 | threads_() {} 61 | 62 | void Component::terminate_attack_and_cleanup_resources() RCPPUTILS_TSA_REQUIRES(!mutex_) 63 | { 64 | PeriodicAttackComponent::terminate_attack_and_cleanup_resources(); 65 | std::vector threads; 66 | { 67 | std::lock_guard lock(mutex_); 68 | threads = std::move(threads_); 69 | } 70 | for (auto & thread : threads) { 71 | thread.join(); 72 | } 73 | threads.clear(); 74 | } 75 | 76 | void Component::run_periodic_attack() RCPPUTILS_TSA_REQUIRES(!mutex_) 77 | { 78 | auto thread = std::thread([this] {consume_cpu_resources();}); 79 | { 80 | std::lock_guard lock(mutex_); 81 | if (max_num_threads_ > threads_.size()) { 82 | threads_.push_back(std::move(thread)); 83 | } 84 | } 85 | } 86 | 87 | 88 | void Component::consume_cpu_resources() 89 | { 90 | int i_sum = 0; 91 | for (int i = 0;; i++) { 92 | if (!rclcpp::ok()) { 93 | return; 94 | } 95 | // It's fine if this overflows 96 | i_sum += i; 97 | // Prevent optimization 98 | asm ("nop"); 99 | } 100 | } 101 | 102 | } // namespace cpu 103 | } // namespace resources 104 | } // namespace attacks 105 | } // namespace ros_sec_test 106 | 107 | #include "class_loader/register_macro.hpp" 108 | 109 | // Register the component with class_loader. 110 | // This acts as a sort of entry point, allowing the component to be discoverable when its library 111 | // is being loaded into a running process. 112 | CLASS_LOADER_REGISTER_CLASS(ros_sec_test::attacks::resources::cpu::Component, 113 | rclcpp_lifecycle::LifecycleNode) 114 | -------------------------------------------------------------------------------- /src/attacks/resources/memory/component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "ros_sec_test/attacks/resources/memory/component.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "lifecycle_msgs/msg/transition.hpp" 34 | #include "rclcpp/publisher.hpp" 35 | #include "rclcpp/rclcpp.hpp" 36 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 37 | #include "rclcpp_lifecycle/lifecycle_publisher.hpp" 38 | #include "rcutils/logging_macros.h" 39 | #include "rcpputils/thread_safety_annotations.hpp" 40 | 41 | #include "ros_sec_test/attacks/periodic_attack_component.hpp" 42 | 43 | using namespace std::chrono_literals; 44 | 45 | using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; 46 | using PeriodicAttackComponent = ros_sec_test::attacks::PeriodicAttackComponent; 47 | 48 | // Amount of additional memory in bytes to allocate each time the attack loop is allocated. 49 | static constexpr std::size_t kBytesAllocatedPerAttack = 100 * 1024 * 1024; 50 | 51 | namespace ros_sec_test 52 | { 53 | namespace attacks 54 | { 55 | namespace resources 56 | { 57 | namespace memory 58 | { 59 | 60 | Component::Component() 61 | : Component(SIZE_MAX) {} 62 | 63 | Component::Component(std::size_t max_num_bytes_allocated) 64 | : PeriodicAttackComponent("resources_memory"), 65 | num_bytes_allocated_(0), 66 | max_num_bytes_allocated_(max_num_bytes_allocated), 67 | memory_block_() {} 68 | 69 | Component::~Component() 70 | { 71 | free(memory_block_); 72 | } 73 | 74 | void Component::terminate_attack_and_cleanup_resources() RCPPUTILS_TSA_REQUIRES(!mutex_) 75 | { 76 | { 77 | std::lock_guard lock(mutex_); 78 | timer_.reset(); 79 | } 80 | { 81 | std::lock_guard lock(mutex_); 82 | munlock(memory_block_, num_bytes_allocated_); 83 | free(memory_block_); 84 | } 85 | } 86 | 87 | void Component::run_periodic_attack() RCPPUTILS_TSA_REQUIRES(!mutex_) 88 | { 89 | std::lock_guard lock(mutex_); 90 | if (num_bytes_allocated_ < max_num_bytes_allocated_) { 91 | size_t memory_to_allocate = std::min(num_bytes_allocated_ + kBytesAllocatedPerAttack, 92 | max_num_bytes_allocated_); 93 | void * new_memory_block = realloc(memory_block_, memory_to_allocate); 94 | if (new_memory_block == NULL) { 95 | RCLCPP_ERROR(get_logger(), "Failed to allocate memory."); 96 | } else { 97 | memory_block_ = new_memory_block; 98 | num_bytes_allocated_ = memory_to_allocate; 99 | int result = mlock(memory_block_, num_bytes_allocated_); 100 | if (0 != result) { 101 | RCLCPP_ERROR(get_logger(), "Error while trying to lock memory: %s ", std::strerror(errno)); 102 | } 103 | } 104 | } 105 | } 106 | 107 | 108 | } // namespace memory 109 | } // namespace resources 110 | } // namespace attacks 111 | } // namespace ros_sec_test 112 | 113 | #include "class_loader/register_macro.hpp" 114 | 115 | // Register the component with class_loader. 116 | // This acts as a sort of entry point, allowing the component to be discoverable when its library 117 | // is being loaded into a running process. 118 | CLASS_LOADER_REGISTER_CLASS(ros_sec_test::attacks::resources::memory::Component, 119 | rclcpp_lifecycle::LifecycleNode) 120 | -------------------------------------------------------------------------------- /src/utilities/lifecycle_service_client.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef UTILITIES__LIFECYCLE_SERVICE_CLIENT_HPP_ 15 | #define UTILITIES__LIFECYCLE_SERVICE_CLIENT_HPP_ 16 | #include 17 | #include 18 | #include 19 | 20 | #include "lifecycle_msgs/srv/change_state.hpp" 21 | #include "lifecycle_msgs/srv/get_state.hpp" 22 | #include "rclcpp/rclcpp.hpp" 23 | #include "rclcpp_lifecycle/transition.hpp" 24 | #include "rclcpp_lifecycle/state.hpp" 25 | 26 | namespace ros_sec_test 27 | { 28 | namespace utilities 29 | { 30 | 31 | /// Class wrapping the lifecycle_node services to get and set node states. 32 | class LifecycleServiceClient 33 | { 34 | public: 35 | /// Initializes the object and construct all necessary service clients. 36 | /** 37 | * \param[in] parent_node Pointer to the node which will hold this client 38 | * \param[in] target_node_name lifecycle_node to be controlled by this client 39 | * 40 | * CAVEAT: rclcpp::init() must be invoked before this object is constructed. 41 | */ 42 | LifecycleServiceClient(rclcpp::Node * parent_node, const std::string & target_node_name); 43 | 44 | LifecycleServiceClient(const LifecycleServiceClient &) = delete; 45 | LifecycleServiceClient & operator=(const LifecycleServiceClient &) = delete; 46 | 47 | /// Requests the current state of the node 48 | /** 49 | * In this function, we send a service request 50 | * asking for the current state of the node 51 | * lc_talker. 52 | * If it does return within the given time_out, 53 | * we return the current state of the node, if 54 | * not, we return an unknown state. 55 | * \param time_out Duration in seconds specifying 56 | * how long we wait for a response before returning 57 | * unknown state 58 | */ 59 | rclcpp_lifecycle::State get_state(std::chrono::seconds time_out = std::chrono::seconds(3)); 60 | 61 | /// Try to switch the target node to the state "active". 62 | /** 63 | * \return true if the service call is successful, false otherwise 64 | */ 65 | bool activate(); 66 | 67 | /// Try to switch the target node to the state "configured". 68 | /** 69 | * \return true if the service call is successful, false otherwise 70 | */ 71 | bool configure(); 72 | 73 | /// Try to switch the target node to the state "shutting down". 74 | /** 75 | * \return true if the service call is successful, false otherwise 76 | */ 77 | bool shutdown(); 78 | 79 | private: 80 | /// Invokes a transition 81 | /** 82 | * We send a Service request and indicate 83 | * that we want to invoke transition with 84 | * the id "transition". 85 | * By default, these transitions are 86 | * - configure 87 | * - activate 88 | * - cleanup 89 | * - shutdown 90 | * \param transition id specifying which 91 | * transition to invoke 92 | * \param time_out Duration in seconds specifying 93 | * how long we wait for a response before returning 94 | * unknown state 95 | */ 96 | bool change_state( 97 | const rclcpp_lifecycle::Transition transition, 98 | const std::chrono::seconds time_out = std::chrono::seconds(5)); 99 | 100 | /// Node controlled by this client. 101 | const std::string target_node_name_; 102 | 103 | rclcpp::Node * parent_node_; 104 | const rclcpp::Client::SharedPtr client_change_state_; 105 | const rclcpp::Client::SharedPtr client_get_state_; 106 | }; 107 | 108 | } // namespace utilities 109 | } // namespace ros_sec_test 110 | 111 | #endif // UTILITIES__LIFECYCLE_SERVICE_CLIENT_HPP_ 112 | -------------------------------------------------------------------------------- /src/runner/runner.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef RUNNER__RUNNER_HPP_ 15 | #define RUNNER__RUNNER_HPP_ 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "rclcpp/executor.hpp" 22 | #include "rclcpp/logger.hpp" 23 | #include "rclcpp/node.hpp" 24 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 25 | #include "rcutils/logging_macros.h" 26 | 27 | #include "utilities/lifecycle_service_client.hpp" 28 | 29 | namespace ros_sec_test 30 | { 31 | namespace runner 32 | { 33 | 34 | /// Main class containing the whole application logic, instantiated in main(). 35 | /** 36 | * Runner holds a ROS 2 node and one additional lifecycle_node per enabled attack node. 37 | * 38 | * The additional ROS 2 node (node_) is used to keep isolated from attack nodes the 39 | * calls to the services managing the lifecycle nodes. 40 | * 41 | * Attack nodes are set a instantiation time and can *never* be changed. 42 | * 43 | * The only public method exposed by this class is spin() which starts, execute the attacks 44 | * and stop all the nodes when needed. 45 | */ 46 | class Runner 47 | { 48 | public: 49 | /// Instantiate all nodes from parameter without activating them. 50 | /** 51 | * CAVEAT: rclcpp::init() *must* be called before instantiating this object. 52 | */ 53 | Runner(); 54 | /// Use a vector of already instantiated nodes. 55 | /** 56 | * CAVEAT: rclcpp::init() *must* be called before instantiating this object. 57 | */ 58 | explicit Runner(const std::vector & attack_nodes); 59 | 60 | Runner(const Runner &) = delete; 61 | Runner & operator=(const Runner &) = delete; 62 | 63 | /// Starts, executes all attacks and shutdown all nodes. 64 | void spin(); 65 | 66 | private: 67 | /// Holds a shared pointer to a node and the associated lifecycle client. 68 | struct AttackNodeData 69 | { 70 | rclcpp_lifecycle::LifecycleNode::SharedPtr node; 71 | 72 | /// Wraps lifecycle service calls in a conveninent interface. 73 | std::shared_ptr lifecycle_client; 74 | }; 75 | 76 | /// Execute all attacks synchronously. 77 | /** 78 | * Running attacks in a different thread allow us to spin from the main thread. 79 | */ 80 | std::future execute_all_attacks_async(); 81 | 82 | /// Initialize the attack_nodes_ attributes. Invoked from the class constructor. 83 | /** 84 | * \param[in] node_names All attack nodes to be instantiated. 85 | */ 86 | void initialize_attack_nodes(const std::vector & node_names); 87 | 88 | /// Read the list of attacks to be run from the node parameter. 89 | /** 90 | * \return Names of all enabled attacks. 91 | */ 92 | std::vector retrieve_attack_nodes_names(); 93 | 94 | /// Read the attack duration in seconds from the node parameter. 95 | /** 96 | * \return Duration of attack in seconds. 97 | */ 98 | std::chrono::seconds retrieve_attack_duration_s(); 99 | 100 | /// Relies on lifecycle client to start and stop all attacks. 101 | void start_and_stop_all_nodes(); 102 | 103 | /// Log a message explaining that no attack have been specified and the runner will do nothing. 104 | void warn_user_no_attack_nodes_passed(); 105 | 106 | /// Create a separate node to send lifecycle requests. 107 | rclcpp::Node::SharedPtr node_; 108 | 109 | /// Contain all attack nodes information. 110 | std::vector attack_nodes_; 111 | 112 | /// Executor shared by all nodes. 113 | rclcpp::executors::SingleThreadedExecutor executor_; 114 | 115 | rclcpp::Logger logger_; 116 | }; 117 | 118 | } // namespace runner 119 | } // namespace ros_sec_test 120 | 121 | #endif // RUNNER__RUNNER_HPP_ 122 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws-robotics/ROS2-SecTest/issues), or [recently closed](https://github.com/aws-robotics/ROS2-SecTest/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-robotics/ROS2-SecTest/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/aws-robotics/ROS2-SecTest/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | 63 | Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): 64 | 65 | ~~~ 66 | 5. Submission of Contributions. Unless You explicitly state otherwise, 67 | any Contribution intentionally submitted for inclusion in the Work 68 | by You to the Licensor shall be under the terms and conditions of 69 | this License, without any additional terms or conditions. 70 | Notwithstanding the above, nothing herein shall supersede or modify 71 | the terms of any separate license agreement you may have executed 72 | with Licensor regarding such Contributions. 73 | ~~~ 74 | 75 | Contributors must sign-off each commit by adding a `Signed-off-by: ...` 76 | line to commit messages to certify that they have the right to submit 77 | the code they are contributing to the project according to the 78 | [Developer Certificate of Origin (DCO)](https://developercertificate.org/). 79 | -------------------------------------------------------------------------------- /test/ros_sec_test/utilities/test_client_utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "rcl_interfaces/srv/list_parameters.hpp" 22 | #include "rclcpp/executors/single_threaded_executor.hpp" 23 | #include "rclcpp/node.hpp" 24 | #include "rclcpp/utilities.hpp" 25 | 26 | #include "utilities/client_utils.hpp" 27 | 28 | using rcl_interfaces::srv::ListParameters; 29 | using rclcpp::executors::SingleThreadedExecutor; 30 | using ros_sec_test::utilities::invoke_service_once_ready; 31 | using ros_sec_test::utilities::wait_for_result; 32 | 33 | TEST(invoke_service_once_ready, service_not_available) { 34 | using namespace std::chrono_literals; 35 | rclcpp::init(0, nullptr); 36 | { 37 | auto node = rclcpp::Node::make_shared("test_node"); 38 | auto client = node->create_client("test_service"); 39 | auto request = std::make_shared(); 40 | auto response = invoke_service_once_ready(node.get(), client.get(), request, 100ms); 41 | RCLCPP_INFO(node->get_logger(), "The following reported error is expected."); 42 | EXPECT_EQ(response.get(), nullptr); 43 | } 44 | rclcpp::shutdown(); 45 | } 46 | 47 | TEST(invoke_service_once_ready, invoke_service_successfully) { 48 | using namespace std::chrono_literals; 49 | rclcpp::init(0, nullptr); 50 | { 51 | SingleThreadedExecutor executor; 52 | auto node = rclcpp::Node::make_shared("test_node"); 53 | executor.add_node(node); 54 | 55 | std::promise thread_promise; 56 | std::shared_future future = thread_promise.get_future(); 57 | std::atomic_bool service_has_been_invoked(false); 58 | 59 | auto callback = 60 | [&service_has_been_invoked](const ListParameters::Request::SharedPtr, 61 | ListParameters::Response::SharedPtr) { 62 | service_has_been_invoked.store(true); 63 | }; 64 | auto srv = node->create_service("test_service", callback); 65 | 66 | std::thread thread_spin([&executor, &future, &node]() { 67 | RCLCPP_INFO(node->get_logger(), "Spin thread started."); 68 | executor.spin_until_future_complete(future, 10ms); 69 | RCLCPP_INFO(node->get_logger(), "Spin thread ended."); 70 | }); 71 | 72 | auto client = node->create_client("test_service"); 73 | auto request = std::make_shared(); 74 | auto response = invoke_service_once_ready(node.get(), client.get(), request, 10s); 75 | EXPECT_NE(response.get(), nullptr); 76 | EXPECT_TRUE(service_has_been_invoked.load()); 77 | 78 | RCLCPP_INFO(node->get_logger(), "Thread promise set."); 79 | thread_promise.set_value(); 80 | thread_spin.join(); 81 | } 82 | rclcpp::shutdown(); 83 | } 84 | 85 | TEST(wait_for_result, check_timeout) { 86 | using namespace std::chrono_literals; 87 | rclcpp::init(0, nullptr); 88 | { 89 | std::promise promise; 90 | std::future future = promise.get_future(); 91 | EXPECT_EQ(wait_for_result(future, 1ms), std::future_status::timeout); 92 | } 93 | rclcpp::shutdown(); 94 | } 95 | 96 | TEST(wait_for_result, check_ready) { 97 | using namespace std::chrono_literals; 98 | rclcpp::init(0, nullptr); 99 | { 100 | std::promise promise; 101 | std::future future = promise.get_future(); 102 | promise.set_value(); 103 | EXPECT_EQ(wait_for_result(future, 1ms), std::future_status::ready); 104 | } 105 | rclcpp::shutdown(); 106 | } 107 | 108 | // Unlike std::future::wait_for(), wait_for_result should never block if ROS is not 109 | // initialized or already shut down. 110 | TEST(wait_for_result, check_rclcpp_not_ok) { 111 | using namespace std::chrono_literals; 112 | EXPECT_FALSE(rclcpp::ok()); 113 | std::promise promise; 114 | std::future future = promise.get_future(); 115 | EXPECT_EQ(wait_for_result(future, 10s), std::future_status::timeout); 116 | } 117 | 118 | 119 | int main(int argc, char ** argv) 120 | { 121 | ::testing::InitGoogleTest(&argc, argv); 122 | return RUN_ALL_TESTS(); 123 | } 124 | -------------------------------------------------------------------------------- /test/ros_sec_test/attacks/noop/test_component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "ros_sec_test/attacks/noop/component.hpp" 21 | #include "test_utilities/utility_fixtures.hpp" 22 | 23 | #include "lifecycle_msgs/msg/state.hpp" 24 | #include "lifecycle_msgs/msg/transition.hpp" 25 | #include "rclcpp/executors/single_threaded_executor.hpp" 26 | #include "rclcpp/node.hpp" 27 | 28 | using NoopNode = ros_sec_test::attacks::noop::Component; 29 | using lifecycle_msgs::msg::State; 30 | using lifecycle_msgs::msg::Transition; 31 | using ros_sec_test::test::test_utilities::NodeConfigurationFixture; 32 | 33 | TEST_F(NodeConfigurationFixture, check_configuring_transition) { 34 | auto attack_node = std::make_shared(); 35 | add_node_to_executor(attack_node->get_node_base_interface()); 36 | start_executor(); 37 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 38 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 39 | } 40 | 41 | TEST_F(NodeConfigurationFixture, check_activating_transition) { 42 | auto attack_node = std::make_shared(); 43 | add_node_to_executor(attack_node->get_node_base_interface()); 44 | start_executor(); 45 | attack_node->trigger_transition( 46 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 47 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 48 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 49 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 50 | } 51 | 52 | TEST_F(NodeConfigurationFixture, check_deactivating_transition) { 53 | auto attack_node = std::make_shared(); 54 | add_node_to_executor(attack_node->get_node_base_interface()); 55 | start_executor(); 56 | attack_node->trigger_transition( 57 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 58 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 59 | attack_node->trigger_transition( 60 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 61 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 62 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 63 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 64 | } 65 | 66 | TEST_F(NodeConfigurationFixture, check_cleaningup_transition) { 67 | auto attack_node = std::make_shared(); 68 | add_node_to_executor(attack_node->get_node_base_interface()); 69 | start_executor(); 70 | attack_node->trigger_transition( 71 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 72 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 73 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 74 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 75 | } 76 | 77 | TEST_F(NodeConfigurationFixture, check_unconfigured_shuttingdown_transition) { 78 | auto attack_node = std::make_shared(); 79 | add_node_to_executor(attack_node->get_node_base_interface()); 80 | start_executor(); 81 | attack_node->trigger_transition( 82 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 83 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 84 | attack_node->trigger_transition( 85 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)); 86 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->get_current_state().id()); 87 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 88 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 89 | } 90 | 91 | TEST_F(NodeConfigurationFixture, check_active_shuttingdown_transition) { 92 | auto attack_node = std::make_shared(); 93 | add_node_to_executor(attack_node->get_node_base_interface()); 94 | start_executor(); 95 | attack_node->trigger_transition( 96 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 97 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 98 | attack_node->trigger_transition( 99 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 100 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 101 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 102 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id()); 103 | } 104 | 105 | TEST_F(NodeConfigurationFixture, check_full_node_lifecycle) { 106 | auto attack_node = std::make_shared(); 107 | add_node_to_executor(attack_node->get_node_base_interface()); 108 | start_executor(); 109 | 110 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 111 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 112 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 113 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 114 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 115 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 116 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 117 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 118 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 119 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 120 | } 121 | 122 | int main(int argc, char ** argv) 123 | { 124 | ::testing::InitGoogleTest(&argc, argv); 125 | return RUN_ALL_TESTS(); 126 | } 127 | -------------------------------------------------------------------------------- /test/ros_sec_test/attacks/resources/cpu/test_component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "ros_sec_test/attacks/resources/cpu/component.hpp" 21 | #include "test_utilities/utility_fixtures.hpp" 22 | 23 | #include "lifecycle_msgs/msg/state.hpp" 24 | #include "lifecycle_msgs/msg/transition.hpp" 25 | #include "rclcpp/executors/single_threaded_executor.hpp" 26 | #include "rclcpp/node.hpp" 27 | 28 | using CPUNode = ros_sec_test::attacks::resources::cpu::Component; 29 | using lifecycle_msgs::msg::State; 30 | using lifecycle_msgs::msg::Transition; 31 | using ros_sec_test::test::test_utilities::NodeConfigurationFixture; 32 | 33 | TEST_F(NodeConfigurationFixture, check_configuring_transition) { 34 | auto attack_node = std::make_shared(0); 35 | add_node_to_executor(attack_node->get_node_base_interface()); 36 | start_executor(); 37 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 38 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 39 | } 40 | 41 | TEST_F(NodeConfigurationFixture, check_activating_transition) { 42 | auto attack_node = std::make_shared(0); 43 | add_node_to_executor(attack_node->get_node_base_interface()); 44 | start_executor(); 45 | attack_node->trigger_transition( 46 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 47 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 48 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 49 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 50 | } 51 | 52 | TEST_F(NodeConfigurationFixture, check_deactivating_transition) { 53 | auto attack_node = std::make_shared(0); 54 | add_node_to_executor(attack_node->get_node_base_interface()); 55 | start_executor(); 56 | attack_node->trigger_transition( 57 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 58 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 59 | attack_node->trigger_transition( 60 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 61 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 62 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 63 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 64 | } 65 | 66 | TEST_F(NodeConfigurationFixture, check_cleaningup_transition) { 67 | auto attack_node = std::make_shared(0); 68 | add_node_to_executor(attack_node->get_node_base_interface()); 69 | start_executor(); 70 | attack_node->trigger_transition( 71 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 72 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 73 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 74 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 75 | } 76 | 77 | TEST_F(NodeConfigurationFixture, check_unconfigured_shuttingdown_transition) { 78 | auto attack_node = std::make_shared(0); 79 | add_node_to_executor(attack_node->get_node_base_interface()); 80 | start_executor(); 81 | attack_node->trigger_transition( 82 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 83 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 84 | attack_node->trigger_transition( 85 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)); 86 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->get_current_state().id()); 87 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 88 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 89 | } 90 | 91 | TEST_F(NodeConfigurationFixture, check_active_shuttingdown_transition) { 92 | auto attack_node = std::make_shared(0); 93 | add_node_to_executor(attack_node->get_node_base_interface()); 94 | start_executor(); 95 | attack_node->trigger_transition( 96 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 97 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 98 | attack_node->trigger_transition( 99 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 100 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 101 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 102 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id()); 103 | } 104 | 105 | TEST_F(NodeConfigurationFixture, check_full_node_lifecycle) { 106 | auto attack_node = std::make_shared(0); 107 | add_node_to_executor(attack_node->get_node_base_interface()); 108 | start_executor(); 109 | 110 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 111 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 112 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 113 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 114 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 115 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 116 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 117 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 118 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 119 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 120 | } 121 | 122 | int main(int argc, char ** argv) 123 | { 124 | ::testing::InitGoogleTest(&argc, argv); 125 | return RUN_ALL_TESTS(); 126 | } 127 | -------------------------------------------------------------------------------- /test/ros_sec_test/attacks/resources/disk/test_component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "ros_sec_test/attacks/resources/disk/component.hpp" 21 | #include "test_utilities/utility_fixtures.hpp" 22 | 23 | #include "lifecycle_msgs/msg/state.hpp" 24 | #include "lifecycle_msgs/msg/transition.hpp" 25 | #include "rclcpp/executors/single_threaded_executor.hpp" 26 | #include "rclcpp/node.hpp" 27 | 28 | using DiskNode = ros_sec_test::attacks::resources::disk::Component; 29 | using lifecycle_msgs::msg::State; 30 | using lifecycle_msgs::msg::Transition; 31 | using ros_sec_test::test::test_utilities::NodeConfigurationFixture; 32 | 33 | TEST_F(NodeConfigurationFixture, check_configuring_transition) { 34 | auto attack_node = std::make_shared(); 35 | add_node_to_executor(attack_node->get_node_base_interface()); 36 | start_executor(); 37 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 38 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 39 | } 40 | 41 | TEST_F(NodeConfigurationFixture, check_activating_transition) { 42 | auto attack_node = std::make_shared(); 43 | add_node_to_executor(attack_node->get_node_base_interface()); 44 | start_executor(); 45 | attack_node->trigger_transition( 46 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 47 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 48 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 49 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 50 | } 51 | 52 | TEST_F(NodeConfigurationFixture, check_deactivating_transition) { 53 | auto attack_node = std::make_shared(); 54 | add_node_to_executor(attack_node->get_node_base_interface()); 55 | start_executor(); 56 | attack_node->trigger_transition( 57 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 58 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 59 | attack_node->trigger_transition( 60 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 61 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 62 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 63 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 64 | } 65 | 66 | TEST_F(NodeConfigurationFixture, check_cleaningup_transition) { 67 | auto attack_node = std::make_shared(); 68 | add_node_to_executor(attack_node->get_node_base_interface()); 69 | start_executor(); 70 | attack_node->trigger_transition( 71 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 72 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 73 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 74 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 75 | } 76 | 77 | TEST_F(NodeConfigurationFixture, check_unconfigured_shuttingdown_transition) { 78 | auto attack_node = std::make_shared(); 79 | add_node_to_executor(attack_node->get_node_base_interface()); 80 | start_executor(); 81 | attack_node->trigger_transition( 82 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 83 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 84 | attack_node->trigger_transition( 85 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)); 86 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->get_current_state().id()); 87 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 88 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 89 | } 90 | 91 | TEST_F(NodeConfigurationFixture, check_active_shuttingdown_transition) { 92 | auto attack_node = std::make_shared(); 93 | add_node_to_executor(attack_node->get_node_base_interface()); 94 | start_executor(); 95 | attack_node->trigger_transition( 96 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 97 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 98 | attack_node->trigger_transition( 99 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 100 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 101 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 102 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id()); 103 | } 104 | 105 | TEST_F(NodeConfigurationFixture, check_full_node_lifecycle) { 106 | auto attack_node = std::make_shared(); 107 | add_node_to_executor(attack_node->get_node_base_interface()); 108 | start_executor(); 109 | 110 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 111 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 112 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 113 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 114 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 115 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 116 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 117 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 118 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 119 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 120 | } 121 | 122 | int main(int argc, char ** argv) 123 | { 124 | ::testing::InitGoogleTest(&argc, argv); 125 | return RUN_ALL_TESTS(); 126 | } 127 | -------------------------------------------------------------------------------- /test/ros_sec_test/attacks/resources/memory/test_component.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "ros_sec_test/attacks/resources/memory/component.hpp" 21 | #include "test_utilities/utility_fixtures.hpp" 22 | 23 | #include "lifecycle_msgs/msg/state.hpp" 24 | #include "lifecycle_msgs/msg/transition.hpp" 25 | #include "rclcpp/executors/single_threaded_executor.hpp" 26 | #include "rclcpp/node.hpp" 27 | 28 | using MemoryNode = ros_sec_test::attacks::resources::memory::Component; 29 | using lifecycle_msgs::msg::State; 30 | using lifecycle_msgs::msg::Transition; 31 | using ros_sec_test::test::test_utilities::NodeConfigurationFixture; 32 | 33 | TEST_F(NodeConfigurationFixture, check_configuring_transition) { 34 | auto attack_node = std::make_shared(0); 35 | add_node_to_executor(attack_node->get_node_base_interface()); 36 | start_executor(); 37 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 38 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 39 | } 40 | 41 | TEST_F(NodeConfigurationFixture, check_activating_transition) { 42 | auto attack_node = std::make_shared(0); 43 | add_node_to_executor(attack_node->get_node_base_interface()); 44 | start_executor(); 45 | attack_node->trigger_transition( 46 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 47 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 48 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 49 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 50 | } 51 | 52 | TEST_F(NodeConfigurationFixture, check_deactivating_transition) { 53 | auto attack_node = std::make_shared(0); 54 | add_node_to_executor(attack_node->get_node_base_interface()); 55 | start_executor(); 56 | attack_node->trigger_transition( 57 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 58 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 59 | attack_node->trigger_transition( 60 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 61 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 62 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 63 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 64 | } 65 | 66 | TEST_F(NodeConfigurationFixture, check_cleaningup_transition) { 67 | auto attack_node = std::make_shared(0); 68 | add_node_to_executor(attack_node->get_node_base_interface()); 69 | start_executor(); 70 | attack_node->trigger_transition( 71 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 72 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 73 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 74 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 75 | } 76 | 77 | TEST_F(NodeConfigurationFixture, check_unconfigured_shuttingdown_transition) { 78 | auto attack_node = std::make_shared(0); 79 | add_node_to_executor(attack_node->get_node_base_interface()); 80 | start_executor(); 81 | attack_node->trigger_transition( 82 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 83 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 84 | attack_node->trigger_transition( 85 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)); 86 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->get_current_state().id()); 87 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 88 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 89 | } 90 | 91 | TEST_F(NodeConfigurationFixture, check_active_shuttingdown_transition) { 92 | auto attack_node = std::make_shared(0); 93 | add_node_to_executor(attack_node->get_node_base_interface()); 94 | start_executor(); 95 | attack_node->trigger_transition( 96 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)); 97 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->get_current_state().id()); 98 | attack_node->trigger_transition( 99 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)); 100 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->get_current_state().id()); 101 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 102 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id()); 103 | } 104 | 105 | TEST_F(NodeConfigurationFixture, check_full_node_lifecycle) { 106 | auto attack_node = std::make_shared(0); 107 | add_node_to_executor(attack_node->get_node_base_interface()); 108 | start_executor(); 109 | 110 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 111 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id()); 112 | ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, attack_node->trigger_transition( 113 | rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id()); 114 | ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, attack_node->trigger_transition( 115 | rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id()); 116 | ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, attack_node->trigger_transition( 117 | rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id()); 118 | ASSERT_EQ(State::PRIMARY_STATE_FINALIZED, attack_node->trigger_transition( 119 | rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id()); 120 | } 121 | 122 | int main(int argc, char ** argv) 123 | { 124 | ::testing::InitGoogleTest(&argc, argv); 125 | return RUN_ALL_TESTS(); 126 | } 127 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(ros_sec_test) 4 | 5 | # Default to C++14 6 | if(NOT CMAKE_CXX_STANDARD) 7 | set(CMAKE_CXX_STANDARD 14) 8 | endif() 9 | 10 | find_package(ament_cmake REQUIRED) 11 | find_package(class_loader REQUIRED) 12 | find_package(geometry_msgs) 13 | find_package(lifecycle_msgs REQUIRED) 14 | find_package(rclcpp REQUIRED) 15 | find_package(rclcpp_components REQUIRED) 16 | find_package(rclcpp_lifecycle REQUIRED) 17 | find_package(rcutils REQUIRED) 18 | find_package(rcpputils REQUIRED) 19 | 20 | # Enable strict compiler flags if possible. 21 | include(CheckCXXCompilerFlag) 22 | set(FLAGS -pedantic -Wno-long-long -Wall -Wextra -Wcast-align -Wcast-qual -Wformat -Wwrite-strings -Wconversion) 23 | foreach(FLAG ${FLAGS}) 24 | check_cxx_compiler_flag(${FLAG} R${FLAG}) 25 | if(${R${FLAG}}) 26 | set(WARNING_CXX_FLAGS "${WARNING_CXX_FLAGS} ${FLAG}") 27 | endif() 28 | endforeach() 29 | 30 | if(NOT DEFINED CXX_DISABLE_WERROR) 31 | set(WARNING_CXX_FLAGS "-Werror ${WARNING_CXX_FLAGS}") 32 | endif() 33 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_CXX_FLAGS}") 34 | 35 | include_directories( 36 | include 37 | src # For private headers 38 | ${lifecycle_msgs_INCLUDE_DIRS} 39 | ${rclcpp_INCLUDE_DIRS} 40 | ${rclcpp_lifecycle_INCLUDE_DIRS} 41 | ${rcpputils_INCLUDE_DIRS} 42 | ) 43 | 44 | # This package contains multiple targets: 45 | # 46 | # ros_sec_utility <- ros_sec_attacks <- runner 47 | # (all attacks) <-/ 48 | 49 | # Define utility library containing all the shared code. 50 | add_library( 51 | ros_sec_test_utilities 52 | SHARED 53 | src/utilities/lifecycle_service_client.cpp 54 | src/utilities/service_utils.cpp 55 | ) 56 | ament_target_dependencies(ros_sec_test_utilities "rclcpp" "rclcpp_lifecycle") 57 | 58 | add_library( 59 | periodic_attack_component 60 | SHARED 61 | src/attacks/periodic_attack_component.cpp 62 | ) 63 | # Define all attacks. 64 | function(custom_component target file_path component) 65 | add_library(${target} SHARED ${file_path}) 66 | target_compile_definitions(${target} 67 | PRIVATE "COMPOSITION_BUILDING_DLL") 68 | ament_target_dependencies(${target} "class_loader") 69 | rclcpp_components_register_nodes(${target} ${component}) 70 | endfunction() 71 | 72 | custom_component( 73 | noop_component src/attacks/noop/component.cpp 74 | ros_sec_test::attacks::noop::Component) 75 | custom_component( 76 | cpu_component src/attacks/resources/cpu/component.cpp 77 | ros_sec_test::attacks::resources::cpu::Component) 78 | target_link_libraries( 79 | cpu_component 80 | periodic_attack_component 81 | ) 82 | custom_component( 83 | disk_component src/attacks/resources/disk/component.cpp 84 | ros_sec_test::attacks::resources::disk::Component) 85 | target_link_libraries( 86 | disk_component 87 | periodic_attack_component 88 | ) 89 | custom_component( 90 | memory_component src/attacks/resources/memory/component.cpp 91 | ros_sec_test::attacks::resources::memory::Component) 92 | target_link_libraries( 93 | memory_component 94 | periodic_attack_component 95 | ) 96 | # Define the attack library containing all attack nodes and the factory. 97 | add_library( 98 | ros_sec_test_attacks 99 | SHARED 100 | src/attacks/factory_utils.cpp 101 | ) 102 | target_link_libraries( 103 | ros_sec_test_attacks 104 | noop_component 105 | cpu_component 106 | disk_component 107 | memory_component 108 | ) 109 | ament_target_dependencies(ros_sec_test_attacks "class_loader" "rclcpp" "rclcpp_lifecycle") 110 | 111 | # Define the runner node that manages executing attacks 112 | add_library( 113 | runner 114 | src/runner/runner.cpp 115 | ) 116 | target_link_libraries( 117 | runner 118 | ros_sec_test_attacks 119 | ros_sec_test_utilities 120 | ) 121 | ament_target_dependencies(runner "rclcpp" "rclcpp_lifecycle") 122 | 123 | install(TARGETS 124 | ros_sec_test_attacks 125 | ros_sec_test_utilities 126 | runner 127 | periodic_attack_component 128 | noop_component 129 | cpu_component 130 | disk_component 131 | memory_component 132 | ARCHIVE DESTINATION lib 133 | LIBRARY DESTINATION lib 134 | RUNTIME DESTINATION bin) 135 | 136 | # Define the main function 137 | add_executable( 138 | ros_sec_test 139 | src/runner/main.cpp 140 | ) 141 | target_link_libraries( 142 | ros_sec_test 143 | runner 144 | ) 145 | ament_target_dependencies(ros_sec_test "rclcpp") 146 | 147 | install(TARGETS ros_sec_test DESTINATION lib/${PROJECT_NAME}) 148 | 149 | install(DIRECTORY examples DESTINATION share/${PROJECT_NAME}) 150 | 151 | if(BUILD_TESTING) 152 | find_package(ament_cmake_gtest REQUIRED) 153 | find_package(ament_cmake_gmock REQUIRED) 154 | find_package(ament_lint_auto REQUIRED) 155 | ament_lint_auto_find_test_dependencies() 156 | 157 | ament_find_gmock() 158 | add_library( 159 | test_utilities 160 | SHARED 161 | test/test_utilities/utility_fixtures.cpp 162 | ) 163 | target_include_directories(test_utilities PUBLIC ${PROJECT_SOURCE_DIR}/test/include) 164 | 165 | ament_add_gtest(test_service_utils test/ros_sec_test/utilities/test_service_utils.cpp) 166 | target_link_libraries(test_service_utils ros_sec_test_utilities) 167 | 168 | ament_add_gtest(test_client_utils test/ros_sec_test/utilities/test_client_utils.cpp) 169 | target_link_libraries(test_client_utils ros_sec_test_utilities) 170 | 171 | ament_add_gmock(test_runner test/ros_sec_test/runner/test_runner.cpp) 172 | target_link_libraries(test_runner runner periodic_attack_component test_utilities) 173 | 174 | ament_add_gtest(test_attack_noop test/ros_sec_test/attacks/noop/test_component.cpp) 175 | target_link_libraries(test_attack_noop noop_component ros_sec_test_utilities test_utilities) 176 | 177 | ament_add_gtest(test_attack_resources_cpu test/ros_sec_test/attacks/resources/cpu/test_component.cpp) 178 | target_link_libraries(test_attack_resources_cpu cpu_component ros_sec_test_attacks ros_sec_test_utilities test_utilities) 179 | 180 | ament_add_gtest(test_attack_resources_disk test/ros_sec_test/attacks/resources/disk/test_component.cpp) 181 | target_link_libraries(test_attack_resources_disk disk_component ros_sec_test_attacks ros_sec_test_utilities test_utilities) 182 | 183 | ament_add_gtest(test_attack_resources_memory test/ros_sec_test/attacks/resources/memory/test_component.cpp) 184 | target_link_libraries(test_attack_resources_memory memory_component ros_sec_test_attacks ros_sec_test_utilities test_utilities) 185 | endif() 186 | 187 | # since the package installs libraries without exporting them 188 | # it needs to make sure that the library path is being exported 189 | if(NOT WIN32) 190 | ament_environment_hooks( 191 | "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}") 192 | endif() 193 | 194 | ament_package() 195 | -------------------------------------------------------------------------------- /src/runner/runner.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "runner/runner.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "lifecycle_msgs/msg/state.hpp" 23 | #include "rclcpp/logger.hpp" 24 | #include "rclcpp_lifecycle/lifecycle_node.hpp" 25 | #include "rclcpp_lifecycle/state.hpp" 26 | #include "ros_sec_test/attacks/factory_utils.hpp" 27 | 28 | using rclcpp::ParameterValue; 29 | using LifecycleServiceClient = ros_sec_test::utilities::LifecycleServiceClient; 30 | using ros_sec_test::attacks::build_attack_node_from_name; 31 | 32 | static const char * const kAttackNodeNamesParameter = "attack_nodes"; 33 | static const char * const kAttackDurationParameter = "attack_duration"; 34 | 35 | // By default, do not run any attack and print a message explaining to the user how 36 | // to use the node. 37 | static const std::vector kDefaultAttackNodeNames = {}; 38 | // By default runs indefinitely 39 | static const int kDefaultAttackDurationSeconds = 0; 40 | 41 | namespace ros_sec_test 42 | { 43 | namespace runner 44 | { 45 | 46 | Runner::Runner() 47 | : node_(rclcpp::Node::make_shared("attacker_node", "", 48 | rclcpp::NodeOptions().use_intra_process_comms(true))), 49 | attack_nodes_(), 50 | executor_(), 51 | logger_(rclcpp::get_logger("Runner")) 52 | { 53 | RCLCPP_INFO(logger_, "Initializing Runner"); 54 | node_->declare_parameter(kAttackNodeNamesParameter, ParameterValue(kDefaultAttackNodeNames)); 55 | executor_.add_node(node_); 56 | const auto node_names = retrieve_attack_nodes_names(); 57 | if (node_names.empty()) { 58 | warn_user_no_attack_nodes_passed(); 59 | } else { 60 | initialize_attack_nodes(node_names); 61 | } 62 | } 63 | 64 | Runner::Runner(const std::vector & attack_nodes) 65 | : node_(rclcpp::Node::make_shared("attacker_node", "", 66 | rclcpp::NodeOptions().use_intra_process_comms(true))), 67 | attack_nodes_(), 68 | executor_(), 69 | logger_(rclcpp::get_logger("Runner")) 70 | { 71 | RCLCPP_INFO(logger_, "Initializing Runner"); 72 | executor_.add_node(node_); 73 | if (attack_nodes.empty()) { 74 | warn_user_no_attack_nodes_passed(); 75 | } else { 76 | for (const auto & attack_node : attack_nodes) { 77 | AttackNodeData node_data = { 78 | attack_node, 79 | std::make_shared(node_.get(), attack_node->get_name()) 80 | }; 81 | attack_nodes_.emplace_back(std::move(node_data)); 82 | executor_.add_node(attack_node->get_node_base_interface()); 83 | RCLCPP_INFO(logger_, "Adding attack node '%s'", attack_node->get_name()); 84 | } 85 | } 86 | } 87 | 88 | std::future Runner::execute_all_attacks_async() 89 | { 90 | return std::async(std::launch::async, 91 | [this]() {start_and_stop_all_nodes();}); 92 | } 93 | 94 | void Runner::initialize_attack_nodes(const std::vector & node_names) 95 | { 96 | for (const auto & node_name : node_names) { 97 | auto attack_node = build_attack_node_from_name(node_name); 98 | if (attack_node) { 99 | AttackNodeData node_data = { 100 | attack_node, 101 | std::make_shared(node_.get(), node_name) 102 | }; 103 | attack_nodes_.emplace_back(std::move(node_data)); 104 | executor_.add_node(attack_node->get_node_base_interface()); 105 | RCLCPP_INFO(logger_, "Adding attack node '%s'", node_name.c_str()); 106 | } 107 | } 108 | } 109 | 110 | std::vector Runner::retrieve_attack_nodes_names() 111 | { 112 | return node_->get_parameter(kAttackNodeNamesParameter).as_string_array(); 113 | } 114 | 115 | std::chrono::seconds Runner::retrieve_attack_duration_s() 116 | { 117 | node_->declare_parameter(kAttackDurationParameter, ParameterValue(kDefaultAttackDurationSeconds)); 118 | return std::chrono::seconds(node_->get_parameter(kAttackDurationParameter).as_int()); 119 | } 120 | 121 | void Runner::spin() 122 | { 123 | RCLCPP_INFO(logger_, "Spinning started"); 124 | std::shared_future attack_result_future = execute_all_attacks_async(); 125 | executor_.spin_until_future_complete(attack_result_future); 126 | RCLCPP_INFO(logger_, "Spinning finished"); 127 | } 128 | 129 | void Runner::start_and_stop_all_nodes() 130 | { 131 | for (const auto & node_data : attack_nodes_) { 132 | RCLCPP_INFO(logger_, "Configuring attack node '%s'", node_data.node->get_name()); 133 | auto & client = node_data.lifecycle_client; 134 | if (!client->configure() || 135 | client->get_state().id() == lifecycle_msgs::msg::State::TRANSITION_STATE_CONFIGURING) 136 | { 137 | return; 138 | } 139 | } 140 | for (const auto & node_data : attack_nodes_) { 141 | RCLCPP_INFO(logger_, "Enabling attack node '%s'", node_data.node->get_name()); 142 | auto & client = node_data.lifecycle_client; 143 | if (!client->activate() || 144 | client->get_state().id() == lifecycle_msgs::msg::State::TRANSITION_STATE_ACTIVATING) 145 | { 146 | return; 147 | } 148 | } 149 | auto attack_duration = retrieve_attack_duration_s(); 150 | RCLCPP_INFO(logger_, "Attack duration set to %d", attack_duration.count()); 151 | if (0 > attack_duration.count()) { 152 | while (rclcpp::ok()) { 153 | rclcpp::sleep_for(std::chrono::seconds(1)); 154 | } 155 | } else { 156 | rclcpp::sleep_for(attack_duration); 157 | } 158 | for (const auto & node_data : attack_nodes_) { 159 | RCLCPP_INFO(logger_, "Shutting-down attack node '%s'", node_data.node->get_name()); 160 | auto & client = node_data.lifecycle_client; 161 | if (!client->shutdown() || 162 | client->get_state().id() == lifecycle_msgs::msg::State::TRANSITION_STATE_SHUTTINGDOWN) 163 | { 164 | return; 165 | } 166 | } 167 | } 168 | 169 | void Runner::warn_user_no_attack_nodes_passed() 170 | { 171 | RCLCPP_WARN(logger_, 172 | "%s", 173 | "No attack specified. This node will not no anything.\n" 174 | "Please re-start this node and specify the list of attacks to execute:\n" 175 | "$ ros2 run ros_sec_test runner __params:=params.yaml\n" 176 | "\n" 177 | "params.yaml:\n" 178 | "attacker_node:\n" 179 | " ros__parameters:\n" 180 | " attack_nodes:\n" 181 | " - 'noop'\n" 182 | "\n" 183 | "The available attacks are 'noop' and 'resources/disk'.\n" 184 | ); 185 | } 186 | 187 | } // namespace runner 188 | } // namespace ros_sec_test 189 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------