From 700193cd0946aaaf2bcac4b9fbfd8f61206967dd Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 5 Dec 2014 23:54:02 +0100 Subject: [PATCH 01/16] Serialize AdminCheckResponse by ProtocolAdmin Add serialization and deserialization of AdminCheckResponse by ProtocolAdmin. Change-Id: I727c44f5a599537887d75dca724c56a448107368 --- src/common/protocol/ProtocolAdmin.cpp | 38 +++++++++++++++++++++++++++++++++++ src/common/protocol/ProtocolAdmin.h | 2 ++ src/common/protocol/ProtocolOpCode.h | 3 ++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 0d646a4..2c1164e 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,24 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { return nullptr; } +ResponsePtr ProtocolAdmin::deserializeAdminCheckResponse(void) { + PolicyType result; + PolicyResult::PolicyMetadata additionalInfo; + bool bucketValid; + + ProtocolDeserialization::deserialize(m_frameHeader, result); + ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo); + ProtocolDeserialization::deserialize(m_frameHeader, bucketValid); + + const PolicyResult policyResult(result, additionalInfo); + + LOGD("Deserialized AdminCheckResponse: result [%" PRIu16 "], metadata <%s>, bucketValid [%d]", + policyResult.policyType(), policyResult.metadata().c_str(), static_cast(bucketValid)); + + return std::make_shared(policyResult, bucketValid, + m_frameHeader.sequenceNumber()); +} + ResponsePtr ProtocolAdmin::deserializeCheckResponse(void) { PolicyType result; PolicyResult::PolicyMetadata additionalInfo; @@ -264,6 +283,8 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) ProtocolDeserialization::deserialize(m_frameHeader, opCode); LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { + case OpAdminCheckPolicyResponse: + return deserializeAdminCheckResponse(); case OpCheckPolicyResponse: return deserializeCheckResponse(); case OpCodeResponse: @@ -386,6 +407,23 @@ void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr req ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } +void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckResponsePtr response) { + LOGD("Serializing AdminCheckResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " + "policyType [%" PRIu16 "], metadata <%s>, bucketValid [%d]", OpAdminCheckPolicyResponse, + response->sequenceNumber(), response->result().policyType(), + response->result().metadata().c_str(), static_cast(response->isBucketValid())); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( + response->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpAdminCheckPolicyResponse); + ProtocolSerialization::serialize(frame, response->result().policyType()); + ProtocolSerialization::serialize(frame, response->result().metadata()); + ProtocolSerialization::serialize(frame, response->isBucketValid()); + + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); +} + void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response) { LOGD("Serializing CheckResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " "policyType [%" PRIu16 "], metadata <%s>", OpCheckPolicyResponse, diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index 48421be..1454be2 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -44,6 +44,7 @@ public: virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); + virtual void execute(RequestContextPtr context, AdminCheckResponsePtr response); virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); virtual void execute(RequestContextPtr context, ListResponsePtr response); @@ -55,6 +56,7 @@ private: RequestPtr deserializeRemoveBucketRequest(void); RequestPtr deserializeSetPoliciesRequest(void); + ResponsePtr deserializeAdminCheckResponse(void); ResponsePtr deserializeCheckResponse(void); ResponsePtr deserializeCodeResponse(void); ResponsePtr deserializeListResponse(void); diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index 69be21c..984ddef 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -47,8 +47,9 @@ enum ProtocolOpCode : uint8_t { OpAdminCheckRequest, OpListRequest, OpListResponse, + OpAdminCheckPolicyResponse, - /** Opcodes 27 - 39 are reserved for future use */ + /** Opcodes 28 - 39 are reserved for future use */ /** Agent operations */ OpAgentRegisterRequest = 40, -- 2.7.4 From 6566b149fe740e5f4347da1df4c579bbfb1979ce Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 6 Dec 2014 00:37:20 +0100 Subject: [PATCH 02/16] Respond to AdminCheckRequest with AdminCheckResponse Change implementation of both service and admin library Logic layers so they use AdminCheckResponse instead of CheckResponse as a reply for AdminCheckRequest. This change allows passing additional information about existence or vacancy of start bucket given in AdminCheckRequest. In case of vacancy of such bucket in cynara database cynara-admin library returns CYNARA_API_BUCKET_NOT_FOUND from cynara_admin_check() function. This fixes also a bug that was hidden in service Logic. Passing unexisting bucket causes cynara service to stop because of an unhandled exception. Change-Id: Ibf65a69c35ba92ea62bee91a67f43975b97052ca --- src/admin/logic/Logic.cpp | 24 +++++++++++++++--------- src/common/protocol/ProtocolAdmin.cpp | 34 ---------------------------------- src/common/protocol/ProtocolAdmin.h | 2 -- src/service/logic/Logic.cpp | 13 ++++++++++--- 4 files changed, 25 insertions(+), 48 deletions(-) diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 6648189..7fef282 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -132,7 +132,7 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); //Ask cynara service - CheckResponsePtr checkResponse; + AdminCheckResponsePtr adminCheckResponse; RequestPtr request = std::make_shared(key, startBucket, recursive, sequenceNumber); @@ -142,17 +142,23 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P return CYNARA_API_SERVICE_NOT_AVAILABLE; } - checkResponse = std::dynamic_pointer_cast(response); - if (!checkResponse) { - LOGC("Casting Response to CheckResponse failed."); + adminCheckResponse = std::dynamic_pointer_cast(response); + if (!adminCheckResponse) { + LOGC("Casting Response to AdminCheckResponse failed."); return CYNARA_API_UNKNOWN_ERROR; } - LOGD("checkResponse: policyType [%" PRIu16 "], metadata <%s>", - checkResponse->m_resultRef.policyType(), - checkResponse->m_resultRef.metadata().c_str()); + LOGD("AdminCheckResponse: policyType [%" PRIu16 "], metadata <%s>, bucketValid [%d]", + adminCheckResponse->result().policyType(), adminCheckResponse->result().metadata().c_str(), + static_cast(adminCheckResponse->isBucketValid())); - result = checkResponse->m_resultRef; + if (!adminCheckResponse->isBucketValid()) { + LOGE("Bucket <%s> provided as startBucket in adminCheck does not exist in cynara database", + startBucket.c_str()); + return CYNARA_API_BUCKET_NOT_FOUND; + } + + result = adminCheckResponse->result(); return CYNARA_API_SUCCESS; } diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 2c1164e..293db97 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -216,21 +215,6 @@ ResponsePtr ProtocolAdmin::deserializeAdminCheckResponse(void) { m_frameHeader.sequenceNumber()); } -ResponsePtr ProtocolAdmin::deserializeCheckResponse(void) { - PolicyType result; - PolicyResult::PolicyMetadata additionalInfo; - - ProtocolDeserialization::deserialize(m_frameHeader, result); - ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo); - - const PolicyResult policyResult(result, additionalInfo); - - LOGD("Deserialized CheckResponse: result [%" PRIu16 "], metadata <%s>", - policyResult.policyType(), policyResult.metadata().c_str()); - - return std::make_shared(policyResult, m_frameHeader.sequenceNumber()); -} - ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) { ProtocolResponseCode responseCode; ProtocolDeserialization::deserialize(m_frameHeader, responseCode); @@ -285,8 +269,6 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) switch (opCode) { case OpAdminCheckPolicyResponse: return deserializeAdminCheckResponse(); - case OpCheckPolicyResponse: - return deserializeCheckResponse(); case OpCodeResponse: return deserializeCodeResponse(); case OpListResponse: @@ -424,22 +406,6 @@ void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckResponsePtr res ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } -void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response) { - LOGD("Serializing CheckResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " - "policyType [%" PRIu16 "], metadata <%s>", OpCheckPolicyResponse, - response->sequenceNumber(), response->m_resultRef.policyType(), - response->m_resultRef.metadata().c_str()); - - ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( - response->sequenceNumber()); - - ProtocolSerialization::serialize(frame, OpCheckPolicyResponse); - ProtocolSerialization::serialize(frame, response->m_resultRef.policyType()); - ProtocolSerialization::serialize(frame, response->m_resultRef.metadata()); - - ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); -} - void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) { LOGD("Serializing CodeResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " "code [%" PRIu16 "]", OpCodeResponse, response->sequenceNumber(), response->m_code); diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index 1454be2..b9c7e17 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -45,7 +45,6 @@ public: virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); virtual void execute(RequestContextPtr context, AdminCheckResponsePtr response); - virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); virtual void execute(RequestContextPtr context, ListResponsePtr response); @@ -57,7 +56,6 @@ private: RequestPtr deserializeSetPoliciesRequest(void); ResponsePtr deserializeAdminCheckResponse(void); - ResponsePtr deserializeCheckResponse(void); ResponsePtr deserializeCodeResponse(void); ResponsePtr deserializeListResponse(void); }; diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index 679da17..3445984 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -86,10 +87,16 @@ void Logic::execute(RequestContextPtr context UNUSED, SignalRequestPtr request) } void Logic::execute(RequestContextPtr context, AdminCheckRequestPtr request) { - PolicyResult result = m_storage->checkPolicy(request->key(), request->startBucket(), - request->recursive()); + PolicyResult result; + bool bucketValid = true; + try { + result = m_storage->checkPolicy(request->key(), request->startBucket(), + request->recursive()); + } catch (const BucketNotExistsException &ex) { + bucketValid = false; + } - context->returnResponse(context, std::make_shared(result, + context->returnResponse(context, std::make_shared(result, bucketValid, request->sequenceNumber())); } -- 2.7.4 From 2dff221b30a078f65496d57381ef1f449ffa3f4b Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 6 Dec 2014 01:25:25 +0100 Subject: [PATCH 03/16] Test usage of AdminCheck Req/Resp by ProtocolAdmin Test serialization and deserialization of AdminCheckRequest and AdminCheckResponse objects by ProtocolAdmin. Change-Id: Ia8923dbeaf0d03c29fd77bde3758375df59e1bc6 --- test/CMakeLists.txt | 2 + test/common/protocols/admin/admincheckrequest.cpp | 149 +++++++++++++++++++++ test/common/protocols/admin/admincheckresponse.cpp | 138 +++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 test/common/protocols/admin/admincheckrequest.cpp create mode 100644 test/common/protocols/admin/admincheckresponse.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5bb0a7e..82f26cd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -57,6 +57,8 @@ SET(CYNARA_SOURCES_FOR_TESTS SET(CYNARA_TESTS_SOURCES TestEventListenerProxy.cpp common/exceptions/bucketrecordcorrupted.cpp + common/protocols/admin/admincheckrequest.cpp + common/protocols/admin/admincheckresponse.cpp common/protocols/admin/listrequest.cpp common/protocols/admin/listresponse.cpp common/types/policybucket.cpp diff --git a/test/common/protocols/admin/admincheckrequest.cpp b/test/common/protocols/admin/admincheckrequest.cpp new file mode 100644 index 0000000..d5f1103 --- /dev/null +++ b/test/common/protocols/admin/admincheckrequest.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file test/common/protocols/admin/admincheckrequest.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Tests for Cynara::AdminCheckRequest usage in Cynara::ProtocolAdmin + */ + +#include + +#include +#include + +#include +#include + +namespace { + +template<> +void compare(const Cynara::AdminCheckRequest &req1, const Cynara::AdminCheckRequest &req2) { + EXPECT_EQ(req1.key(), req2.key()); + EXPECT_EQ(req1.startBucket(), req2.startBucket()); + EXPECT_EQ(req1.recursive(), req2.recursive()); +} + +static const bool RECURSIVE = true; +static const bool NON_RECURSIVE = false; + +} /* anonymous namespace */ + +using namespace Cynara; +using namespace RequestTestHelper; +using namespace TestDataCollection; + +/* *** compare by objects test cases *** */ + +TEST(ProtocolAdmin, AdminCheckRequest01) { + auto request = std::make_shared(Keys::k_nun, Buckets::empty, RECURSIVE, + SN::min); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequest02) { + auto request = std::make_shared(Keys::k_cup, Buckets::not_empty, RECURSIVE, + SN::min_1); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequest03) { + auto request = std::make_shared(Keys::k_www, Buckets::empty, NON_RECURSIVE, + SN::min_2); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequest04) { + auto request = std::make_shared(Keys::k_wuw, Buckets::not_empty, + NON_RECURSIVE, SN::max); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequest05) { + auto request = std::make_shared(Keys::k_aaa, Buckets::empty, RECURSIVE, + SN::max_1); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequest06) { + auto request = std::make_shared(Keys::k_wua, Buckets::not_empty, RECURSIVE, + SN::max_2); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequest07) { + auto request = std::make_shared(Keys::k_nua, Buckets::empty, NON_RECURSIVE, + SN::mid); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +/* *** compare by serialized data test cases *** */ + +TEST(ProtocolAdmin, AdminCheckRequestBinary01) { + auto request = std::make_shared(Keys::k_nun, Buckets::empty, RECURSIVE, + SN::min); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequestBinary02) { + auto request = std::make_shared(Keys::k_cup, Buckets::not_empty, RECURSIVE, + SN::min_1); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequestBinary03) { + auto request = std::make_shared(Keys::k_www, Buckets::empty, NON_RECURSIVE, + SN::min_2); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequestBinary04) { + auto request = std::make_shared(Keys::k_wuw, Buckets::not_empty, + NON_RECURSIVE, SN::max); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequestBinary05) { + auto request = std::make_shared(Keys::k_aaa, Buckets::empty, RECURSIVE, + SN::max_1); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequestBinary06) { + auto request = std::make_shared(Keys::k_wua, Buckets::not_empty, RECURSIVE, + SN::max_2); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, AdminCheckRequestBinary07) { + auto request = std::make_shared(Keys::k_nua, Buckets::empty, NON_RECURSIVE, + SN::mid); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} diff --git a/test/common/protocols/admin/admincheckresponse.cpp b/test/common/protocols/admin/admincheckresponse.cpp new file mode 100644 index 0000000..666f65e --- /dev/null +++ b/test/common/protocols/admin/admincheckresponse.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file test/common/protocols/admin/admincheckresponse.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Tests for Cynara::AdminCheckResponse usage in Cynara::ProtocolAdmin + */ + +#include + +#include +#include + +#include +#include + +namespace { + +template<> +void compare(const Cynara::AdminCheckResponse &resp1, const Cynara::AdminCheckResponse &resp2) { + EXPECT_EQ(resp1.result(), resp2.result()); + EXPECT_EQ(resp1.isBucketValid(), resp2.isBucketValid()); +} + +static const bool VALID_BUCKET = true; +static const bool NO_BUCKET = false; + +} /* anonymous namespace */ + +using namespace Cynara; +using namespace ResponseTestHelper; +using namespace TestDataCollection; + +/* *** compare by objects test cases *** */ + +TEST(ProtocolAdmin, AdminCheckResponse01) { + auto response = std::make_shared(Results::allow, VALID_BUCKET, SN::min); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponse02) { + auto response = std::make_shared(Results::deny, NO_BUCKET, SN::min_1); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponse03) { + auto response = std::make_shared(Results::bucket_empty, VALID_BUCKET, + SN::min_2); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponse04) { + auto response = std::make_shared(Results::bucket_not_empty, NO_BUCKET, + SN::max); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponse05) { + auto response = std::make_shared(Results::none, VALID_BUCKET, SN::max_1); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponse06) { + auto response = std::make_shared(Results::plugin_1, NO_BUCKET, SN::max_2); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponse07) { + auto response = std::make_shared(Results::plugin_2, VALID_BUCKET, SN::mid); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +/* *** compare by serialized data test cases *** */ + +TEST(ProtocolAdmin, AdminCheckResponseBinary01) { + auto response = std::make_shared(Results::allow, VALID_BUCKET, SN::min); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponseBinary02) { + auto response = std::make_shared(Results::deny, NO_BUCKET, SN::min_1); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponseBinary03) { + auto response = std::make_shared(Results::bucket_empty, VALID_BUCKET, + SN::min_2); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponseBinary04) { + auto response = std::make_shared(Results::bucket_not_empty, NO_BUCKET, + SN::max); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponseBinary05) { + auto response = std::make_shared(Results::none, VALID_BUCKET, SN::max_1); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponseBinary06) { + auto response = std::make_shared(Results::plugin_1, NO_BUCKET, SN::max_2); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, AdminCheckResponseBinary07) { + auto response = std::make_shared(Results::plugin_2, VALID_BUCKET, SN::mid); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} -- 2.7.4 From 3ff1fd995077fca9ba5af670f8be502561a1a183 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Tue, 2 Dec 2014 13:57:33 +0100 Subject: [PATCH 04/16] build: unbreak out-of-tree build of cynara-db-migration Fix "make install" failing on cynara-db-migration when building out-of-tree. Change-Id: I4a0c90a32e91e25de279d084d3a3801a1f0bb1b2 Signed-off-by: Rafal Krypa --- migration/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/CMakeLists.txt b/migration/CMakeLists.txt index 53e10d5..b9bc9bf 100644 --- a/migration/CMakeLists.txt +++ b/migration/CMakeLists.txt @@ -18,7 +18,7 @@ # INSTALL(FILES - ${CMAKE_BINARY_DIR}/migration/cynara-db-migration.sh + ${CMAKE_SOURCE_DIR}/migration/cynara-db-migration.sh DESTINATION ${SBIN_INSTALL_DIR}/cynara/ ) -- 2.7.4 From cf6e4c6c07592c05478fdb9af161cdef0859b3bd Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 19 Dec 2014 10:57:22 +0100 Subject: [PATCH 05/16] Fix wrong null terminated list deallocation Fixed wrong iteration on null terminated list in deallocating function. Change-Id: I1f344cbfdcf775aedd3f7e0eb00518cfec423bc2 --- src/admin/api/admin-api.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index c2a5212..55fc4db 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -233,14 +233,13 @@ static int createPoliciesArray(const char *bucket, return CYNARA_API_OUT_OF_MEMORY; std::unique_ptr> plumber(tab, [](Elem **tab) { - Elem *elem = *tab; - while (elem) { - free(elem->bucket); - free(elem->client); - free(elem->user); - free(elem->privilege); - free(elem->result_extra); - free(elem++); + for (int i = 0; tab[i] != nullptr; i++) { + free(tab[i]->bucket); + free(tab[i]->client); + free(tab[i]->user); + free(tab[i]->privilege); + free(tab[i]->result_extra); + free(tab[i]); } free(tab); }); -- 2.7.4 From 3da576cb1ee203c475b1d5eb4e7f29f2362f38ee Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 16 Dec 2014 10:24:46 +0100 Subject: [PATCH 06/16] Introduce new admin API function cynara_admin_erase() cynara_admin_erase() can be used to erase multiple policies matching given filter key (client, user, privilege). Erasing starts in given bucket and then can step into nested buckets if recursive flag is enabled. Filter key can use CYNARA_ADMIN_ANY to match any value of client, user or privilege. Change-Id: Ib2eb55e864828b4b073a177bc6fea468ec3911c8 --- src/include/cynara-admin-types.h | 2 +- src/include/cynara-admin.h | 62 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/include/cynara-admin-types.h b/src/include/cynara-admin-types.h index 5978c80..b83c81d 100644 --- a/src/include/cynara-admin-types.h +++ b/src/include/cynara-admin-types.h @@ -67,7 +67,7 @@ struct cynara_admin_policy { * \name Any * definition of ANY, that can replace client, user or privilege name. * ANY matches any string (including WILDCARD) during: - * * policy removal (setPolicies with CYNARA_ADMIN_DELETE) + * * policy removal with cynara_admin_erase() function * * listing policies from a single bucket. * Using ANY as default policy for bucket or as policy type of inserted policy record * is forbidden and will cause CYNARA_API_INVALID_PARAM error. diff --git a/src/include/cynara-admin.h b/src/include/cynara-admin.h index 595ad6a..bb1b8d1 100644 --- a/src/include/cynara-admin.h +++ b/src/include/cynara-admin.h @@ -257,16 +257,16 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin, * * \par Method of function operation: * Policies are arranged into buckets. Every bucket contains set of policies. Each of policies are - * identified with tripple {client, user, privilege}. Function lists all policies from single bucket + * identified with triple {client, user, privilege}. Function lists all policies from single bucket * with matching client, user and privilege names. * * CYNARA_ADMIN_ANY can be used to match any client, user or privilege, e.g. * - * List with paramaters: {client = CYNARA_ADMIN_ANY, user = "alice", privilege = CYNARA_ADMIN_ANY} + * List with parameters: {client = CYNARA_ADMIN_ANY, user = "alice", privilege = CYNARA_ADMIN_ANY} * will match all policies related to "alice", so will match {"app1", "alice", "gps"} and * {CYNARA_ADMIN_WILDCARD, "alice", "sms"}, but won't match {"app3", CYNARA_ADMIN_WILDCARD, "call"}. * - * List with paramaters: {client = "calculator", user = CYNARA_ADMIN_WILDCARD, + * List with parameters: {client = "calculator", user = CYNARA_ADMIN_WILDCARD, * privilege = CYNARA_ADMIN_ANY} will match {"calculator", CYNARA_ADMIN_WILDCARD, "sms"} but won't * match {CYNARA_ADMIN_WILDCARD, CYNARA_ADMIN_WILDCARD, "sms"} nor {"calculator", "bob", "sms"} * @@ -302,6 +302,62 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin, int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char *bucket, const char *client, const char *user, const char *privilege, struct cynara_admin_policy ***policies); + +/** + * \par Description: + * Erase policies matching filter from cynara database. + * + * \par Purpose: + * This API should be used to erase multiple policies with some common key part, + * e.g. all policies related to given user. + * + * \par Typical use case: + * Erase all policies matching defined filter. + * + * \par Method of function operation: + * Policies are arranged into buckets. Every bucket contains set of policies. Each of policies are + * identified with triple {client, user, privilege}. Function erases all policies with matching + * client, user and privilege names. + * + * There are two modes: + * * non-recursive (recursive parameter set to 0) - when policies are erased only from single bucket + * * recursive (recursive parameter set to 1) when policies are removed from given start_bucket and + * all nested buckets. + * + * CYNARA_ADMIN_ANY can be used to match any client, user or privilege, e.g. + * + * Erase with parameters: {client = CYNARA_ADMIN_ANY, user = "alice", privilege = CYNARA_ADMIN_ANY} + * will match all policies related to "alice", so will match {"app1", "alice", "gps"} and + * {CYNARA_ADMIN_WILDCARD, "alice", "sms"}, but won't match {"app3", CYNARA_ADMIN_WILDCARD, "call"}. + * + * Erase with parameters: {client = "calculator", user = CYNARA_ADMIN_WILDCARD, + * privilege = CYNARA_ADMIN_ANY} will match {"calculator", CYNARA_ADMIN_WILDCARD, "sms"} but won't + * match {CYNARA_ADMIN_WILDCARD, CYNARA_ADMIN_WILDCARD, "sms"} nor {"calculator", "bob", "sms"} + * + * If any of: start_bucket, client, user, privilege, policies is NULL then CYNARA_API_INVALID_PARAM + * is returned. + * If there is no bucket with given name CYNARA_API_BUCKET_NOT_FOUND is returned. + * + * In case of successful call CYNARA_API_SUCCESS is returned. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \param[in] p_cynara_admin cynara admin structure. + * \param[in] start_bucket name of bucket where erase would start. + * \param[in] recursive FALSE (== 0) : erase is not recursive (single bucket erase); + * TRUE (!= 0) : erase follows all policies leading to nested buckets + * \param[in] client filter for client name. + * \param[in] user filter for user name. + * \param[in] privilege filter for privilege. + * + * \return CYNARA_API_SUCCESS on success, or error code otherwise. + * + * \brief Erase policies matching filter from cynara database. + */ +int cynara_admin_erase(struct cynara_admin *p_cynara_admin, + const char *start_bucket, int recursive, + const char *client, const char *user, const char *privilege); #ifdef __cplusplus } #endif -- 2.7.4 From 7ef4f9a16f96b36ff135aadac859ee37fccda384 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 16 Dec 2014 10:48:20 +0100 Subject: [PATCH 07/16] Implement cynara_admin_erase() in admin API layer Implementation: * checks validity of parameters, * translates parameters to C++ objects used in higher layers, * catches all exceptions, * runs erasePolicies() method from admin Logic object. Change-Id: I6d4f0be5f20e283c41839b9618da2dac1c36f858 --- src/admin/api/ApiInterface.h | 2 ++ src/admin/api/admin-api.cpp | 32 +++++++++++++++++++++++++++++++- src/admin/logic/Logic.cpp | 6 ++++++ src/admin/logic/Logic.h | 3 +++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/admin/api/ApiInterface.h b/src/admin/api/ApiInterface.h index 6628b2c..89ac978 100644 --- a/src/admin/api/ApiInterface.h +++ b/src/admin/api/ApiInterface.h @@ -54,6 +54,8 @@ public: const PolicyKey &key, PolicyResult &result) = 0; virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies) = 0; + virtual int erasePolicies(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &filter) = 0; }; diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 55fc4db..401df51 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -302,7 +302,7 @@ int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char * } std::vector policiesVector; - int ret = p_cynara_admin->impl->listPolicies(bucket, Cynara::PolicyKey(clientStr, userStr, + int ret = p_cynara_admin->impl->listPolicies(bucketId, Cynara::PolicyKey(clientStr, userStr, privilegeStr), policiesVector); if (ret != CYNARA_API_SUCCESS) return ret; @@ -310,3 +310,33 @@ int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char * return createPoliciesArray(bucket, policiesVector, policies); }); } + +CYNARA_API +int cynara_admin_erase(struct cynara_admin *p_cynara_admin, + const char *start_bucket, const int recursive, + const char *client, const char *user, const char *privilege) { + if (!p_cynara_admin || !p_cynara_admin->impl) + return CYNARA_API_INVALID_PARAM; + if (!start_bucket || !client || !user || !privilege) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + Cynara::PolicyKeyFeature::ValueType clientStr; + Cynara::PolicyKeyFeature::ValueType userStr; + Cynara::PolicyKeyFeature::ValueType privilegeStr; + Cynara::PolicyBucketId startBucket; + try { + clientStr = client; + userStr = user; + privilegeStr = privilege; + startBucket = start_bucket; + } catch (const std::length_error &e) { + LOGE("%s", e.what()); + return CYNARA_API_INVALID_PARAM; + } + + return p_cynara_admin->impl->erasePolicies(startBucket, recursive != 0, + Cynara::PolicyKey(clientStr, userStr, + privilegeStr)); + }); +} diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 7fef282..3a5654c 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -198,4 +198,10 @@ int Logic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, return CYNARA_API_SUCCESS; } +int Logic::erasePolicies(const PolicyBucketId &startBucket UNUSED, bool recursive UNUSED, + const PolicyKey &filter UNUSED) { + //todo implement erase + return CYNARA_API_SUCCESS; +} + } // namespace Cynara diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h index 3469593..584d35d 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/Logic.h @@ -52,6 +52,9 @@ public: const PolicyKey &key, PolicyResult &result); virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies); + virtual int erasePolicies(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &filter); + }; } // namespace Cynara -- 2.7.4 From dbd976916f878eca38858614879ed291cc7a38ab Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 19 Dec 2014 09:35:24 +0100 Subject: [PATCH 08/16] Fix documentation and code style in requests folder Fix invalid file paths in ListRequest.* files. Break to long line in RequestTaker.cpp Change-Id: Icee52525c5413be1cc754d588773151689eb52f7 --- src/common/request/ListRequest.cpp | 2 +- src/common/request/ListRequest.h | 2 +- src/common/request/RequestTaker.cpp | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/request/ListRequest.cpp b/src/common/request/ListRequest.cpp index f8e261e..87abea7 100644 --- a/src/common/request/ListRequest.cpp +++ b/src/common/request/ListRequest.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * @file src/common/list/ListRequest.cpp + * @file src/common/request/ListRequest.cpp * @author Lukasz Wojciechowski * @version 1.0 * @brief This file implements policies list request class diff --git a/src/common/request/ListRequest.h b/src/common/request/ListRequest.h index 069ea4a..2df9506 100644 --- a/src/common/request/ListRequest.h +++ b/src/common/request/ListRequest.h @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * @file src/common/list/ListRequest.h + * @file src/common/request/ListRequest.h * @author Lukasz Wojciechowski * @version 1.0 * @brief This file defines policies list request class diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp index bc6c7a1..6a9b0df 100644 --- a/src/common/request/RequestTaker.cpp +++ b/src/common/request/RequestTaker.cpp @@ -37,7 +37,8 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, AgentActionRequestP throw NotImplementedException(); } -void RequestTaker::execute(RequestContextPtr context UNUSED, AgentRegisterRequestPtr request UNUSED) { +void RequestTaker::execute(RequestContextPtr context UNUSED, + AgentRegisterRequestPtr request UNUSED) { throw NotImplementedException(); } -- 2.7.4 From 10b2572501ee231523b0ba7a7630e663d2bf340e Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 19 Dec 2014 09:37:55 +0100 Subject: [PATCH 09/16] Add EraseRequest class EraseRequest class will be used to send request for erasing multiple policies matching filter key from cynara database. Change-Id: I32f8ef4449ecfcc2b32061a609a9beb442823c64 --- src/common/CMakeLists.txt | 1 + src/common/request/EraseRequest.cpp | 36 ++++++++++++++++++++ src/common/request/EraseRequest.h | 66 +++++++++++++++++++++++++++++++++++++ src/common/request/RequestTaker.cpp | 4 +++ src/common/request/RequestTaker.h | 3 +- src/common/request/pointers.h | 3 ++ test/CMakeLists.txt | 1 + 7 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/common/request/EraseRequest.cpp create mode 100644 src/common/request/EraseRequest.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e01c325..37073ad 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -44,6 +44,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/request/AgentRegisterRequest.cpp ${COMMON_PATH}/request/CancelRequest.cpp ${COMMON_PATH}/request/CheckRequest.cpp + ${COMMON_PATH}/request/EraseRequest.cpp ${COMMON_PATH}/request/InsertOrUpdateBucketRequest.cpp ${COMMON_PATH}/request/ListRequest.cpp ${COMMON_PATH}/request/RemoveBucketRequest.cpp diff --git a/src/common/request/EraseRequest.cpp b/src/common/request/EraseRequest.cpp new file mode 100644 index 0000000..54b59fc --- /dev/null +++ b/src/common/request/EraseRequest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/request/EraseRequest.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file implements policies erase request class + */ + +#include + +#include + +#include "EraseRequest.h" + +namespace Cynara { + +void EraseRequest::execute(RequestPtr self, RequestTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/request/EraseRequest.h b/src/common/request/EraseRequest.h new file mode 100644 index 0000000..bbbf7d3 --- /dev/null +++ b/src/common/request/EraseRequest.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/common/request/EraseRequest.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file defines policies erase request class + */ + +#ifndef SRC_COMMON_REQUEST_ERASEREQUEST_H_ +#define SRC_COMMON_REQUEST_ERASEREQUEST_H_ + +#include +#include + +#include +#include + +namespace Cynara { + +class EraseRequest : public Request { +public: + EraseRequest(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &filter, + ProtocolFrameSequenceNumber sequenceNumber) : + Request(sequenceNumber), m_startBucket(startBucket), m_recursive(recursive), + m_filter(filter) { + } + + virtual ~EraseRequest() {}; + + const PolicyBucketId &startBucket(void) const { + return m_startBucket; + } + + bool recursive(void) const { + return m_recursive; + } + + const PolicyKey &filter(void) const { + return m_filter; + } + + virtual void execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const; + +private: + PolicyBucketId m_startBucket; + bool m_recursive; + PolicyKey m_filter; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_REQUEST_ERASEREQUEST_H_ */ diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp index 6a9b0df..1233f17 100644 --- a/src/common/request/RequestTaker.cpp +++ b/src/common/request/RequestTaker.cpp @@ -50,6 +50,10 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, CheckRequestPtr req throw NotImplementedException(); } +void RequestTaker::execute(RequestContextPtr context UNUSED, EraseRequestPtr request UNUSED) { + throw NotImplementedException(); +} + void RequestTaker::execute(RequestContextPtr context UNUSED, InsertOrUpdateBucketRequestPtr request UNUSED) { throw NotImplementedException(); diff --git a/src/common/request/RequestTaker.h b/src/common/request/RequestTaker.h index c36b5c9..9d929d9 100644 --- a/src/common/request/RequestTaker.h +++ b/src/common/request/RequestTaker.h @@ -37,8 +37,9 @@ public: virtual void execute(RequestContextPtr context, AgentRegisterRequestPtr request); virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); - virtual void execute(RequestContextPtr context, ListRequestPtr request); + virtual void execute(RequestContextPtr context, EraseRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); + virtual void execute(RequestContextPtr context, ListRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); virtual void execute(RequestContextPtr context, SignalRequestPtr request); diff --git a/src/common/request/pointers.h b/src/common/request/pointers.h index d984c99..865a4c4 100644 --- a/src/common/request/pointers.h +++ b/src/common/request/pointers.h @@ -42,6 +42,9 @@ typedef std::shared_ptr CancelRequestPtr; class CheckRequest; typedef std::shared_ptr CheckRequestPtr; +class EraseRequest; +typedef std::shared_ptr EraseRequestPtr; + class InsertOrUpdateBucketRequest; typedef std::shared_ptr InsertOrUpdateBucketRequestPtr; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 82f26cd..fb9524c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -29,6 +29,7 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/common/protocol/ProtocolFrameHeader.cpp ${CYNARA_SRC}/common/protocol/ProtocolFrameSerializer.cpp ${CYNARA_SRC}/common/request/AdminCheckRequest.cpp + ${CYNARA_SRC}/common/request/EraseRequest.cpp ${CYNARA_SRC}/common/request/InsertOrUpdateBucketRequest.cpp ${CYNARA_SRC}/common/request/ListRequest.cpp ${CYNARA_SRC}/common/request/RemoveBucketRequest.cpp -- 2.7.4 From facc8534cbd287665bf03484365857784177da92 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 16 Dec 2014 12:52:04 +0100 Subject: [PATCH 10/16] Add serialization of EraseRequest with ProtocolAdmin Add serialization and deserialization of request for erasing multiple policies matching filter key. Provide new OpCode (28) for EraseRequest. Change-Id: Ib2370e98e6edae3fbb6a6457ebc5c58590f27580 --- src/common/protocol/ProtocolAdmin.cpp | 42 +++++++++++++++++++++++++++++++++++ src/common/protocol/ProtocolAdmin.h | 2 ++ src/common/protocol/ProtocolOpCode.h | 3 ++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 293db97..ccbf589 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,26 @@ RequestPtr ProtocolAdmin::deserializeAdminCheckRequest(void) { m_frameHeader.sequenceNumber()); } +RequestPtr ProtocolAdmin::deserializeEraseRequest(void) { + PolicyBucketId startBucket; + bool recursive; + PolicyKeyFeature::ValueType client, user, privilege; + + ProtocolDeserialization::deserialize(m_frameHeader, startBucket); + ProtocolDeserialization::deserialize(m_frameHeader, recursive); + ProtocolDeserialization::deserialize(m_frameHeader, client); + ProtocolDeserialization::deserialize(m_frameHeader, user); + ProtocolDeserialization::deserialize(m_frameHeader, privilege); + + LOGD("Deserialized EraseRequest: startBucket <%s>, recursive [%d], filter client <%s> " + "filter user <%s>, filter privilege <%s>", startBucket.c_str(), + static_cast(recursive), client.c_str(), user.c_str(), privilege.c_str()); + + return std::make_shared(startBucket, recursive, + PolicyKey(client, user, privilege), + m_frameHeader.sequenceNumber()); +} + RequestPtr ProtocolAdmin::deserializeInsertOrUpdateBucketRequest(void) { PolicyBucketId policyBucketId; PolicyType policyType; @@ -180,6 +201,8 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { switch (opCode) { case OpAdminCheckRequest: return deserializeAdminCheckRequest(); + case OpEraseRequest: + return deserializeEraseRequest(); case OpInsertOrUpdateBucket: return deserializeInsertOrUpdateBucketRequest(); case OpListRequest: @@ -300,6 +323,25 @@ void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckRequestPtr requ ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } +void ProtocolAdmin::execute(RequestContextPtr context, EraseRequestPtr request) { + LOGD("Serializing EraseRequest: sequenceNumber [%" PRIu16 "], startBucket <%s>, " + "recursive [%d], filter client <%s> filter user <%s> filter privilege <%s>", + request->sequenceNumber(), request->startBucket().c_str(), + static_cast(request->recursive()), request->filter().client().value().c_str(), + request->filter().user().value().c_str(), request->filter().privilege().value().c_str()); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpEraseRequest); + ProtocolSerialization::serialize(frame, request->startBucket()); + ProtocolSerialization::serialize(frame, request->recursive()); + ProtocolSerialization::serialize(frame, request->filter().client().value()); + ProtocolSerialization::serialize(frame, request->filter().user().value()); + ProtocolSerialization::serialize(frame, request->filter().privilege().value()); + + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); +} + void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) { LOGD("Serializing InsertOrUpdateBucketRequest: sequenceNumber [%" PRIu16 "], bucketId <%s>, " "result.type [%" PRIu16 "], result.meta <%s>", request->sequenceNumber(), diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index b9c7e17..f1db4e4 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -39,6 +39,7 @@ public: virtual ResponsePtr extractResponseFromBuffer(BinaryQueuePtr bufferQueue); virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); + virtual void execute(RequestContextPtr context, EraseRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); virtual void execute(RequestContextPtr context, ListRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); @@ -50,6 +51,7 @@ public: private: RequestPtr deserializeAdminCheckRequest(void); + RequestPtr deserializeEraseRequest(void); RequestPtr deserializeInsertOrUpdateBucketRequest(void); RequestPtr deserializeListRequest(void); RequestPtr deserializeRemoveBucketRequest(void); diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index 984ddef..42289ac 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -48,8 +48,9 @@ enum ProtocolOpCode : uint8_t { OpListRequest, OpListResponse, OpAdminCheckPolicyResponse, + OpEraseRequest, - /** Opcodes 28 - 39 are reserved for future use */ + /** Opcodes 29 - 39 are reserved for future use */ /** Agent operations */ OpAgentRegisterRequest = 40, -- 2.7.4 From 610d2dcaccb80256769bd367446e67c091e88b6a Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 16 Dec 2014 13:13:24 +0100 Subject: [PATCH 11/16] Add tests for EraseRequest serialization Add tests for checking equality of objects and binary data in serialization / deserialization of EraseRequest by ProtocolAdmin. Change-Id: I25c2768572d6aa419c1635586437e7bf673d301f --- test/CMakeLists.txt | 1 + test/common/protocols/admin/eraserequest.cpp | 147 +++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 test/common/protocols/admin/eraserequest.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fb9524c..99097cc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -60,6 +60,7 @@ SET(CYNARA_TESTS_SOURCES common/exceptions/bucketrecordcorrupted.cpp common/protocols/admin/admincheckrequest.cpp common/protocols/admin/admincheckresponse.cpp + common/protocols/admin/eraserequest.cpp common/protocols/admin/listrequest.cpp common/protocols/admin/listresponse.cpp common/types/policybucket.cpp diff --git a/test/common/protocols/admin/eraserequest.cpp b/test/common/protocols/admin/eraserequest.cpp new file mode 100644 index 0000000..4b1efdc --- /dev/null +++ b/test/common/protocols/admin/eraserequest.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file test/common/protocols/admin/eraserequest.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Tests for Cynara::EraseRequest usage in Cynara::ProtocolAdmin + */ + +#include + +#include +#include + +#include +#include + +namespace { + +template<> +void compare(const Cynara::EraseRequest &req1, const Cynara::EraseRequest &req2) { + EXPECT_EQ(req1.startBucket(), req2.startBucket()); + EXPECT_EQ(req1.recursive(), req2.recursive()); + EXPECT_EQ(req1.filter(), req2.filter()); +} + +static const bool RECURSIVE = true; +static const bool NON_RECURSIVE = false; + +} /* namespace anonymous */ + +using namespace Cynara; +using namespace RequestTestHelper; +using namespace TestDataCollection; + +/* *** compare by objects test cases *** */ + +TEST(ProtocolAdmin, EraseRequest01) { + auto request = std::make_shared(Buckets::empty, RECURSIVE, Keys::k_nun, SN::min); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequest02) { + auto request = std::make_shared(Buckets::not_empty, NON_RECURSIVE, Keys::k_cup, + SN::min_1); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequest03) { + auto request = std::make_shared(Buckets::empty, NON_RECURSIVE, Keys::k_www, + SN::min_2); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequest04) { + auto request = std::make_shared(Buckets::not_empty, RECURSIVE, Keys::k_wuw, + SN::max); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequest05) { + auto request = std::make_shared(Buckets::empty, RECURSIVE, Keys::k_aaa, + SN::max_1); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequest06) { + auto request = std::make_shared(Buckets::not_empty, NON_RECURSIVE, Keys::k_wua, + SN::max_2); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequest07) { + auto request = std::make_shared(Buckets::empty, NON_RECURSIVE, Keys::k_nua, + SN::mid); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +/* *** compare by serialized data test cases *** */ + +TEST(ProtocolAdmin, EraseRequestBinary01) { + auto request = std::make_shared(Buckets::empty, RECURSIVE, Keys::k_nun, SN::min); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequestBinary02) { + auto request = std::make_shared(Buckets::not_empty, NON_RECURSIVE, Keys::k_cup, + SN::min_1); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequestBinary03) { + auto request = std::make_shared(Buckets::empty, NON_RECURSIVE, Keys::k_www, + SN::min_2); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequestBinary04) { + auto request = std::make_shared(Buckets::not_empty, RECURSIVE, Keys::k_wuw, + SN::max); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequestBinary05) { + auto request = std::make_shared(Buckets::empty, RECURSIVE, Keys::k_aaa, + SN::max_1); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequestBinary06) { + auto request = std::make_shared(Buckets::not_empty, NON_RECURSIVE, Keys::k_wua, + SN::max_2); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, EraseRequestBinary07) { + auto request = std::make_shared(Buckets::empty, NON_RECURSIVE, Keys::k_nua, + SN::mid); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} -- 2.7.4 From 5ecca98e958deace134a6d289954859e3de8bd1d Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 16 Dec 2014 13:36:38 +0100 Subject: [PATCH 12/16] Handle EraseRequest in admin library Logic layer Create EraseRequest and wait for CodeResponse. Interprete it and return proper code to admin API layer. Change-Id: I35ba3573fdf8a455c5a42020e918a6a7b17c0a46 --- src/admin/logic/Logic.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 3a5654c..b0ea895 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,7 @@ int Logic::askCynaraAndInterpreteCodeResponse(Args... args) { LOGD("codeResponse: code [%" PRIu16 "]", codeResponse->m_code); switch (codeResponse->m_code) { case CodeResponse::Code::OK: - LOGI("Policies set successfully."); + LOGI("Cynara command finished successfully."); return CYNARA_API_SUCCESS; case CodeResponse::Code::NOT_ALLOWED: LOGE("Cynara service answered: Operation not allowed."); @@ -198,10 +199,9 @@ int Logic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, return CYNARA_API_SUCCESS; } -int Logic::erasePolicies(const PolicyBucketId &startBucket UNUSED, bool recursive UNUSED, - const PolicyKey &filter UNUSED) { - //todo implement erase - return CYNARA_API_SUCCESS; +int Logic::erasePolicies(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &filter) { + return askCynaraAndInterpreteCodeResponse(startBucket, recursive, filter); } } // namespace Cynara -- 2.7.4 From 72e607fbb64c97179afe6862c1ed7770ec8f8799 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Thu, 18 Dec 2014 14:04:09 +0100 Subject: [PATCH 13/16] Implement erasePolicies() in Storage Implementation add StorageBackend::erasePolicies() in base class and its implementation in InMemoryStorageBackend. In Storage class erasePolicies() just passes this request to backend. PolicyBucket class was enhanced with getSubBuckets() method returning set of all IDs of subbuckets. Subbucket is a bucket that can be reached with policy (type==BUCKET) from current bucket. Change-Id: I90598aa916857a917d911068da1a1c18c69391a5 --- src/common/types/PolicyBucket.cpp | 10 + src/common/types/PolicyBucket.h | 3 + src/storage/InMemoryStorageBackend.cpp | 23 ++ src/storage/InMemoryStorageBackend.h | 2 + src/storage/Storage.cpp | 5 + src/storage/Storage.h | 2 + src/storage/StorageBackend.h | 2 + test/common/protocols/TestDataCollection.h | 12 +- .../inmemeorystoragebackendfixture.h | 83 +++++++ .../inmemorystoragebackend.cpp | 245 +++++++++++++++++++++ test/storage/storage/fakestoragebackend.h | 2 + 11 files changed, 388 insertions(+), 1 deletion(-) diff --git a/src/common/types/PolicyBucket.cpp b/src/common/types/PolicyBucket.cpp index 052ac35..a25c274 100644 --- a/src/common/types/PolicyBucket.cpp +++ b/src/common/types/PolicyBucket.cpp @@ -99,6 +99,16 @@ PolicyBucket::Policies PolicyBucket::listPolicies(const PolicyKey &filter) const return policies; } +PolicyBucket::BucketIds PolicyBucket::getSubBuckets(void) const { + PolicyBucket::BucketIds buckets; + for (auto iter = m_policyCollection.begin(); iter != m_policyCollection.end(); ++iter) { + auto &policyPtr = iter->second; + if (policyPtr->result().policyType() == PredefinedPolicyType::BUCKET) + buckets.insert(policyPtr->result().metadata()); + } + return buckets; +} + PolicyMap PolicyBucket::makePolicyMap(const PolicyCollection &policies) { PolicyMap result; for (const auto &policy : policies) { diff --git a/src/common/types/PolicyBucket.h b/src/common/types/PolicyBucket.h index 262c7d3..62cdf5f 100644 --- a/src/common/types/PolicyBucket.h +++ b/src/common/types/PolicyBucket.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -49,6 +50,7 @@ public: typedef PolicyCollection::value_type value_type; typedef const_policy_iterator const_iterator; typedef std::vector Policies; + typedef std::set BucketIds; // TODO: Review usefulness of ctors //delete default constructor in order to prevent creation of buckets with no id @@ -65,6 +67,7 @@ public: void insertPolicy(PolicyPtr policy); void deletePolicy(const PolicyKey &key); Policies listPolicies(const PolicyKey &filter) const; + BucketIds getSubBuckets(void) const; // TODO: Try to change interface, so this method is not needed void deletePolicy(std::function predicate); diff --git a/src/storage/InMemoryStorageBackend.cpp b/src/storage/InMemoryStorageBackend.cpp index bc3d01a..f5bd505 100644 --- a/src/storage/InMemoryStorageBackend.cpp +++ b/src/storage/InMemoryStorageBackend.cpp @@ -211,6 +211,29 @@ PolicyBucket::Policies InMemoryStorageBackend::listPolicies(const PolicyBucketId } } +void InMemoryStorageBackend::erasePolicies(const PolicyBucketId &bucketId, bool recursive, + const PolicyKey &filter) { + PolicyBucket::BucketIds bucketIds = {bucketId}; + + while (!bucketIds.empty()) { + auto it = bucketIds.begin(); + PolicyBucketId bucketId = *it; + bucketIds.erase(it); + try { + auto &policyBucket = buckets().at(bucketId); + if (recursive) { + auto subBuckets = policyBucket.getSubBuckets(); + bucketIds.insert(subBuckets.begin(), subBuckets.end()); + } + policyBucket.deletePolicy([&filter] (PolicyPtr policy) -> bool { + return policy->key().matchFilter(filter); + }); + } catch (const std::out_of_range &) { + throw BucketNotExistsException(bucketId); + } + } +} + void InMemoryStorageBackend::openFileStream(std::shared_ptr stream, const std::string &filename) { // TODO: Consider adding exceptions to streams and handling them: diff --git a/src/storage/InMemoryStorageBackend.h b/src/storage/InMemoryStorageBackend.h index 07f7fcd..872486b 100644 --- a/src/storage/InMemoryStorageBackend.h +++ b/src/storage/InMemoryStorageBackend.h @@ -60,6 +60,8 @@ public: virtual void deleteLinking(const PolicyBucketId &bucketId); virtual PolicyBucket::Policies listPolicies(const PolicyBucketId &bucketId, const PolicyKey &filter) const; + virtual void erasePolicies(const PolicyBucketId &bucketId, bool recursive, + const PolicyKey &filter); protected: InMemoryStorageBackend() {} diff --git a/src/storage/Storage.cpp b/src/storage/Storage.cpp index fafb374..3fe5c7b 100644 --- a/src/storage/Storage.cpp +++ b/src/storage/Storage.cpp @@ -159,6 +159,11 @@ PolicyBucket::Policies Storage::listPolicies(const PolicyBucketId &bucketId, return m_backend.listPolicies(bucketId, filter); } +void Storage::erasePolicies(const PolicyBucketId &bucketId, bool recursive, + const PolicyKey &filter) { + return m_backend.erasePolicies(bucketId, recursive, filter); +} + void Storage::load(void) { m_backend.load(); } diff --git a/src/storage/Storage.h b/src/storage/Storage.h index 838bdb7..0893974 100644 --- a/src/storage/Storage.h +++ b/src/storage/Storage.h @@ -56,6 +56,8 @@ public: PolicyBucket::Policies listPolicies(const PolicyBucketId &bucketId, const PolicyKey &filter) const; + void erasePolicies(const PolicyBucketId &bucketId, bool recursive, const PolicyKey &filter); + void load(void); void save(void); diff --git a/src/storage/StorageBackend.h b/src/storage/StorageBackend.h index 5bb4e61..10430e2 100644 --- a/src/storage/StorageBackend.h +++ b/src/storage/StorageBackend.h @@ -54,6 +54,8 @@ public: virtual void deleteLinking(const PolicyBucketId &bucket) = 0; virtual PolicyBucket::Policies listPolicies(const PolicyBucketId &bucketId, const PolicyKey &filter) const = 0; + virtual void erasePolicies(const PolicyBucketId &bucketId, bool recursive, + const PolicyKey &filter) = 0; virtual void load(void) = 0; virtual void save(void) = 0; }; diff --git a/test/common/protocols/TestDataCollection.h b/test/common/protocols/TestDataCollection.h index cf7c323..bb0bc13 100644 --- a/test/common/protocols/TestDataCollection.h +++ b/test/common/protocols/TestDataCollection.h @@ -39,13 +39,23 @@ typedef Cynara::PolicyKeyFeature PKF; namespace Keys { static const Cynara::PolicyKey k_nun(PKF::create(""), PKF::create("u"), PKF::create("")); static const Cynara::PolicyKey k_cup(PKF::create("c"), PKF::create("u"), PKF::create("p")); - static const Cynara::PolicyKey k_www(PKF::createWildcard(), PKF::createWildcard(), + static const Cynara::PolicyKey k_wup(PKF::createWildcard(), PKF::create("u"), PKF::create("p")); + static const Cynara::PolicyKey k_cwp(PKF::create("c"), PKF::createWildcard(), PKF::create("p")); + static const Cynara::PolicyKey k_cuw(PKF::create("c"), PKF::create("u"), PKF::createWildcard()); + static const Cynara::PolicyKey k_cww(PKF::create("c"), PKF::createWildcard(), PKF::createWildcard()); static const Cynara::PolicyKey k_wuw(PKF::createWildcard(), PKF::create("u"), PKF::createWildcard()); + static const Cynara::PolicyKey k_wwp(PKF::createWildcard(), PKF::createWildcard(), + PKF::create("p")); + static const Cynara::PolicyKey k_www(PKF::createWildcard(), PKF::createWildcard(), + PKF::createWildcard()); static const Cynara::PolicyKey k_aaa(PKF::createAny(), PKF::createAny(), PKF::createAny()); static const Cynara::PolicyKey k_wua(PKF::createWildcard(), PKF::create("u"), PKF::createAny()); static const Cynara::PolicyKey k_nua(PKF::create(""), PKF::create("u"), PKF::createAny()); + static const Cynara::PolicyKey k_wwa(PKF::createWildcard(), PKF::createWildcard(), + PKF::createAny()); + static const Cynara::PolicyKey k_aup(PKF::createAny(), PKF::create("u"), PKF::create("p")); } /* namespace Keys */ namespace SN { diff --git a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h index 2ec2920..b671a0d 100644 --- a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h +++ b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h @@ -26,12 +26,38 @@ #include #include +#include +#include + #include #include +#include #include #include +#include + class InMemeoryStorageBackendFixture : public ::testing::Test { +public: + class Filter { + public: + Filter(const std::string &name, const Cynara::PolicyKey &key) : + m_name(name), m_key(key) {} + + const std::string &name(void) const { + return m_name; + } + + const Cynara::PolicyKey &key(void) const { + return m_key; + } + + private: + std::string m_name; + Cynara::PolicyKey m_key; + }; + + typedef std::vector Filters; protected: Cynara::Buckets::mapped_type & @@ -65,10 +91,67 @@ protected: virtual ~InMemeoryStorageBackendFixture() {} + const Cynara::PolicyCollection &fullPoliciesCollection(void) { + using Cynara::PredefinedPolicyType::ALLOW; + if (m_fullPolicyCollection.empty()) { + m_fullPolicyCollection = { + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cup, ALLOW), + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_wup, ALLOW), + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cwp, ALLOW), + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cuw, ALLOW), + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cww, ALLOW), + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_wuw, ALLOW), + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_wwp, ALLOW), + Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_www, ALLOW), + }; + } + return m_fullPolicyCollection; + } + + const Filters &filters(void) { + if (m_filters.empty()) { + m_filters.push_back(Filter("cup", TestDataCollection::Keys::k_cup)); + m_filters.push_back(Filter("www", TestDataCollection::Keys::k_www)); + m_filters.push_back(Filter("wuw", TestDataCollection::Keys::k_wuw)); + m_filters.push_back(Filter("aaa", TestDataCollection::Keys::k_aaa)); + m_filters.push_back(Filter("wua", TestDataCollection::Keys::k_wua)); + m_filters.push_back(Filter("wwa", TestDataCollection::Keys::k_wwa)); + m_filters.push_back(Filter("aup", TestDataCollection::Keys::k_aup)); + } + return m_filters; + } + + const Cynara::PolicyCollection &expectedEraseResult(const std::string &filterName) { + if (m_expectedResults.empty()) { + const Cynara::PolicyCollection &pc = fullPoliciesCollection(); + // "cup", "wup", "cwp", "cuw", "cww", "wuw", "wwp", "www" + m_expectedResults["cup"] = { pc[1], pc[2], pc[3], pc[4], pc[5], pc[6], pc[7]}; + m_expectedResults["www"] = {pc[0], pc[1], pc[2], pc[3], pc[4], pc[5], pc[6], }; + m_expectedResults["wuw"] = {pc[0], pc[1], pc[2], pc[3], pc[4], pc[6], pc[7]}; + m_expectedResults["aaa"] = { }; + m_expectedResults["wua"] = {pc[0], pc[2], pc[3], pc[4], pc[6], pc[7]}; + m_expectedResults["wwa"] = {pc[0], pc[1], pc[2], pc[3], pc[4], pc[5], }; + m_expectedResults["aup"] = { pc[2], pc[3], pc[4], pc[5], pc[6], pc[7]}; + } + + return m_expectedResults[filterName]; + } + + bool isLinkPolicyErased(const std::string &filterName) { + if (filterName == "aaa") + return true; + return false; + } + // TODO: consider defaulting accessor with ON_CALL Cynara::Buckets m_buckets; static const std::string m_indexFileName; static const std::string m_backupFileNameSuffix; + + //erase helper structures + Cynara::PolicyCollection m_fullPolicyCollection; + Filters m_filters; + std::map m_expectedResults; }; diff --git a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp index c0fd640..a684b22 100644 --- a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp +++ b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp @@ -288,3 +288,248 @@ TEST_F(InMemeoryStorageBackendFixture, load_from_backup) { ASSERT_THAT(bucketPolicies, IsEmpty()); } } + +/** + * @brief Erase from non-exiting bucket should throw BucketNotExistsException + * @test Scenario: + * - For different filter keys: + * - try erase policies from "non-existing-bucket" + * - expect BucketNotExistsException is thrown + */ +TEST_F(InMemeoryStorageBackendFixture, erasePoliciesEmptyBase) { + using ::testing::ReturnRef; + + FakeInMemoryStorageBackend backend; + EXPECT_CALL(backend, buckets()) + .WillRepeatedly(ReturnRef(m_buckets)); + + PolicyBucketId bucketId = "non-existing-bucket"; + const bool NON_RECURSIVE = false; + + for (const auto &filter : filters()) { + SCOPED_TRACE(filter.name()); + + EXPECT_THROW(backend.erasePolicies(bucketId, NON_RECURSIVE, filter.key()), + BucketNotExistsException); + } +} + +/** + * @brief Erase from single bucket + * @test Scenario: + * - For different filter keys: + * - create "test-bucket" + * - add all types of policies (fullPoliciesCollection) into "test-bucket" + * - erase policies from "test-bucket" + * - check if received results match expected + */ +TEST_F(InMemeoryStorageBackendFixture, erasePoliciesSingleBucket) { + using ::testing::ReturnRef; + using ::testing::UnorderedElementsAreArray; + + PolicyBucketId bucketId = "test-bucket"; + const bool NON_RECURSIVE = false; + + for (const auto &filter : filters()) { + SCOPED_TRACE(filter.name()); + + FakeInMemoryStorageBackend backend; + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + + createBucket(bucketId); + addToBucket(bucketId, fullPoliciesCollection()); + + backend.erasePolicies(bucketId, NON_RECURSIVE, filter.key()); + ASSERT_THAT(m_buckets.at(bucketId), + UnorderedElementsAreArray(expectedEraseResult(filter.name()))); + } +} + +/** + * @brief Verify if recursive erase doesn't propagate to not linked bucket + * @test Scenario: + * - For different filter keys: + * - create "test-bucket" + * - add all types of policies (fullPoliciesCollection) into "test-bucket" + * - create "test-bucket2" + * - add all types of policies (fullPoliciesCollection) into "test-bucket2" + * - erase policies from "test-bucket" + * - check if received results match expected in case of "test-bucket" + * - check if policies in "test-bucket2" remain unaffected + */ +TEST_F(InMemeoryStorageBackendFixture, erasePoliciesRecursiveNotLinkedBuckets) { + using ::testing::ReturnRef; + using ::testing::UnorderedElementsAreArray; + + PolicyBucketId bucketId = "test-bucket"; + PolicyBucketId bucketId2 = "test-bucket2"; + const bool RECURSIVE = true; + + for (const auto &filter : filters()) { + SCOPED_TRACE(filter.name()); + + FakeInMemoryStorageBackend backend; + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + + createBucket(bucketId); + addToBucket(bucketId, fullPoliciesCollection()); + + createBucket(bucketId2); + addToBucket(bucketId2, fullPoliciesCollection()); + + backend.erasePolicies(bucketId, RECURSIVE, filter.key()); + ASSERT_THAT(m_buckets.at(bucketId), + UnorderedElementsAreArray(expectedEraseResult(filter.name()))); + ASSERT_THAT(m_buckets.at(bucketId2), + UnorderedElementsAreArray(fullPoliciesCollection())); + } +} + +/** + * @brief Verify if recursive erase does propagate to linked bucket + * @test Scenario: + * - For different filter keys: + * - create "test-bucket" + * - add all types of policies (fullPoliciesCollection) into "test-bucket" + * - create "test-bucket2" + * - add all types of policies (fullPoliciesCollection) into "test-bucket2" + * - add policy linking test buckets + * - erase policies from "test-bucket" + * - check if received results match expected in case of "test-bucket" + * - check if received results match expected in case of "test-bucket2" + */ +TEST_F(InMemeoryStorageBackendFixture, erasePoliciesRecursiveLinkedBuckets) { + using ::testing::ReturnRef; + using ::testing::UnorderedElementsAreArray; + + PolicyBucketId bucketId = "test-bucket"; + PolicyBucketId bucketId2 = "test-bucket2"; + PolicyKey linkKey = Helpers::generatePolicyKey("link"); + PolicyCollection linkPolicy = {Policy::bucketWithKey(linkKey, bucketId2)}; + const bool RECURSIVE = true; + + for (const auto &filter : filters()) { + SCOPED_TRACE(filter.name()); + + FakeInMemoryStorageBackend backend; + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + + createBucket(bucketId); + addToBucket(bucketId, fullPoliciesCollection()); + + createBucket(bucketId2); + addToBucket(bucketId2, fullPoliciesCollection()); + + addToBucket(bucketId, linkPolicy); + + backend.erasePolicies(bucketId, RECURSIVE, filter.key()); + + PolicyCollection expectedResult = expectedEraseResult(filter.name()); + if (!isLinkPolicyErased(filter.name())) { + expectedResult.insert(expectedResult.end(), linkPolicy.begin(), linkPolicy.end()); + } + ASSERT_THAT(m_buckets.at(bucketId), + UnorderedElementsAreArray(expectedResult)); + ASSERT_THAT(m_buckets.at(bucketId2), + UnorderedElementsAreArray(expectedEraseResult(filter.name()))); + } +} + +/** + * @brief Verify if recursive erase doesn't propagate backwards to linked bucket + * @test Scenario: + * - For different filter keys: + * - create "test-bucket" + * - add all types of policies (fullPoliciesCollection) into "test-bucket" + * - create "test-bucket2" + * - add all types of policies (fullPoliciesCollection) into "test-bucket2" + * - add policy linking test buckets + * - erase policies from "test-bucket2" + * - check if policies in "test-bucket" remain unaffected + * - check if received results match expected in case of "test-bucket2" + */ +TEST_F(InMemeoryStorageBackendFixture, erasePoliciesRecursiveLinkedBucketsNoBackwardPropagation) { + using ::testing::ReturnRef; + using ::testing::UnorderedElementsAreArray; + + PolicyBucketId bucketId = "test-bucket"; + PolicyBucketId bucketId2 = "test-bucket2"; + PolicyKey linkKey = Helpers::generatePolicyKey("link"); + PolicyCollection linkPolicy = {Policy::bucketWithKey(linkKey, bucketId2)}; + const bool RECURSIVE = true; + + for (const auto &filter : filters()) { + SCOPED_TRACE(filter.name()); + + FakeInMemoryStorageBackend backend; + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + + createBucket(bucketId); + addToBucket(bucketId, fullPoliciesCollection()); + + createBucket(bucketId2); + addToBucket(bucketId2, fullPoliciesCollection()); + + addToBucket(bucketId, linkPolicy); + + backend.erasePolicies(bucketId2, RECURSIVE, filter.key()); + + PolicyCollection expectedResult = fullPoliciesCollection(); + expectedResult.insert(expectedResult.end(), linkPolicy.begin(), linkPolicy.end()); + + ASSERT_THAT(m_buckets.at(bucketId), + UnorderedElementsAreArray(expectedResult)); + ASSERT_THAT(m_buckets.at(bucketId2), + UnorderedElementsAreArray(expectedEraseResult(filter.name()))); + } +} + +/** + * @brief Verify if non-recursive erase doesn't propagate to linked bucket + * @test Scenario: + * - For different filter keys: + * - create "test-bucket" + * - add all types of policies (fullPoliciesCollection) into "test-bucket" + * - create "test-bucket2" + * - add all types of policies (fullPoliciesCollection) into "test-bucket2" + * - add policy linking test buckets + * - erase policies from "test-bucket" + * - check if received results match expected in case of "test-bucket" + * - check if policies in "test-bucket2" remain unaffected + */ +TEST_F(InMemeoryStorageBackendFixture, erasePoliciesNonRecursiveLinkedBuckets) { + using ::testing::ReturnRef; + using ::testing::UnorderedElementsAreArray; + + PolicyBucketId bucketId = "test-bucket"; + PolicyBucketId bucketId2 = "test-bucket2"; + PolicyKey linkKey = Helpers::generatePolicyKey("link"); + PolicyCollection linkPolicy = {Policy::bucketWithKey(linkKey, bucketId2)}; + const bool NON_RECURSIVE = false; + + for (const auto &filter : filters()) { + SCOPED_TRACE(filter.name()); + + FakeInMemoryStorageBackend backend; + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + + createBucket(bucketId); + addToBucket(bucketId, fullPoliciesCollection()); + + createBucket(bucketId2); + addToBucket(bucketId2, fullPoliciesCollection()); + + addToBucket(bucketId, linkPolicy); + + backend.erasePolicies(bucketId, NON_RECURSIVE, filter.key()); + + PolicyCollection expectedResult = expectedEraseResult(filter.name()); + if (!isLinkPolicyErased(filter.name())) { + expectedResult.insert(expectedResult.end(), linkPolicy.begin(), linkPolicy.end()); + } + ASSERT_THAT(m_buckets.at(bucketId), + UnorderedElementsAreArray(expectedResult)); + ASSERT_THAT(m_buckets.at(bucketId2), + UnorderedElementsAreArray(fullPoliciesCollection())); + } +} diff --git a/test/storage/storage/fakestoragebackend.h b/test/storage/storage/fakestoragebackend.h index 86bfd30..0aefd60 100644 --- a/test/storage/storage/fakestoragebackend.h +++ b/test/storage/storage/fakestoragebackend.h @@ -44,6 +44,8 @@ public: MOCK_METHOD2(insertPolicy, void(const PolicyBucketId &bucketId, PolicyPtr policy)); MOCK_CONST_METHOD2(listPolicies, PolicyBucket::Policies(const PolicyBucketId &bucketId, const PolicyKey &filter)); + MOCK_METHOD3(erasePolicies, void(const PolicyBucketId &bucketId, bool recursive, + const PolicyKey &filter)); }; #endif /* FAKESTORAGEBACKEND_H_ */ -- 2.7.4 From 5608ee822b94bb559f822890e489abb76be05340 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Thu, 18 Dec 2014 14:18:53 +0100 Subject: [PATCH 14/16] Add processing EraseRequest on serviceLogic layer Process EraseRequest, pass data to Storage layer. Save database in case of successful erase. Return CodeResponse to sender of EraseRequest. Change-Id: I9bddfff64bf8b8e11f36ccac85ab5bb715f69c4f --- src/service/logic/Logic.cpp | 17 +++++++++++++++++ src/service/logic/Logic.h | 1 + 2 files changed, 18 insertions(+) diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index 3445984..75c94ca 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -270,6 +271,22 @@ bool Logic::update(const PolicyKey &key, ProtocolFrameSequenceNumber checkId, return false; } +void Logic::execute(RequestContextPtr context, EraseRequestPtr request) { + auto code = CodeResponse::Code::OK; + + try { + m_storage->erasePolicies(request->startBucket(), request->recursive(), request->filter()); + onPoliciesChanged(); + } catch (const DatabaseException &ex) { + code = CodeResponse::Code::FAILED; + } catch (const BucketNotExistsException &ex) { + code = CodeResponse::Code::NO_BUCKET; + } + + context->returnResponse(context, std::make_shared(code, + request->sequenceNumber())); +} + void Logic::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) { auto code = CodeResponse::Code::OK; diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index d347071..71c5d01 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -69,6 +69,7 @@ public: virtual void execute(RequestContextPtr context, AgentRegisterRequestPtr request); virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); + virtual void execute(RequestContextPtr context, EraseRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); virtual void execute(RequestContextPtr context, ListRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); -- 2.7.4 From 8dcd79f13ef1e0c71bf3239c704d263d1f0c129f Mon Sep 17 00:00:00 2001 From: Pawel Wieczorek Date: Mon, 22 Dec 2014 09:29:43 +0100 Subject: [PATCH 15/16] Remove surplus read permissions for migration tool In order to prevent possibility of non-authorised usage of migration tool read permissions for wrapper script are now retracted. Change-Id: I40d3f7cea0a9597863d0d75f168b2dea9ec64d6d --- packaging/cynara.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 91b80a6..c057aa1 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -357,4 +357,4 @@ fi %files -n cynara-db-migration %manifest cynara-db-migration.manifest -%attr(744,root,root) %{_sbindir}/cynara/cynara-db-migration.sh +%attr(700,root,root) %{_sbindir}/cynara/cynara-db-migration.sh -- 2.7.4 From aa62332eb893ad65d5b65cb19f020ed6f87b2514 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Mon, 27 Oct 2014 14:44:14 +0100 Subject: [PATCH 16/16] Add StoragePath::lockfile path Change-Id: I16242dd8da7435661ee65698541e935ea9105cf1 --- src/common/config/PathConfig.cpp | 2 ++ src/common/config/PathConfig.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/common/config/PathConfig.cpp b/src/common/config/PathConfig.cpp index f2799a1..8dd0491 100644 --- a/src/common/config/PathConfig.cpp +++ b/src/common/config/PathConfig.cpp @@ -16,6 +16,7 @@ /** * @file src/common/config/PathConfig.cpp * @author Zofia Abramowska + * @author Aleksander Zdyb * @version 1.0 * @brief This file specifies PathConfig namespace containing values of default cynara paths */ @@ -52,6 +53,7 @@ const std::string agent(clientPath + "cynara-agent.socket"); namespace StoragePath { const std::string dbDir(statePath + "db/"); +const std::string lockFile(statePath); } // namespace StoragePath namespace PluginPath { diff --git a/src/common/config/PathConfig.h b/src/common/config/PathConfig.h index 2f5836a..da5671f 100644 --- a/src/common/config/PathConfig.h +++ b/src/common/config/PathConfig.h @@ -16,6 +16,7 @@ /** * @file src/common/config/PathConfig.h * @author Zofia Abramowska + * @author Aleksander Zdyb * @version 1.0 * @brief This file specifies PathConfig namespace containing default cynara paths */ @@ -40,6 +41,7 @@ extern const std::string agent; namespace StoragePath { extern const std::string dbDir; +extern const std::string lockFile; } // namespace StoragePath namespace PluginPath { -- 2.7.4