diff --git a/test/blackbox/api/dds-pim/PubSubReader.hpp b/test/blackbox/api/dds-pim/PubSubReader.hpp index b7e267c1724..136286df750 100644 --- a/test/blackbox/api/dds-pim/PubSubReader.hpp +++ b/test/blackbox/api/dds-pim/PubSubReader.hpp @@ -858,18 +858,31 @@ class PubSubReader } #if HAVE_SECURITY - void waitAuthorized() + void waitAuthorized( + std::chrono::seconds timeout = std::chrono::seconds::zero(), + unsigned int expected = 1) { std::unique_lock lock(mutexAuthentication_); std::cout << "Reader is waiting authorization..." << std::endl; - cvAuthentication_.wait(lock, [&]() -> bool - { - return authorized_ > 0; - }); + if (timeout == std::chrono::seconds::zero()) + { + cvAuthentication_.wait(lock, [&]() + { + std::cout << "authorized " << authorized_ << " expected " << expected << std::endl; + return authorized_ >= expected; + }); + } + else + { + cvAuthentication_.wait_for(lock, timeout, [&]() + { + return authorized_ >= expected; + }); + } - std::cout << "Reader authorization finished..." << std::endl; + std::cout << "Reader authorization finished" << std::endl; } void waitUnauthorized() @@ -1173,6 +1186,15 @@ class PubSubReader return *this; } + PubSubReader& participants_allocation_properties( + size_t initial, + size_t maximum) + { + participant_qos_.allocation().participants.initial = initial; + participant_qos_.allocation().participants.maximum = maximum; + return *this; + } + PubSubReader& expect_no_allocs() { // TODO(Mcc): Add no allocations check code when feature is completely ready diff --git a/test/blackbox/api/dds-pim/PubSubWriter.hpp b/test/blackbox/api/dds-pim/PubSubWriter.hpp index 61bffb036b8..7793323d964 100644 --- a/test/blackbox/api/dds-pim/PubSubWriter.hpp +++ b/test/blackbox/api/dds-pim/PubSubWriter.hpp @@ -743,18 +743,30 @@ class PubSubWriter } #if HAVE_SECURITY - void waitAuthorized() + void waitAuthorized( + std::chrono::seconds timeout = std::chrono::seconds::zero(), + unsigned int expected = 1) { std::unique_lock lock(mutexAuthentication_); std::cout << "Writer is waiting authorization..." << std::endl; - cvAuthentication_.wait(lock, [&]() -> bool - { - return authorized_ > 0; - }); + if (timeout == std::chrono::seconds::zero()) + { + cvAuthentication_.wait(lock, [&]() + { + return matched_ >= expected; + }); + } + else + { + cvAuthentication_.wait_for(lock, timeout, [&]() + { + return matched_ >= expected; + }); + } - std::cout << "Writer authorization finished..." << std::endl; + std::cout << "Writer authorization finished" << std::endl; } void waitUnauthorized() @@ -1137,6 +1149,15 @@ class PubSubWriter return *this; } + PubSubWriter& participants_allocation_properties( + size_t initial, + size_t maximum) + { + participant_qos_.allocation().participants.initial = initial; + participant_qos_.allocation().participants.maximum = maximum; + return *this; + } + PubSubWriter& expect_no_allocs() { // TODO(Mcc): Add no allocations check code when feature is completely ready diff --git a/test/blackbox/common/BlackboxTestsSecurity.cpp b/test/blackbox/common/BlackboxTestsSecurity.cpp index 18fc959a0d6..59a77722463 100644 --- a/test/blackbox/common/BlackboxTestsSecurity.cpp +++ b/test/blackbox/common/BlackboxTestsSecurity.cpp @@ -3530,11 +3530,11 @@ TEST_F(SecurityPkcs, BuiltinAuthenticationAndAccessAndCryptoPlugin_pkcs11_key) static void CommonPermissionsConfigure( PubSubReader& reader, - PubSubWriter& writer, const std::string& governance_file, - const std::string& permissions_file) + const std::string& permissions_file, + const PropertyPolicy& extra_properties) { - PropertyPolicy sub_property_policy; + PropertyPolicy sub_property_policy(extra_properties); sub_property_policy.properties().emplace_back(Property("dds.sec.auth.plugin", "builtin.PKI-DH")); sub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.identity_ca", @@ -3553,9 +3553,18 @@ static void CommonPermissionsConfigure( "file://" + std::string(certs_path) + "/" + governance_file)); sub_property_policy.properties().emplace_back(Property("dds.sec.access.builtin.Access-Permissions.permissions", "file://" + std::string(certs_path) + "/" + permissions_file)); + reader.property_policy(sub_property_policy); +} + +static void CommonPermissionsConfigure( + PubSubWriter& writer, + const std::string& governance_file, + const std::string& permissions_file, + const PropertyPolicy& extra_properties) +{ + PropertyPolicy pub_property_policy(extra_properties); - PropertyPolicy pub_property_policy; pub_property_policy.properties().emplace_back(Property("dds.sec.auth.plugin", "builtin.PKI-DH")); pub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.identity_ca", @@ -3574,9 +3583,21 @@ static void CommonPermissionsConfigure( "file://" + std::string(certs_path) + "/" + governance_file)); pub_property_policy.properties().emplace_back(Property("dds.sec.access.builtin.Access-Permissions.permissions", "file://" + std::string(certs_path) + "/" + permissions_file)); + writer.property_policy(pub_property_policy); } +static void CommonPermissionsConfigure( + PubSubReader& reader, + PubSubWriter& writer, + const std::string& governance_file, + const std::string& permissions_file, + const PropertyPolicy& extra_properties = PropertyPolicy()) +{ + CommonPermissionsConfigure(reader, governance_file, permissions_file, extra_properties); + CommonPermissionsConfigure(writer, governance_file, permissions_file, extra_properties); +} + static void BuiltinAuthenticationAndAccessAndCryptoPlugin_Permissions_validation_ok_common( PubSubReader& reader, PubSubWriter& writer, @@ -5088,6 +5109,87 @@ TEST(Security, security_with_initial_peers_over_tcpv4_correctly_behaves) tcp_server.block_for_all(std::chrono::seconds(10)); } +// Regression test for Redmine issue #22033 +// Authorized participants shall remove the changes from the +// participants secure stateless msgs pool +TEST(Security, participant_stateless_secure_writer_pool_change_is_removed_upon_participant_authentication) +{ + struct TestConsumer : public eprosima::fastdds::dds::LogConsumer + { + TestConsumer( + std::atomic_size_t& n_logs_ref) + : n_logs_(n_logs_ref) + { + } + + void Consume( + const eprosima::fastdds::dds::Log::Entry&) override + { + ++n_logs_; + } + + private: + + std::atomic_size_t& n_logs_; + }; + + // Counter for log entries + std::atomicn_logs{}; + + // Prepare Log module to check that no SECURITY errors are produced + eprosima::fastdds::dds::Log::SetCategoryFilter(std::regex("SECURITY")); + eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); + eprosima::fastdds::dds::Log::RegisterConsumer(std::unique_ptr(new TestConsumer( + n_logs))); + + const size_t n_participants = 20; + + // Create 21 secure participants + std::vector>> participants; + participants.reserve(n_participants + 1); + + for (size_t i = 0; i < n_participants + 1; ++i) + { + participants.emplace_back(std::make_shared>("HelloWorldTopic")); + // Configure security + const std::string governance_file("governance_helloworld_all_enable.smime"); + const std::string permissions_file("permissions_helloworld.smime"); + + PropertyPolicy handshake_prop_policy; + + handshake_prop_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.max_handshake_requests", + "10000000")); + handshake_prop_policy.properties().emplace_back(Property( + "dds.sec.auth.builtin.PKI-DH.initial_handshake_resend_period", + "250")); + handshake_prop_policy.properties().emplace_back(Property( + "dds.sec.auth.builtin.PKI-DH.handshake_resend_period_gain", + "1.0")); + + CommonPermissionsConfigure(*participants.back(), governance_file, permissions_file, handshake_prop_policy); + + // Init all except the latest one + if (i != n_participants) + { + participants.back()->init(); + ASSERT_TRUE(participants.back()->isInitialized()); + } + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + + // Wait for the first participant to authenticate the rest + participants.front()->waitAuthorized(std::chrono::seconds::zero(), n_participants - 1); + + // Init the last one + participants.back()->init(); + ASSERT_TRUE(participants.back()->isInitialized()); + + participants.front()->waitAuthorized(std::chrono::seconds::zero(), n_participants); + + // No SECURITY error logs should have been produced + eprosima::fastdds::dds::Log::Flush(); + EXPECT_EQ(0u, n_logs); +} void blackbox_security_init() {