From 10b2572501ee231523b0ba7a7630e663d2bf340e Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 19 Dec 2014 09:37:55 +0100 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 From 7a6ec0f04bc425bbc35000c08f86ae17a8394cd1 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Mon, 27 Oct 2014 14:45:58 +0100 Subject: [PATCH 09/16] Don't create database directory This functionality was replaced by database migration tool and database directory is always present. Change-Id: Ib5f1f8a6c2887534f2c4f0ae3c85245d69818a14 --- src/storage/InMemoryStorageBackend.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/storage/InMemoryStorageBackend.cpp b/src/storage/InMemoryStorageBackend.cpp index f5bd505..77676f0 100644 --- a/src/storage/InMemoryStorageBackend.cpp +++ b/src/storage/InMemoryStorageBackend.cpp @@ -95,18 +95,6 @@ void InMemoryStorageBackend::load(void) { } void InMemoryStorageBackend::save(void) { - - //create directory - int ret = mkdir(m_dbPath.c_str(), S_IRWXU); - if (ret < 0) { - int err = errno; - if (err != EEXIST) { - LOGE("Cannot create directory <%s>. Error [%d] : <%s>.", - m_dbPath.c_str(), err, strerror(err)); - throw UnexpectedErrorException(err, strerror(err)); - } - } - auto indexStream = std::make_shared(); std::string indexFilename = m_dbPath + m_indexFilename; openDumpFileStream(indexStream, indexFilename + m_backupFilenameSuffix); -- 2.7.4 From d514cd59397d07540b44bf8bc925947cee545e5b Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 23 Dec 2014 13:54:32 +0100 Subject: [PATCH 10/16] Introduce Lockable in FileLock FileLock now operates on lockable object instead of a file path and internal file descriptor. Lockable is an abstraction of file descriptor. Change-Id: Ie17905a4455492956e5162d90add488ca6f3080c --- src/common/lock/FileLock.cpp | 21 ++++++++++++++++----- src/common/lock/FileLock.h | 18 ++++++++++++++---- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/common/lock/FileLock.cpp b/src/common/lock/FileLock.cpp index b8bd34a..98141f6 100644 --- a/src/common/lock/FileLock.cpp +++ b/src/common/lock/FileLock.cpp @@ -36,8 +36,8 @@ namespace Cynara { -FileLock::FileLock(const std::string &lockFilename) : m_lockFilename(lockFilename) { - m_fd = ::open(m_lockFilename.c_str(), O_RDONLY); +Lockable::Lockable(const std::string &lockFilename) { + m_fd = TEMP_FAILURE_RETRY(::open(lockFilename.c_str(), O_RDONLY)); if (m_fd < 0) { LOGE("Could not open lock file <%s>", lockFilename.c_str()); @@ -47,12 +47,18 @@ FileLock::FileLock(const std::string &lockFilename) : m_lockFilename(lockFilenam LOGD("File lock file opened"); } -FileLock::~FileLock() { +Lockable::~Lockable() { ::close(m_fd); } +FileLock::FileLock(Lockable &lockable) : m_lockable(lockable) {} + +FileLock::~FileLock() { + unlock(); +} + bool FileLock::tryLock(void) { - int lock = TEMP_FAILURE_RETRY(::flock(m_fd, LOCK_EX | LOCK_NB)); + int lock = TEMP_FAILURE_RETRY(::flock(m_lockable.m_fd, LOCK_EX | LOCK_NB)); if (lock == 0) { LOGI("File lock acquired"); @@ -66,7 +72,7 @@ bool FileLock::tryLock(void) { } void FileLock::lock(void) { - int lock = TEMP_FAILURE_RETRY(::flock(m_fd, LOCK_EX)); + int lock = TEMP_FAILURE_RETRY(::flock(m_lockable.m_fd, LOCK_EX)); if (lock == -1) throw FileLockAcquiringException(errno); @@ -74,4 +80,9 @@ void FileLock::lock(void) { LOGI("File lock acquired"); } +void FileLock::unlock(void) { + LOGI("Releasing file lock"); + TEMP_FAILURE_RETRY(::flock(m_lockable.m_fd, LOCK_UN)); +} + } /* namespace Cynara */ diff --git a/src/common/lock/FileLock.h b/src/common/lock/FileLock.h index 53f048f..69311f0 100644 --- a/src/common/lock/FileLock.h +++ b/src/common/lock/FileLock.h @@ -27,16 +27,26 @@ namespace Cynara { +class FileLock; + +class Lockable { + friend FileLock; +public: + explicit Lockable(const std::string &lockFilename); + ~Lockable(); +private: + int m_fd; +}; + class FileLock { public: - explicit FileLock(const std::string &lockFilename); + explicit FileLock(Lockable &lockable); ~FileLock(); bool tryLock(void); void lock(void); - + void unlock(void); private: - std::string m_lockFilename; - int m_fd; + Lockable &m_lockable; }; } /* namespace Cynara */ -- 2.7.4 From b2abe6e5fd4ac22dc1e75b2efcb9f4177aa57a8d Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Mon, 27 Oct 2014 14:49:11 +0100 Subject: [PATCH 11/16] Lock database in Cynara::init() Change-Id: Ib90550c8dd26af899d9749901b3ab3e043fe3e2a --- src/service/main/Cynara.cpp | 5 ++++- src/service/main/Cynara.h | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/service/main/Cynara.cpp b/src/service/main/Cynara.cpp index 96443ce..a6b96c6 100644 --- a/src/service/main/Cynara.cpp +++ b/src/service/main/Cynara.cpp @@ -16,6 +16,7 @@ /** * @file src/service/main/Cynara.cpp * @author Lukasz Wojciechowski + * @author Aleksander Zdyb * @version 1.0 * @brief This file implements main class of cynara service */ @@ -40,7 +41,8 @@ namespace Cynara { Cynara::Cynara() - : m_logic(nullptr), m_socketManager(nullptr), m_storage(nullptr), m_storageBackend(nullptr) { + : m_logic(nullptr), m_socketManager(nullptr), m_storage(nullptr), m_storageBackend(nullptr), + m_lockFile(PathConfig::StoragePath::lockFile), m_databaseLock(m_lockFile) { } Cynara::~Cynara() { @@ -62,6 +64,7 @@ void Cynara::init(void) { m_socketManager->bindLogic(m_logic); + m_databaseLock.lock(); // Wait until database lock can be acquired m_storage->load(); } diff --git a/src/service/main/Cynara.h b/src/service/main/Cynara.h index 89bdd76..b138040 100644 --- a/src/service/main/Cynara.h +++ b/src/service/main/Cynara.h @@ -16,6 +16,7 @@ /** * @file src/service/main/Cynara.h * @author Lukasz Wojciechowski + * @author Aleksander Zdyb * @version 1.0 * @brief This file defines main class of cynara service */ @@ -23,6 +24,8 @@ #ifndef SRC_SERVICE_MAIN_CYNARA_H_ #define SRC_SERVICE_MAIN_CYNARA_H_ +#include + #include
namespace Cynara { @@ -43,6 +46,8 @@ private: SocketManagerPtr m_socketManager; StoragePtr m_storage; StorageBackendPtr m_storageBackend; + Lockable m_lockFile; + FileLock m_databaseLock; }; } // namespace Cynara -- 2.7.4 From 899a094acbd9523c65432a9cb9c55bd596ddc2bc Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 23 Dec 2014 14:11:15 +0100 Subject: [PATCH 12/16] Inherit from Exception in FileLockAcquiringException Change-Id: I40eb3f6b906f34261f8c6b6596e0afb503e41e7a --- src/common/exceptions/FileLockAcquiringException.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/exceptions/FileLockAcquiringException.h b/src/common/exceptions/FileLockAcquiringException.h index 44bc54a..4640719 100644 --- a/src/common/exceptions/FileLockAcquiringException.h +++ b/src/common/exceptions/FileLockAcquiringException.h @@ -30,12 +30,13 @@ namespace Cynara { -class FileLockAcquiringException { +class FileLockAcquiringException : public Exception { public: FileLockAcquiringException(const int errNumber) : m_errno(errNumber) { m_message = "File lock acquiring error [" + std::to_string(errorNumber()) + "]" + " <" + errorString() + ">"; }; + virtual ~FileLockAcquiringException() {}; const std::string &message(void) const { -- 2.7.4 From f308922e9e1ef90823bef58b504d70a5e4d7bf3a Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Wed, 17 Dec 2014 10:24:11 +0100 Subject: [PATCH 13/16] Rename admin's Logic to OnlineLogic This is a preparation to implement OfflineLogic. Change-Id: Ica6e7dfe12ac9bc921f77e2c5d08bc539373ed07 --- src/admin/CMakeLists.txt | 2 +- src/admin/api/admin-api.cpp | 4 ++-- src/admin/logic/{Logic.cpp => OnlineLogic.cpp} | 31 +++++++++++++------------- src/admin/logic/{Logic.h => OnlineLogic.h} | 18 +++++++-------- 4 files changed, 27 insertions(+), 28 deletions(-) rename src/admin/logic/{Logic.cpp => OnlineLogic.cpp} (86%) rename src/admin/logic/{Logic.h => OnlineLogic.h} (84%) diff --git a/src/admin/CMakeLists.txt b/src/admin/CMakeLists.txt index f58c751..321ca92 100644 --- a/src/admin/CMakeLists.txt +++ b/src/admin/CMakeLists.txt @@ -23,7 +23,7 @@ SET(CYNARA_LIB_CYNARA_ADMIN_PATH ${CYNARA_PATH}/admin) SET(LIB_CYNARA_ADMIN_SOURCES ${CYNARA_LIB_CYNARA_ADMIN_PATH}/api/admin-api.cpp - ${CYNARA_LIB_CYNARA_ADMIN_PATH}/logic/Logic.cpp + ${CYNARA_LIB_CYNARA_ADMIN_PATH}/logic/OnlineLogic.cpp ) INCLUDE_DIRECTORIES( diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 401df51..1dfeb90 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -43,7 +43,7 @@ #include #include -#include +#include struct cynara_admin { Cynara::ApiInterface *impl; @@ -61,7 +61,7 @@ int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) { return CYNARA_API_INVALID_PARAM; return Cynara::tryCatch([&]() { - *pp_cynara_admin = new cynara_admin(new Cynara::Logic); + *pp_cynara_admin = new cynara_admin(new Cynara::OnlineLogic); init_log(); diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/OnlineLogic.cpp similarity index 86% rename from src/admin/logic/Logic.cpp rename to src/admin/logic/OnlineLogic.cpp index b0ea895..9aa1831 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/OnlineLogic.cpp @@ -14,10 +14,11 @@ * limitations under the License */ /** - * @file src/admin/logic/Logic.cpp + * @file src/admin/logic/OnlineLogic.cpp * @author Lukasz Wojciechowski + * @author Aleksander Zdyb * @version 1.0 - * @brief This file contains implementation of Logic class - main libcynara-admin class + * @brief This file contains implementation of online version of Logic class */ #include @@ -45,11 +46,11 @@ #include #include -#include "Logic.h" +#include "OnlineLogic.h" namespace Cynara { -Logic::Logic() { +OnlineLogic::OnlineLogic() { m_socketClient = std::make_shared(PathConfig::SocketPath::admin, std::make_shared()); } @@ -59,12 +60,12 @@ ProtocolFrameSequenceNumber generateSequenceNumber(void) { return ++sequenceNumber; } -bool Logic::ensureConnection(void) { +bool OnlineLogic::ensureConnection(void) { return m_socketClient->isConnected() || m_socketClient->connect(); } template -int Logic::askCynaraAndInterpreteCodeResponse(Args... args) { +int OnlineLogic::askCynaraAndInterpreteCodeResponse(Args... args) { if (!ensureConnection()) { LOGE("Cannot connect to cynara. Service not available."); return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -109,22 +110,22 @@ int Logic::askCynaraAndInterpreteCodeResponse(Args... args) { } } -int Logic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, - const ApiInterface::KeysByBucket &remove) { +int OnlineLogic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, + const ApiInterface::KeysByBucket &remove) { return askCynaraAndInterpreteCodeResponse(insertOrUpdate, remove); } -int Logic::insertOrUpdateBucket(const PolicyBucketId &bucket, - const PolicyResult &policyResult) { +int OnlineLogic::insertOrUpdateBucket(const PolicyBucketId &bucket, + const PolicyResult &policyResult) { return askCynaraAndInterpreteCodeResponse(bucket, policyResult); } -int Logic::removeBucket(const PolicyBucketId &bucket) { +int OnlineLogic::removeBucket(const PolicyBucketId &bucket) { return askCynaraAndInterpreteCodeResponse(bucket); } -int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, - PolicyResult &result) { +int OnlineLogic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, + PolicyResult &result) { if (!ensureConnection()) { LOGE("Cannot connect to cynara. Service not available."); return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -163,7 +164,7 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P return CYNARA_API_SUCCESS; } -int Logic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, +int OnlineLogic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies) { if (!ensureConnection()) { LOGE("Cannot connect to cynara. Service not available."); @@ -199,7 +200,7 @@ int Logic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, return CYNARA_API_SUCCESS; } -int Logic::erasePolicies(const PolicyBucketId &startBucket, bool recursive, +int OnlineLogic::erasePolicies(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &filter) { return askCynaraAndInterpreteCodeResponse(startBucket, recursive, filter); } diff --git a/src/admin/logic/Logic.h b/src/admin/logic/OnlineLogic.h similarity index 84% rename from src/admin/logic/Logic.h rename to src/admin/logic/OnlineLogic.h index 584d35d..19e3304 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/OnlineLogic.h @@ -14,16 +14,14 @@ * limitations under the License */ /** - * @file src/admin/logic/Logic.h + * @file src/admin/logic/OnlineLogic.h * @author Lukasz Wojciechowski * @version 1.0 - * @brief This file contains definition of Logic class - main libcynara-admin class + * @brief This file contains definition of online version of Logic class */ -#ifndef SRC_ADMIN_LOGIC_LOGIC_H_ -#define SRC_ADMIN_LOGIC_LOGIC_H_ - -#include +#ifndef SRC_ADMIN_LOGIC_ONLINELOGIC_H_ +#define SRC_ADMIN_LOGIC_ONLINELOGIC_H_ #include @@ -31,7 +29,7 @@ namespace Cynara { -class Logic : public ApiInterface { +class OnlineLogic : public ApiInterface { private: SocketClientPtr m_socketClient; @@ -40,8 +38,8 @@ private: int askCynaraAndInterpreteCodeResponse(Args... args); public: - Logic(); - virtual ~Logic() {}; + OnlineLogic(); + virtual ~OnlineLogic() {}; virtual int setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, const ApiInterface::KeysByBucket &remove); @@ -59,4 +57,4 @@ public: } // namespace Cynara -#endif /* SRC_ADMIN_LOGIC_LOGIC_H_ */ +#endif /* SRC_ADMIN_LOGIC_ONLINELOGIC_H_ */ -- 2.7.4 From 14d1fb229ad782830543cb3ac04b58a46c67f504 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 23 Dec 2014 14:21:47 +0100 Subject: [PATCH 14/16] Implement detection of online/offline mode in admin Change-Id: I93a2af08266d7606491abf4f89bf16663c7d0e15 --- src/admin/CMakeLists.txt | 4 ++ src/admin/api/admin-api.cpp | 10 ++- src/admin/logic/Logic.cpp | 95 ++++++++++++++++++++++++++++ src/admin/logic/Logic.h | 67 ++++++++++++++++++++ src/admin/logic/OfflineLogic.cpp | 133 +++++++++++++++++++++++++++++++++++++++ src/admin/logic/OfflineLogic.h | 68 ++++++++++++++++++++ 6 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 src/admin/logic/Logic.cpp create mode 100644 src/admin/logic/Logic.h create mode 100644 src/admin/logic/OfflineLogic.cpp create mode 100644 src/admin/logic/OfflineLogic.h diff --git a/src/admin/CMakeLists.txt b/src/admin/CMakeLists.txt index 321ca92..3cbff78 100644 --- a/src/admin/CMakeLists.txt +++ b/src/admin/CMakeLists.txt @@ -23,10 +23,13 @@ SET(CYNARA_LIB_CYNARA_ADMIN_PATH ${CYNARA_PATH}/admin) SET(LIB_CYNARA_ADMIN_SOURCES ${CYNARA_LIB_CYNARA_ADMIN_PATH}/api/admin-api.cpp + ${CYNARA_LIB_CYNARA_ADMIN_PATH}/logic/Logic.cpp + ${CYNARA_LIB_CYNARA_ADMIN_PATH}/logic/OfflineLogic.cpp ${CYNARA_LIB_CYNARA_ADMIN_PATH}/logic/OnlineLogic.cpp ) INCLUDE_DIRECTORIES( + ${CYNARA_PATH} ${CYNARA_PATH}/include ${CYNARA_LIB_CYNARA_ADMIN_PATH} ) @@ -43,6 +46,7 @@ SET_TARGET_PROPERTIES( TARGET_LINK_LIBRARIES(${TARGET_LIB_CYNARA_ADMIN} ${CYNARA_DEP_LIBRARIES} ${TARGET_CYNARA_COMMON} + ${TARGET_LIB_CYNARA_STORAGE} ) INSTALL(TARGETS ${TARGET_LIB_CYNARA_ADMIN} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 1dfeb90..d3b6a36 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -43,7 +44,7 @@ #include #include -#include +#include struct cynara_admin { Cynara::ApiInterface *impl; @@ -61,7 +62,12 @@ int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) { return CYNARA_API_INVALID_PARAM; return Cynara::tryCatch([&]() { - *pp_cynara_admin = new cynara_admin(new Cynara::OnlineLogic); + try { + *pp_cynara_admin = new cynara_admin(new Cynara::Logic); + } catch (const Cynara::FileLockAcquiringException &ex) { + LOGE("%s", ex.what()); + return CYNARA_API_OPERATION_FAILED; + } init_log(); diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp new file mode 100644 index 0000000..57fc0b5 --- /dev/null +++ b/src/admin/logic/Logic.cpp @@ -0,0 +1,95 @@ +/* + * 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/admin/logic/Logic.cpp + * @author Lukasz Wojciechowski + * @author Aleksander Zdyb + * @version 1.0 + * @brief This file contains implementation of Logic class - main libcynara-admin class + */ + +#include +#include +#include + +#include "Logic.h" +#include "OfflineLogic.h" +#include "OnlineLogic.h" + +namespace Cynara { + +Logic::Logic() : m_onlineLogic(new OnlineLogic()), m_offlineLogic(new OfflineLogic()), + m_lockable(PathConfig::StoragePath::lockFile) {} + +Logic::~Logic() { + delete m_onlineLogic; + delete m_offlineLogic; +} + +int Logic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, + const ApiInterface::KeysByBucket &remove) { + using std::placeholders::_1; + return callApiFunction(std::bind(&ApiInterface::setPolicies, _1, + std::cref(insertOrUpdate), std::cref(remove))); +} + +int Logic::insertOrUpdateBucket(const PolicyBucketId &bucket, + const PolicyResult &policyResult) { + using std::placeholders::_1; + auto f = std::bind(&ApiInterface::insertOrUpdateBucket, _1, + std::cref(bucket), std::cref(policyResult)); + return callApiFunction(f); +} + +int Logic::removeBucket(const PolicyBucketId &bucket) { + using std::placeholders::_1; + return callApiFunction(std::bind(&ApiInterface::removeBucket, _1, std::cref(bucket))); +} + +int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, + PolicyResult &result) { + using std::placeholders::_1; + return callApiFunction(std::bind(&ApiInterface::adminCheck, _1, std::cref(startBucket), + recursive, std::cref(key), std::ref(result))); +} + +int Logic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, + std::vector &policies) { + using std::placeholders::_1; + return callApiFunction(std::bind(&ApiInterface::listPolicies, _1, std::cref(bucket), + std::cref(filter), std::ref(policies))); +} + +int Logic::erasePolicies(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &filter) { + using std::placeholders::_1; + return callApiFunction(std::bind(&ApiInterface::erasePolicies, _1, std::cref(startBucket), + recursive, std::cref(filter))); +} + +int Logic::callApiFunction(std::function apiCall) { + FileLock lock(m_lockable); + if (lock.tryLock() == true) { + m_offlineLogic->acquireDatabase(); + LOGI("Admin uses offline API"); + return apiCall(m_offlineLogic); + } else { + LOGI("Admin uses online API"); + return apiCall(m_onlineLogic); + } +} + +} // namespace Cynara diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h new file mode 100644 index 0000000..9a24de7 --- /dev/null +++ b/src/admin/logic/Logic.h @@ -0,0 +1,67 @@ +/* + * 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/admin/logic/Logic.h + * @author Lukasz Wojciechowski + * @author Aleksander Zdyb + * @version 1.0 + * @brief This file contains definition of Logic class - main libcynara-admin class + */ + +#ifndef SRC_ADMIN_LOGIC_LOGIC_H_ +#define SRC_ADMIN_LOGIC_LOGIC_H_ + +#include + +#include + +#include + +namespace Cynara { + +class OnlineLogic; +class OfflineLogic; + +class Logic : public ApiInterface { + +public: + Logic(); + virtual ~Logic(); + + virtual int setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, + const ApiInterface::KeysByBucket &remove); + virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, + const PolicyResult &policyResult); + virtual int removeBucket(const PolicyBucketId &bucket); + virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, + 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); + +protected: + int callApiFunction(std::function apiCall); + +private: + OnlineLogic *m_onlineLogic; + OfflineLogic *m_offlineLogic; + Lockable m_lockable; +}; + +} // namespace Cynara + +#endif /* SRC_ADMIN_LOGIC_LOGIC_H_ */ diff --git a/src/admin/logic/OfflineLogic.cpp b/src/admin/logic/OfflineLogic.cpp new file mode 100644 index 0000000..a52a0fe --- /dev/null +++ b/src/admin/logic/OfflineLogic.cpp @@ -0,0 +1,133 @@ +/* + * 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/admin/logic/OfflineLogic.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief This file contains implementation of OfflineLogic class + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "OfflineLogic.h" + +namespace Cynara { + +OfflineLogic::OfflineLogic() {} + +void OfflineLogic::acquireDatabase(void) { + m_storageBackend.reset(new InMemoryStorageBackend(PathConfig::StoragePath::dbDir)); + m_storage.reset(new Storage(*m_storageBackend)); + m_storage->load(); +} + +int OfflineLogic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, + const ApiInterface::KeysByBucket &remove) { + try { + m_storage->insertPolicies(insertOrUpdate); + m_storage->deletePolicies(remove); + onPoliciesChanged(); + } catch (const BucketNotExistsException &) { + return CYNARA_API_BUCKET_NOT_FOUND; + } catch (const DatabaseException &) { + return CYNARA_API_OPERATION_FAILED; + } + + return CYNARA_API_SUCCESS; +} + +int OfflineLogic::insertOrUpdateBucket(const PolicyBucketId &bucket, + const PolicyResult &policyResult) { + try { + m_storage->addOrUpdateBucket(bucket, policyResult); + onPoliciesChanged(); + } catch (const DefaultBucketSetNoneException &) { + return CYNARA_API_OPERATION_NOT_ALLOWED; + } catch (const InvalidBucketIdException &ex) { + return CYNARA_API_OPERATION_NOT_ALLOWED; + } catch (const DatabaseException &) { + return CYNARA_API_OPERATION_FAILED; + } + + return CYNARA_API_SUCCESS; +} + +int OfflineLogic::removeBucket(const PolicyBucketId &bucket) { + try { + m_storage->deleteBucket(bucket); + onPoliciesChanged(); + } catch (const BucketNotExistsException &) { + return CYNARA_API_BUCKET_NOT_FOUND; + } catch (const DefaultBucketDeletionException &) { + return CYNARA_API_OPERATION_NOT_ALLOWED; + } catch (const DatabaseException &) { + return CYNARA_API_OPERATION_FAILED; + } + + return CYNARA_API_SUCCESS; +} + +int OfflineLogic::adminCheck(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &key, PolicyResult &result) { + try { + result = m_storage->checkPolicy(key, startBucket, recursive); + } catch (const BucketNotExistsException &ex) { + return CYNARA_API_BUCKET_NOT_FOUND; + } + + return CYNARA_API_SUCCESS; +} + +int OfflineLogic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, + std::vector &policies) { + try { + policies = m_storage->listPolicies(bucket, filter); + } catch (const BucketNotExistsException &ex) { + return CYNARA_API_BUCKET_NOT_FOUND; + } + + return CYNARA_API_SUCCESS; +} + +int OfflineLogic::erasePolicies(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &filter) { + try { + m_storage->erasePolicies(startBucket, recursive, filter); + onPoliciesChanged(); + } catch (const BucketNotExistsException &) { + return CYNARA_API_BUCKET_NOT_FOUND; + } + + return CYNARA_API_SUCCESS; +} + +void OfflineLogic::onPoliciesChanged(void) { + m_storage->save(); +} + +} /* namespace Cynara */ diff --git a/src/admin/logic/OfflineLogic.h b/src/admin/logic/OfflineLogic.h new file mode 100644 index 0000000..ec180f2 --- /dev/null +++ b/src/admin/logic/OfflineLogic.h @@ -0,0 +1,68 @@ +/* + * 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/admin/logic/OfflineLogic.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief This file contains definition of OfflineLogic class + */ + +#ifndef SRC_ADMIN_LOGIC_OFFLINELOGIC_H_ +#define SRC_ADMIN_LOGIC_OFFLINELOGIC_H_ + +#include + +#include + +#include +#include + +#include + +namespace Cynara { + +class OfflineLogic : public ApiInterface { +public: + OfflineLogic(); + + void acquireDatabase(void); + + int setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, + const ApiInterface::KeysByBucket &remove); + int insertOrUpdateBucket(const PolicyBucketId &bucket, + const PolicyResult &policyResult); + int removeBucket(const PolicyBucketId &bucket); + int adminCheck(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &key, PolicyResult &result); + int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, + std::vector &policies); + int erasePolicies(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &filter); + +protected: + void onPoliciesChanged(void); + +private: + typedef std::unique_ptr StorageUniquePtr; + typedef std::unique_ptr StorageBackendUniquePtr; + + StorageUniquePtr m_storage; + StorageBackendUniquePtr m_storageBackend; +}; + +} /* namespace Cynara */ + +#endif /* SRC_ADMIN_LOGIC_OFFLINELOGIC_H_ */ -- 2.7.4 From 582e79ea7c430629a9ee5fa432839956174c736d Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Tue, 16 Dec 2014 16:48:58 +0100 Subject: [PATCH 15/16] Add listing types of policies Change-Id: Iab51f7ec232fb711ac6945be1ce71effa7e59ef1 --- src/client-async/logic/Logic.cpp | 4 +-- src/client-common/CMakeLists.txt | 1 - src/client-common/cache/CacheInterface.h | 8 ++--- src/client-common/plugins/NaiveInterpreter.cpp | 30 ---------------- src/client-common/plugins/NaiveInterpreter.h | 7 ++-- src/client/logic/Logic.cpp | 4 +-- src/common/CMakeLists.txt | 2 ++ src/common/plugin/ExternalPluginInterface.h | 7 ++-- src/common/plugin/PluginManager.cpp | 18 +++++++--- src/common/plugin/PluginManager.h | 5 ++- src/common/types/PolicyDescription.cpp | 36 +++++++++++++++++++ src/common/types/PolicyDescription.h | 48 ++++++++++++++++++++++++++ src/include/cynara-client-plugin.h | 3 +- 13 files changed, 119 insertions(+), 54 deletions(-) delete mode 100644 src/client-common/plugins/NaiveInterpreter.cpp create mode 100644 src/common/types/PolicyDescription.cpp create mode 100644 src/common/types/PolicyDescription.h diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 48b8bad..7504c7e 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -50,8 +50,8 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); - for (auto &type : naiveInterpreter->getSupportedPolicyTypes()) { - m_cache->registerPlugin(type, naiveInterpreter); + for (auto &descr : naiveInterpreter->getSupportedPolicyDescr()) { + m_cache->registerPlugin(descr, naiveInterpreter); } } diff --git a/src/client-common/CMakeLists.txt b/src/client-common/CMakeLists.txt index bb02eca..2c60ca9 100644 --- a/src/client-common/CMakeLists.txt +++ b/src/client-common/CMakeLists.txt @@ -28,7 +28,6 @@ INCLUDE_DIRECTORIES( SET(LIB_CYNARA_COMMON_SOURCES ${LIB_CYNARA_COMMON_PATH}/cache/CapacityCache.cpp - ${LIB_CYNARA_COMMON_PATH}/plugins/NaiveInterpreter.cpp ) ADD_DEFINITIONS("-fvisibility=default") diff --git a/src/client-common/cache/CacheInterface.h b/src/client-common/cache/CacheInterface.h index 03b7624..bbd18c8 100644 --- a/src/client-common/cache/CacheInterface.h +++ b/src/client-common/cache/CacheInterface.h @@ -31,9 +31,9 @@ #include #include #include +#include #include #include -#include namespace Cynara { @@ -48,8 +48,8 @@ public: const PolicyKey &key, const PolicyResult &result) = 0; - void registerPlugin(const PolicyType policyType, ClientPluginInterfacePtr plugin) { - m_plugins[policyType] = plugin; + void registerPlugin(const PolicyDescription &policyDescr, ClientPluginInterfacePtr plugin) { + m_plugins[policyDescr] = plugin; } virtual void clear(void) { @@ -59,7 +59,7 @@ public: virtual ~PluginCache() {}; protected: - std::map m_plugins; + std::map m_plugins; }; } // namespace Cynara diff --git a/src/client-common/plugins/NaiveInterpreter.cpp b/src/client-common/plugins/NaiveInterpreter.cpp deleted file mode 100644 index 7141cb7..0000000 --- a/src/client-common/plugins/NaiveInterpreter.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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/client-common/plugins/NaiveInterpreter.cpp - * @author Zofia Abramowska - * @version 1.0 - * @brief This file contains NaiveInterpreter supported types definition. - */ - -#include - -namespace Cynara { - - const std::vector NaiveInterpreter::s_supportedTypes = - {PredefinedPolicyType::ALLOW, PredefinedPolicyType::DENY}; - -} diff --git a/src/client-common/plugins/NaiveInterpreter.h b/src/client-common/plugins/NaiveInterpreter.h index 059554d..a0e2d67 100644 --- a/src/client-common/plugins/NaiveInterpreter.h +++ b/src/client-common/plugins/NaiveInterpreter.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace Cynara { @@ -45,13 +46,11 @@ public: return CYNARA_API_ACCESS_DENIED; } - const std::vector &getSupportedPolicyTypes(void) { - return s_supportedTypes; + const std::vector &getSupportedPolicyDescr(void) { + return predefinedPolicyDescr; } void invalidate(void) {} -private: - static const std::vector s_supportedTypes; }; } // namespace Cynara diff --git a/src/client/logic/Logic.cpp b/src/client/logic/Logic.cpp index 498e53c..f8fc543 100644 --- a/src/client/logic/Logic.cpp +++ b/src/client/logic/Logic.cpp @@ -52,8 +52,8 @@ Logic::Logic() { std::make_shared()); m_cache = std::make_shared(); auto naiveInterpreter = std::make_shared(); - for (auto &type : naiveInterpreter->getSupportedPolicyTypes()) { - m_cache->registerPlugin(type, naiveInterpreter); + for (auto &descr : naiveInterpreter->getSupportedPolicyDescr()) { + m_cache->registerPlugin(descr, naiveInterpreter); } } diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 37073ad..fe2f727 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -62,9 +62,11 @@ SET(COMMON_SOURCES ${COMMON_PATH}/sockets/Socket.cpp ${COMMON_PATH}/sockets/SocketClient.cpp ${COMMON_PATH}/types/PolicyBucket.cpp + ${COMMON_PATH}/types/PolicyDescription.cpp ${COMMON_PATH}/types/PolicyKey.cpp ${COMMON_PATH}/types/PolicyKeyHelpers.cpp ${COMMON_PATH}/types/PolicyResult.cpp + ${COMMON_PATH}/types/PolicyType.cpp ) IF (CMAKE_BUILD_TYPE MATCHES "DEBUG") diff --git a/src/common/plugin/ExternalPluginInterface.h b/src/common/plugin/ExternalPluginInterface.h index ddd8363..f4e8a63 100644 --- a/src/common/plugin/ExternalPluginInterface.h +++ b/src/common/plugin/ExternalPluginInterface.h @@ -25,7 +25,7 @@ #include -#include +#include namespace Cynara { @@ -47,11 +47,10 @@ typedef void (*destroy_t)(ExternalPluginInterface *); class ExternalPluginInterface { public: - /** - * Policy type supported by plugin. + * Policy types supported by plugin. */ - virtual const std::vector &getSupportedPolicyTypes(void) = 0; + virtual const std::vector &getSupportedPolicyDescr(void) = 0; /** * Informs, that every data stored based on previously given input diff --git a/src/common/plugin/PluginManager.cpp b/src/common/plugin/PluginManager.cpp index c8a38c5..300dc7f 100644 --- a/src/common/plugin/PluginManager.cpp +++ b/src/common/plugin/PluginManager.cpp @@ -65,6 +65,15 @@ ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) { return m_plugins[pType]; } +std::vector PluginManager::getPolicyDescriptions(void) const { + std::vector descriptions; + descriptions.reserve(m_plugins.size()); + for (auto &plugin : m_plugins) { + descriptions.push_back(plugin.first); + } + return descriptions; +} + void PluginManager::invalidateAll(void) { for (auto &plugin : m_plugins) { plugin.second->invalidate(); @@ -125,14 +134,15 @@ void PluginManager::openPlugin(const std::string &path) { return; } - auto policies = pluginPtr->getSupportedPolicyTypes(); + auto policies = pluginPtr->getSupportedPolicyDescr(); if (policies.empty()) { LOGE("Plugin <%s> does not support any type!", path.c_str()); return; } - for (auto type : policies) { - if (!m_plugins.insert(std::make_pair(type, pluginPtr)).second) { - LOGW("policyType [%" PRIu16 "] was already supported.", type); + for (auto &desc : policies) { + if (!m_plugins.insert(std::make_pair(desc, pluginPtr)).second) { + LOGW("policy type: [%" PRIu16 "] name: <%s> was already supported.", + desc.type, desc.name.c_str()); } } diff --git a/src/common/plugin/PluginManager.h b/src/common/plugin/PluginManager.h index 8de33ae..87b0597 100644 --- a/src/common/plugin/PluginManager.h +++ b/src/common/plugin/PluginManager.h @@ -28,8 +28,10 @@ #include #include #include +#include #include +#include namespace Cynara { typedef std::shared_ptr ExternalPluginPtr; @@ -38,6 +40,7 @@ class PluginManager { public: PluginManager(const std::string &pluginDir); ExternalPluginPtr getPlugin(PolicyType pType); + std::vector getPolicyDescriptions(void) const; void invalidateAll(void); ~PluginManager(); @@ -46,7 +49,7 @@ private: typedef std::list PluginLibs; std::string m_dir; - std::map m_plugins; + std::map m_plugins; PluginLibs m_pluginLibs; void loadPlugins(void); diff --git a/src/common/types/PolicyDescription.cpp b/src/common/types/PolicyDescription.cpp new file mode 100644 index 0000000..1c06137 --- /dev/null +++ b/src/common/types/PolicyDescription.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/types/PolicyDescription.cpp + * @author Zofia Abramowska + * @version 1.0 + * @brief Implementation of functions for Cynara::PolicyDescription + */ + +#include "PolicyDescription.h" + +namespace Cynara { + +const std::vector predefinedPolicyDescr = { + PolicyDescription(PredefinedPolicyType::ALLOW, "Allow"), + PolicyDescription(PredefinedPolicyType::DENY, "Deny") +}; + +bool operator<(const PolicyDescription &left, const PolicyDescription &right) { + return left.type < right.type; +} + +} // namespace Cynara diff --git a/src/common/types/PolicyDescription.h b/src/common/types/PolicyDescription.h new file mode 100644 index 0000000..b4d27d5 --- /dev/null +++ b/src/common/types/PolicyDescription.h @@ -0,0 +1,48 @@ +/* + * 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/types/PolicyDescription.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file defines PolicyDescription for storing policy type + * description. + */ + +#ifndef SRC_COMMON_TYPES_POLICYDESCRIPTION_H_ +#define SRC_COMMON_TYPES_POLICYDESCRIPTION_H_ + +#include + +#include +#include + +namespace Cynara { + +struct PolicyDescription { + PolicyDescription(const PolicyType &pType, const std::string &pName) : type(pType), name(pName) + {}; + PolicyDescription(const PolicyType &pType) : type(pType) {}; + PolicyType type; + std::string name; +}; + +extern const std::vector predefinedPolicyDescr; + +bool operator<(const PolicyDescription &left, const PolicyDescription &right); + +} // namespace Cynara + +#endif /* SRC_COMMON_TYPES_POLICYDESCRIPTION_H_ */ diff --git a/src/include/cynara-client-plugin.h b/src/include/cynara-client-plugin.h index 3d39ad7..29e32ce 100644 --- a/src/include/cynara-client-plugin.h +++ b/src/include/cynara-client-plugin.h @@ -51,13 +51,12 @@ typedef std::shared_ptr ClientPluginInterfacePtr; */ class ClientPluginInterface : public ExternalPluginInterface { public: - /** * Return entry cacheability */ virtual bool isCacheable(const ClientSession &session, const PolicyResult &result) = 0; /** - * Return entry cacheability + * Return entry usability */ virtual bool isUsable(const ClientSession &session, const ClientSession &prevSession, bool &updateSession, PolicyResult &result) = 0; -- 2.7.4 From c58b6587a522499aac183ea5116d3ce69462b0f7 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 19 Dec 2014 10:52:22 +0100 Subject: [PATCH 16/16] Add api side implementation of plugin descriptions listing Add: * description of api function cynara_admin_list_policies_descriptions * implementation in admin-api * utilities for creating null terminated array Change-Id: I4b7d56757e22fab4cce81665f16ceef61f3a0e2c --- src/admin/api/ApiInterface.h | 2 + src/admin/api/admin-api.cpp | 116 +++++++++++++++++++++++---------------- src/admin/logic/Logic.cpp | 5 ++ src/admin/logic/Logic.h | 1 + src/admin/logic/OfflineLogic.cpp | 5 ++ src/admin/logic/OfflineLogic.h | 1 + src/admin/logic/OnlineLogic.cpp | 5 ++ src/admin/logic/OnlineLogic.h | 2 +- src/admin/logic/Utility.h | 69 +++++++++++++++++++++++ src/include/cynara-admin-types.h | 13 +++++ src/include/cynara-admin.h | 49 +++++++++++++++++ 11 files changed, 219 insertions(+), 49 deletions(-) create mode 100644 src/admin/logic/Utility.h diff --git a/src/admin/api/ApiInterface.h b/src/admin/api/ApiInterface.h index 89ac978..9484b7f 100644 --- a/src/admin/api/ApiInterface.h +++ b/src/admin/api/ApiInterface.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -56,6 +57,7 @@ public: std::vector &policies) = 0; virtual int erasePolicies(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &filter) = 0; + virtual int listDescriptions(std::vector &descriptions) = 0; }; diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index d3b6a36..10077df 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -22,11 +22,9 @@ #include #include -#include -#include #include #include -#include +#include #include #include @@ -36,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +44,8 @@ #include #include +#include +#include struct cynara_admin { Cynara::ApiInterface *impl; @@ -228,59 +229,40 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin, }); } -static int createPoliciesArray(const char *bucket, - const std::vector &policiesVector, - struct cynara_admin_policy ***policies) { - typedef struct cynara_admin_policy Elem; - size_t elems = policiesVector.size(); - - Elem **tab = reinterpret_cast(calloc(elems + 1U, sizeof(Elem*))); - if (!tab) +static int copyPolicy(const char *bucket, const Cynara::Policy &from, cynara_admin_policy *&to) { + to = reinterpret_cast(calloc(1, sizeof(cynara_admin_policy))); + if (!to) return CYNARA_API_OUT_OF_MEMORY; - std::unique_ptr> plumber(tab, - [](Elem **tab) { - 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); - }); - - for (size_t i = 0U; i < elems; ++i) { - tab[i] = reinterpret_cast(calloc(1U, sizeof(Elem))); - if (!tab[i]) - return CYNARA_API_OUT_OF_MEMORY; - - tab[i]->bucket = strdup(bucket); - if (!tab[i]->bucket) + to->bucket = strdup(bucket); + if (!to->bucket) + return CYNARA_API_OUT_OF_MEMORY; + to->client = strdup(from.key().client().value().c_str()); + if (!to->client) return CYNARA_API_OUT_OF_MEMORY; - - tab[i]->client = strdup(policiesVector[i].key().client().value().c_str()); - if (!tab[i]->client) + to->user = strdup(from.key().user().value().c_str()); + if (!to->user) return CYNARA_API_OUT_OF_MEMORY; - tab[i]->user = strdup(policiesVector[i].key().user().value().c_str()); - if (!tab[i]->user) + to->privilege = strdup(from.key().privilege().value().c_str()); + if (!to->privilege) return CYNARA_API_OUT_OF_MEMORY; - tab[i]->privilege = strdup(policiesVector[i].key().privilege().value().c_str()); - if (!tab[i]->privilege) + to->result = static_cast(from.result().policyType()); + if (!from.result().metadata().empty()) { + to->result_extra = strdup(from.result().metadata().c_str()); + if (!to->result_extra) return CYNARA_API_OUT_OF_MEMORY; - - tab[i]->result = static_cast(policiesVector[i].result().policyType()); - if (!policiesVector[i].result().metadata().empty()) { - tab[i]->result_extra = strdup(policiesVector[i].result().metadata().c_str()); - if (!tab[i]->result_extra) - return CYNARA_API_OUT_OF_MEMORY; - } } - *policies = tab; - plumber.release(); return CYNARA_API_SUCCESS; } +static void freeElem(struct cynara_admin_policy *policyPtr) { + free(policyPtr->bucket); + free(policyPtr->client); + free(policyPtr->user); + free(policyPtr->privilege); + free(policyPtr->result_extra); + free(policyPtr); +} + CYNARA_API int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char *bucket, const char *client, const char *user, const char *privilege, @@ -313,7 +295,45 @@ int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char * if (ret != CYNARA_API_SUCCESS) return ret; - return createPoliciesArray(bucket, policiesVector, policies); + auto copyFun = std::bind(copyPolicy, bucket, std::placeholders::_1, std::placeholders::_2); + return Cynara::createNullTerminatedArray + (policiesVector, policies, copyFun); + }); +} + +static int copyDescr(const Cynara::PolicyDescription &from, cynara_admin_policy_descr *&to) { + to = reinterpret_cast(calloc(1, sizeof(cynara_admin_policy_descr))); + if (!to) + return CYNARA_API_OUT_OF_MEMORY; + to->result = static_cast(from.type); + to->name = strdup(from.name.c_str()); + if (!to->name) + return CYNARA_API_OUT_OF_MEMORY; + return CYNARA_API_SUCCESS; +} + +static void freeElem(struct cynara_admin_policy_descr *descrPtr) { + free(descrPtr->name); + free(descrPtr); +} + +CYNARA_API +int cynara_admin_list_policies_descriptions(struct cynara_admin *p_cynara_admin, + struct cynara_admin_policy_descr ***descriptions) { + if (!p_cynara_admin || !p_cynara_admin->impl) + return CYNARA_API_INVALID_PARAM; + if (!descriptions) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&p_cynara_admin, &descriptions] () { + std::vector descriptionsVector; + int ret = p_cynara_admin->impl->listDescriptions(descriptionsVector); + + if (ret != CYNARA_API_SUCCESS) + return ret; + return Cynara::createNullTerminatedArray + (descriptionsVector, descriptions, copyDescr); }); } diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 57fc0b5..3f23370 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -66,6 +66,11 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P recursive, std::cref(key), std::ref(result))); } +int Logic::listDescriptions(std::vector &descriptions) { + using std::placeholders::_1; + return callApiFunction(std::bind(&ApiInterface::listDescriptions, _1, std::ref(descriptions))); +} + int Logic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies) { using std::placeholders::_1; diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h index 9a24de7..e9c7774 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/Logic.h @@ -48,6 +48,7 @@ public: virtual int removeBucket(const PolicyBucketId &bucket); virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, PolicyResult &result); + virtual int listDescriptions(std::vector &descriptions); virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies); virtual int erasePolicies(const PolicyBucketId &startBucket, bool recursive, diff --git a/src/admin/logic/OfflineLogic.cpp b/src/admin/logic/OfflineLogic.cpp index a52a0fe..c860ad8 100644 --- a/src/admin/logic/OfflineLogic.cpp +++ b/src/admin/logic/OfflineLogic.cpp @@ -103,6 +103,11 @@ int OfflineLogic::adminCheck(const PolicyBucketId &startBucket, bool recursive, return CYNARA_API_SUCCESS; } +int OfflineLogic::listDescriptions(std::vector &descriptions) { + (void) descriptions; + return CYNARA_API_SUCCESS; +} + int OfflineLogic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies) { try { diff --git a/src/admin/logic/OfflineLogic.h b/src/admin/logic/OfflineLogic.h index ec180f2..fc04d5e 100644 --- a/src/admin/logic/OfflineLogic.h +++ b/src/admin/logic/OfflineLogic.h @@ -47,6 +47,7 @@ public: int removeBucket(const PolicyBucketId &bucket); int adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, PolicyResult &result); + int listDescriptions(std::vector &descriptions); int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies); int erasePolicies(const PolicyBucketId &startBucket, bool recursive, diff --git a/src/admin/logic/OnlineLogic.cpp b/src/admin/logic/OnlineLogic.cpp index 9aa1831..6626a77 100644 --- a/src/admin/logic/OnlineLogic.cpp +++ b/src/admin/logic/OnlineLogic.cpp @@ -205,4 +205,9 @@ int OnlineLogic::erasePolicies(const PolicyBucketId &startBucket, bool recursive return askCynaraAndInterpreteCodeResponse(startBucket, recursive, filter); } +int OnlineLogic::listDescriptions(std::vector &descriptions) { + (void) descriptions; + return CYNARA_API_SUCCESS; +} + } // namespace Cynara diff --git a/src/admin/logic/OnlineLogic.h b/src/admin/logic/OnlineLogic.h index 19e3304..84becd7 100644 --- a/src/admin/logic/OnlineLogic.h +++ b/src/admin/logic/OnlineLogic.h @@ -52,7 +52,7 @@ public: std::vector &policies); virtual int erasePolicies(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &filter); - + virtual int listDescriptions(std::vector &descriptions); }; } // namespace Cynara diff --git a/src/admin/logic/Utility.h b/src/admin/logic/Utility.h new file mode 100644 index 0000000..10e62da --- /dev/null +++ b/src/admin/logic/Utility.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co. + * + * 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/admin/logic/Utility.h + * @author Zofia Abramowska + * @version 1.0 + * @brief This file contains implementation of utility function for managing null pointer + * terminated lists. + */ + +#ifndef SRC_ADMIN_LOGIC_UTILITY_H_ +#define SRC_ADMIN_LOGIC_UTILITY_H_ + +#include +#include +#include +#include + +#include + +namespace Cynara { + +//This function requires proper freeElem function for given type T. +template +static void freeNullTerminatedList(T **list) { + for (int i = 0; list[i]; i++) { + freeElem(list[i]); + } + free(list); +} + +template +static int createNullTerminatedArray(const std::vector &vectorized, T ***array, + std::function copyFun) { + size_t elems = vectorized.size(); + + T **tab = reinterpret_cast(calloc(elems + 1U, sizeof(T*))); + if (!tab) + return CYNARA_API_OUT_OF_MEMORY; + + std::unique_ptr> plumber(tab, freeNullTerminatedList); + + for (size_t i = 0; i < elems; i++) { + int ret = copyFun(vectorized[i], tab[i]); + if (ret != CYNARA_API_SUCCESS) + return ret; + } + + *array = tab; + plumber.release(); + return CYNARA_API_SUCCESS; +} + +} // namespace Cynara + +#endif /* SRC_ADMIN_LOGIC_UTILITY_H_ */ diff --git a/src/include/cynara-admin-types.h b/src/include/cynara-admin-types.h index b83c81d..bb4c1bf 100644 --- a/src/include/cynara-admin-types.h +++ b/src/include/cynara-admin-types.h @@ -17,6 +17,7 @@ * \file src/include/cynara-admin-types.h * \author Lukasz Wojciechowski * \author Aleksander Zdyb + * \author Zofia Abramowska * \version 1.0 * \brief This file contains structs and consts for cynara admin. */ @@ -49,6 +50,18 @@ struct cynara_admin_policy { }; /** + * \name cynara_admin_policy_descr + * describes policy of type given with result + * result - result of policy to describe + * name - name of given policy result + */ + +struct cynara_admin_policy_descr { + int result; + char *name; +}; + +/** * \name Wildcard * definition of WILDCARD, that can replace client, user or privilege name. * WILDCARD matches any string during check procedure from libcynara-client. diff --git a/src/include/cynara-admin.h b/src/include/cynara-admin.h index bb1b8d1..0d958f8 100644 --- a/src/include/cynara-admin.h +++ b/src/include/cynara-admin.h @@ -16,6 +16,7 @@ /** * @file src/include/cynara-admin.h * \author Lukasz Wojciechowski + * \author Zofia Abramowska * \version 1.0 * \brief This file contains administration APIs of cynara available with libcynara-admin. */ @@ -358,6 +359,54 @@ int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char * 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); + +/** + * \par Description: + * + * Lists available cynara policy results with name description. + * + * \par Purpose: + * This API should be used to list all available policy results + * (also from cynara extension plugins). + * + * \par Typical use case: + * Gathering information about possible policy results and presenting them to user (using name + * attribute of description). Result can be passed to cynara_admin_set_policies(). + * + * \par Method of function operation: + * Policies are based on policy result number. Policies can be built in (like primitives: ALLOW, + * DENY...) or can be loaded from cynara plugin extensions. This API gives possibility of checking, + * which of these result exist in current cynara server and can be presented to user in a readable + * way (of course additional translation may be needed). + * + * Descriptions of existing policy results are returned as NULL terminated array of pointers of + * cynara_admin_policy_descr structures. + * + * Example output could be {{0, "Deny"}, {11, "AskUser"}, {65535, "Allow"}, NULL} + * + * In case of successful call CYNARA_API_SUCCESS is returned and *descriptions points + * to newly created array of pointers to struct cynara_admin_policy_descr. It is responsibility + * of caller to release: + * * all non-NULL char* pointers in all cynara_admin_policy_descr structures; + * * all pointers to cynara_admin_policy_descr structures kept in *descriptions array; + * * *descriptions array itself. + * All allocation made by cynara admin library are done with malloc(3) function and must be released + * with free(3) function. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \param[in] p_cynara_admin cynara admin structure. + * \param[out] descriptions placeholder for NULL terminated array of pointers of + * description structures. + * + * \return CYNARA_API_SUCCESS on success, or error code otherwise. + * + * \brief Lists available policies with their name description. + */ +int cynara_admin_list_policies_descriptions(struct cynara_admin *p_cynara_admin, + struct cynara_admin_policy_descr ***descriptions); + #ifdef __cplusplus } #endif -- 2.7.4