From 4c8af90c302f2f8ed13d542f3804e40cee90a800 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Fri, 12 Dec 2014 14:25:08 +0100 Subject: [PATCH 01/16] Support --bulk in --set-policy in Cyad Change-Id: I3c6792fc1f5da1d5ce8c7ca5cca2bc7380154902 --- src/cyad/CommandlineParser/CyadCommand.cpp | 4 +++ src/cyad/CommandlineParser/CyadCommand.h | 16 ++++++++++ src/cyad/CommandsDispatcher.cpp | 15 ++++++++++ src/cyad/CommandsDispatcher.h | 2 ++ test/cyad/commands_dispatcher.cpp | 48 ++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+) diff --git a/src/cyad/CommandlineParser/CyadCommand.cpp b/src/cyad/CommandlineParser/CyadCommand.cpp index 8ab6934..0e482fa 100644 --- a/src/cyad/CommandlineParser/CyadCommand.cpp +++ b/src/cyad/CommandlineParser/CyadCommand.cpp @@ -50,4 +50,8 @@ int SetPolicyCyadCommand::run(CommandsDispatcher &dispatcher) { return dispatcher.execute(*this); } +int SetPolicyBulkCyadCommand::run(CommandsDispatcher &dispatcher) { + return dispatcher.execute(*this); +} + } /* namespace Cynara */ diff --git a/src/cyad/CommandlineParser/CyadCommand.h b/src/cyad/CommandlineParser/CyadCommand.h index 2870582..fc2c808 100644 --- a/src/cyad/CommandlineParser/CyadCommand.h +++ b/src/cyad/CommandlineParser/CyadCommand.h @@ -137,6 +137,22 @@ private: PolicyKey m_policyKey; }; +class SetPolicyBulkCyadCommand : public CyadCommand { +public: + SetPolicyBulkCyadCommand(const std::string &filename) : m_filename(filename) {} + + virtual ~SetPolicyBulkCyadCommand() {} + + virtual int run(CommandsDispatcher &dispatcher); + + const std::string &filename(void) const { + return m_filename; + } + +private: + std::string m_filename; +}; + } /* namespace Cynara */ #endif /* SRC_CYAD_COMMANDLINEPARSER_CYADCOMMAND_H_ */ diff --git a/src/cyad/CommandsDispatcher.cpp b/src/cyad/CommandsDispatcher.cpp index 436e144..203aab2 100644 --- a/src/cyad/CommandsDispatcher.cpp +++ b/src/cyad/CommandsDispatcher.cpp @@ -23,8 +23,11 @@ #include #include +#include + #include #include +#include #include "CommandsDispatcher.h" @@ -83,4 +86,16 @@ int CommandsDispatcher::execute(SetPolicyCyadCommand &result) { return m_adminApiWrapper.cynara_admin_set_policies(m_cynaraAdmin, policies.data()); } +int CommandsDispatcher::execute(SetPolicyBulkCyadCommand &result) { + auto input = m_io.openFile(result.filename()); + + try { + auto policies = Cynara::AdminPolicyParser::parse(input); + return m_adminApiWrapper.cynara_admin_set_policies(m_cynaraAdmin, policies.data()); + } catch (const BucketRecordCorruptedException &ex) { + m_io.cerr() << ex.message(); + return CYNARA_API_INVALID_COMMANDLINE_PARAM; + } +} + } /* namespace Cynara */ diff --git a/src/cyad/CommandsDispatcher.h b/src/cyad/CommandsDispatcher.h index 63d2441..4193a95 100644 --- a/src/cyad/CommandsDispatcher.h +++ b/src/cyad/CommandsDispatcher.h @@ -43,6 +43,7 @@ public: virtual int execute(DeleteBucketCyadCommand &); virtual int execute(SetBucketCyadCommand &); virtual int execute(SetPolicyCyadCommand &); + virtual int execute(SetPolicyBulkCyadCommand &); private: // TODO: Get argv[0] instead of hardcoded name @@ -61,6 +62,7 @@ private: " -r, --privilege= privilege value\n" " -p, --policy= policy\n" " -m, --metadata= metadata for policy\n" + " -f, --bulk= path or - for stdin\n" "\n" "Help options:\n" " -h, --help print help message"; diff --git a/test/cyad/commands_dispatcher.cpp b/test/cyad/commands_dispatcher.cpp index d459dad..34ff9dc 100644 --- a/test/cyad/commands_dispatcher.cpp +++ b/test/cyad/commands_dispatcher.cpp @@ -20,6 +20,7 @@ * @brief Tests for CommandsDispatcher */ +#include #include #include @@ -181,3 +182,50 @@ TEST_F(CyadCommandlineDispatcherTest, setPolicyWithMetadata) { dispatcher.execute(result); } + +TEST_F(CyadCommandlineDispatcherTest, setPoliciesBulk) { + using ::testing::_; + using ::testing::Return; + + FakeAdminApiWrapper adminApi; + + EXPECT_CALL(adminApi, cynara_admin_initialize(_)).WillOnce(Return(CYNARA_API_SUCCESS)); + EXPECT_CALL(adminApi, cynara_admin_finish(_)).WillOnce(Return(CYNARA_API_SUCCESS)); + + Cynara::CommandsDispatcher dispatcher(m_io, adminApi); + Cynara::SetPolicyBulkCyadCommand result("-"); + + // fake stdin ;) + m_io.file() << "bucket;cli;usr;privilege;0;metadata" << std::endl; + m_io.file() << "bucket-2;cli;usr;privilege;0xFFFF"; + + Cynara::CynaraAdminPolicies expectedPolicies; + expectedPolicies.add("bucket", { CYNARA_ADMIN_DENY, "metadata" }, {"cli", "usr", "privilege"} ); + expectedPolicies.add("bucket-2", { CYNARA_ADMIN_ALLOW, "" }, {"cli", "usr", "privilege"} ); + expectedPolicies.seal(); + + EXPECT_CALL(adminApi, cynara_admin_set_policies(_, AdmPolicyListEq(expectedPolicies.data()))) + .WillOnce(Return(CYNARA_API_SUCCESS)); + + dispatcher.execute(result); +} + +TEST_F(CyadCommandlineDispatcherTest, setPoliciesBulkInputError) { + using ::testing::_; + using ::testing::Return; + + FakeAdminApiWrapper adminApi; + + EXPECT_CALL(adminApi, cynara_admin_initialize(_)).WillOnce(Return(CYNARA_API_SUCCESS)); + EXPECT_CALL(adminApi, cynara_admin_finish(_)).WillOnce(Return(CYNARA_API_SUCCESS)); + + Cynara::CommandsDispatcher dispatcher(m_io, adminApi); + Cynara::SetPolicyBulkCyadCommand result("-"); + + // fake stdin ;) + m_io.file() << "invalid input" << std::endl; + + dispatcher.execute(result); + + ASSERT_FALSE(m_io.cerrRaw().str().empty()); +} -- 2.7.4 From 3b6f95cd7abb9055555216aa30b0be6afee9af17 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Mon, 15 Dec 2014 10:26:12 +0100 Subject: [PATCH 02/16] Add CyadCommandlineParser Only --help option is currently supported. There is also errors handling implemented. Change-Id: I81b9aae457c49518e42582653b8c29a84b4870ac --- src/cyad/CMakeLists.txt | 1 + .../CommandlineParser/CyadCommandlineParser.cpp | 81 +++++++++++++++++++++ src/cyad/CommandlineParser/CyadCommandlineParser.h | 57 +++++++++++++++ test/CMakeLists.txt | 3 + test/cyad/CyadCommandlineTest.h | 84 ++++++++++++++++++++++ test/cyad/commandline.cpp | 40 +++++++++++ test/cyad/commandline_errors.cpp | 50 +++++++++++++ 7 files changed, 316 insertions(+) create mode 100644 src/cyad/CommandlineParser/CyadCommandlineParser.cpp create mode 100644 src/cyad/CommandlineParser/CyadCommandlineParser.h create mode 100644 test/cyad/CyadCommandlineTest.h create mode 100644 test/cyad/commandline.cpp create mode 100644 test/cyad/commandline_errors.cpp diff --git a/src/cyad/CMakeLists.txt b/src/cyad/CMakeLists.txt index 1ce4d1e..2a53be4 100644 --- a/src/cyad/CMakeLists.txt +++ b/src/cyad/CMakeLists.txt @@ -23,6 +23,7 @@ SET(CYAD_SOURCES ${CYAD_PATH}/AdminPolicyParser.cpp ${CYAD_PATH}/CynaraAdminPolicies.cpp ${CYAD_PATH}/CommandlineParser/CyadCommand.cpp + ${CYAD_PATH}/CommandlineParser/CyadCommandlineParser.cpp ${CYAD_PATH}/CommandsDispatcher.cpp ${CYAD_PATH}/DispatcherIO.cpp ${CYAD_PATH}/main.cpp diff --git a/src/cyad/CommandlineParser/CyadCommandlineParser.cpp b/src/cyad/CommandlineParser/CyadCommandlineParser.cpp new file mode 100644 index 0000000..845f1ef --- /dev/null +++ b/src/cyad/CommandlineParser/CyadCommandlineParser.cpp @@ -0,0 +1,81 @@ +/* + * 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/cyad/CommandlineParser/CyadCommandlineParser.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Commandline parser for Cyad + */ + +#include +#include +#include +#include + +#include "CyadCommandlineParser.h" + +namespace Cynara { + +namespace CyadCmdlineArgs { + const char HELP = 'h'; + const char * const HELP_LONG = "help"; +} + +namespace CyadCmdlineErrors { + const char * const UNKNOWN_ERROR = "Unknown error"; + const char * const NO_OPTION = "No option specified"; + const char * const UNKNOWN_OPTION = "Unknown option"; +} + +CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv) + : m_argc(argc), m_argv(argv) {} + +CyadCommandlineParser::~CyadCommandlineParser() {} + +std::shared_ptr CyadCommandlineParser::parseMain(void) { + namespace Args = CyadCmdlineArgs; + + const struct option long_options[] = { + { Args::HELP_LONG, no_argument, nullptr, Args::HELP }, + { nullptr, 0, nullptr, 0 } + }; + + optind = 0; // On entry to `getopt', zero means this is the first call; initialize. + int opt; + std::stringstream optstr; + optstr << ":" << Args::HELP; + + while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) { + switch (opt) { + case Args::HELP: + return std::make_shared(); + + case '?': // Unknown option + return std::make_shared(CyadCmdlineErrors::UNKNOWN_OPTION); + + case ':': // Missing argument + // Shall never happen, but let's just make compiler happy. + return std::make_shared(CyadCmdlineErrors::UNKNOWN_ERROR); + + default: + return std::make_shared(CyadCmdlineErrors::UNKNOWN_OPTION); + } + } + + return std::make_shared(CyadCmdlineErrors::NO_OPTION); +} + +} /* namespace Cynara */ diff --git a/src/cyad/CommandlineParser/CyadCommandlineParser.h b/src/cyad/CommandlineParser/CyadCommandlineParser.h new file mode 100644 index 0000000..7b30348 --- /dev/null +++ b/src/cyad/CommandlineParser/CyadCommandlineParser.h @@ -0,0 +1,57 @@ +/* + * 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/cyad/CommandlineParser/CyadCommandlineParser.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Commandline parser for Cyad + */ + +#ifndef SRC_CYAD_COMMANDLINEPARSER_CYADCOMMANDLINEPARSER_H_ +#define SRC_CYAD_COMMANDLINEPARSER_CYADCOMMANDLINEPARSER_H_ + +#include + +#include + +namespace Cynara { + +namespace CyadCmdlineArgs { + extern const char HELP; + extern const char * const HELP_LONG; +} + +namespace CyadCmdlineErrors { + extern const char * const UNKNOWN_ERROR; + extern const char * const NO_OPTION; + extern const char * const UNKNOWN_OPTION; +} + +class CyadCommandlineParser { +public: + CyadCommandlineParser(int argc, char * const *argv); + virtual ~CyadCommandlineParser(); + + std::shared_ptr parseMain(void); + +private: + int m_argc; + char * const *m_argv; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_COMMANDLINEPARSER_CYADCOMMANDLINEPARSER_H_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f99d555..5ab37d2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -50,6 +50,7 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/common/types/PolicyType.cpp ${CYNARA_SRC}/cyad/AdminPolicyParser.cpp ${CYNARA_SRC}/cyad/CommandlineParser/CyadCommand.cpp + ${CYNARA_SRC}/cyad/CommandlineParser/CyadCommandlineParser.cpp ${CYNARA_SRC}/cyad/CommandsDispatcher.cpp ${CYNARA_SRC}/cyad/CynaraAdminPolicies.cpp ${CYNARA_SRC}/helpers/creds-commons/CredsCommonsInner.cpp @@ -74,6 +75,8 @@ SET(CYNARA_TESTS_SOURCES common/protocols/admin/listresponse.cpp common/types/policybucket.cpp credsCommons/parser/Parser.cpp + cyad/commandline.cpp + cyad/commandline_errors.cpp cyad/commands_dispatcher.cpp cyad/helpers.cpp cyad/policy_collection.cpp diff --git a/test/cyad/CyadCommandlineTest.h b/test/cyad/CyadCommandlineTest.h new file mode 100644 index 0000000..d45fe3d --- /dev/null +++ b/test/cyad/CyadCommandlineTest.h @@ -0,0 +1,84 @@ +/* + * 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/cyad/CyadCommandlineTest.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Fixture for CyadCommandlineParser tests + */ + +#ifndef TEST_CYAD_CYADCOMMANDLINETEST_H_ +#define TEST_CYAD_CYADCOMMANDLINETEST_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +class CyadCommandlineTest : public ::testing::Test { +public: + typedef std::vector Args; + + void prepare_argv(const Args &args) { + destroy_argv(); + + m_argc = args.size(); + m_argv = new char *[m_argc]; + + for (auto i = 0; i < m_argc; ++i) { + m_argv[i] = strdup(args.at(i).c_str()); + if (m_argv[i] == nullptr) + throw std::bad_alloc(); + } + } + + int argc(void) const { + return m_argc; + } + + char * const *argv(void) const { + return m_argv; + } + +protected: + virtual void TearDown(void) { + destroy_argv(); + } + + void destroy_argv(void) { + for (auto i = 0; i < m_argc; ++i) { + free(m_argv[i]); + } + delete[] m_argv; + + m_argc = 0; + m_argv = nullptr; + } + +private: + int m_argc = 0; + char **m_argv = nullptr; +}; + +#endif /* TEST_CYAD_CYADCOMMANDLINETEST_H_ */ diff --git a/test/cyad/commandline.cpp b/test/cyad/commandline.cpp new file mode 100644 index 0000000..620cf28 --- /dev/null +++ b/test/cyad/commandline.cpp @@ -0,0 +1,40 @@ +/* + * 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/cyad/commandline.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Tests for CyadCommandlineParser + */ + +#include + +#include +#include + +#include +#include +#include + +#include "CyadCommandlineTest.h" + +TEST_F(CyadCommandlineTest, help) { + prepare_argv({ "./cyad", "--help" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); +} diff --git a/test/cyad/commandline_errors.cpp b/test/cyad/commandline_errors.cpp new file mode 100644 index 0000000..5326119 --- /dev/null +++ b/test/cyad/commandline_errors.cpp @@ -0,0 +1,50 @@ +/* + * 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/cyad/commandline.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Tests for CyadCommandlineParser (errors) + */ + +#include + +#include +#include + +#include +#include + +#include "CyadCommandlineTest.h" + +#define ASSERT_ERROR_MSG(msg,rawResult) { \ + auto result = std::dynamic_pointer_cast(rawResult); \ + ASSERT_NE(nullptr, result); \ + ASSERT_TRUE(result->isError()); \ + ASSERT_EQ(msg, result->message()); \ +} + +TEST_F(CyadCommandlineTest, noOption) { + prepare_argv({ "./cyad" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_OPTION, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, unknownOption) { + prepare_argv({ "./cyad", "--unknown-option" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION, parser.parseMain()); +} -- 2.7.4 From 83b327dd46b85cb2e4bcf4d1a8a4fc5040e9152d Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Mon, 15 Dec 2014 13:49:46 +0100 Subject: [PATCH 03/16] Implement --set-bucket and --delete-bucket in Cyad Change-Id: I61065bb8364d8cb33821c8a7be20a4b756522b43 --- .../CommandlineParser/CyadCommandlineParser.cpp | 133 +++++++++++++++++++-- src/cyad/CommandlineParser/CyadCommandlineParser.h | 22 ++++ .../CommandlineParser/PolicyParsingException.h | 46 +++++++ test/cyad/commandline.cpp | 67 +++++++++++ test/cyad/commandline_errors.cpp | 42 +++++++ 5 files changed, 299 insertions(+), 11 deletions(-) create mode 100644 src/cyad/CommandlineParser/PolicyParsingException.h diff --git a/src/cyad/CommandlineParser/CyadCommandlineParser.cpp b/src/cyad/CommandlineParser/CyadCommandlineParser.cpp index 845f1ef..713b506 100644 --- a/src/cyad/CommandlineParser/CyadCommandlineParser.cpp +++ b/src/cyad/CommandlineParser/CyadCommandlineParser.cpp @@ -24,6 +24,9 @@ #include #include #include +#include + +#include #include "CyadCommandlineParser.h" @@ -32,12 +35,29 @@ namespace Cynara { namespace CyadCmdlineArgs { const char HELP = 'h'; const char * const HELP_LONG = "help"; + + const char SET_BUCKET = 'b'; + const char * const SET_BUCKET_LONG = "set-bucket"; + + const char DELETE_BUCKET = 'd'; + const char * const DELETE_BUCKET_LONG = "delete-bucket"; + + const char POLICY = 'p'; + const char * const POLICY_LONG = "policy"; + + const char METADATA = 'm'; + const char * const METADATA_LONG = "metadata"; } namespace CyadCmdlineErrors { const char * const UNKNOWN_ERROR = "Unknown error"; const char * const NO_OPTION = "No option specified"; const char * const UNKNOWN_OPTION = "Unknown option"; + const char * const UNKNOWN_OPTION_SET_BUCKET = "Unknown option in --set-bucket"; + const char * const UNKNOWN_OPTION_DELETE_BUCKET = "Unknown option in --delete-bucket"; + const char * const NO_POLICY = "No --policy specified"; + const char * const NO_BUCKET = "No bucket specified"; + const char * const INVALID_POLICY = "Invalid --policy option"; } CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv) @@ -49,33 +69,124 @@ std::shared_ptr CyadCommandlineParser::parseMain(void) { namespace Args = CyadCmdlineArgs; const struct option long_options[] = { - { Args::HELP_LONG, no_argument, nullptr, Args::HELP }, + { Args::HELP_LONG, no_argument, nullptr, Args::HELP }, + { Args::SET_BUCKET_LONG, required_argument, nullptr, Args::SET_BUCKET }, + { Args::DELETE_BUCKET_LONG, required_argument, nullptr, Args::DELETE_BUCKET }, { nullptr, 0, nullptr, 0 } }; optind = 0; // On entry to `getopt', zero means this is the first call; initialize. int opt; std::stringstream optstr; - optstr << ":" << Args::HELP; + optstr << ":" << Args::HELP + << Args::SET_BUCKET << ":" + << Args::DELETE_BUCKET << ":"; while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) { switch (opt) { - case Args::HELP: - return std::make_shared(); + case Args::HELP: + return std::make_shared(); - case '?': // Unknown option - return std::make_shared(CyadCmdlineErrors::UNKNOWN_OPTION); + case Args::SET_BUCKET: + return parseSetBucket(optarg); - case ':': // Missing argument - // Shall never happen, but let's just make compiler happy. - return std::make_shared(CyadCmdlineErrors::UNKNOWN_ERROR); + case Args::DELETE_BUCKET: + return parseDeleteBucket(optarg); - default: - return std::make_shared(CyadCmdlineErrors::UNKNOWN_OPTION); + case '?': // Unknown option + return std::make_shared(CyadCmdlineErrors::UNKNOWN_OPTION); + + case ':': // Missing argument + switch (optopt) { + case Args::SET_BUCKET: + case Args::DELETE_BUCKET: + return std::make_shared(CyadCmdlineErrors::NO_BUCKET); + } + // Shall never happen, but let's just make compiler happy. + return std::make_shared(CyadCmdlineErrors::UNKNOWN_ERROR); + + default: + return std::make_shared(CyadCmdlineErrors::UNKNOWN_OPTION); } } return std::make_shared(CyadCmdlineErrors::NO_OPTION); } +std::shared_ptr CyadCommandlineParser::parseSetBucket(const std::string &bucketId) { + namespace Args = CyadCmdlineArgs; + namespace Errors = CyadCmdlineErrors; + + const struct option long_options[] = { + { Args::POLICY_LONG, required_argument, nullptr, Args::POLICY }, + { Args::METADATA_LONG, required_argument, nullptr, Args::METADATA }, + { nullptr, 0, nullptr, 0 } + }; + + std::string policy; + std::string metadata; + + int opt; + std::stringstream optstr; + optstr << ":" + << Args::POLICY << ":" + << Args::METADATA << ":"; + + while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) { + switch(opt) { + case Args::POLICY: + policy = optarg; + break; + case Args::METADATA: + metadata = optarg; + break; + default: + return std::make_shared(Errors::UNKNOWN_OPTION_SET_BUCKET); + } + } + + if (policy.empty()) + return std::make_shared(Errors::NO_POLICY); + + try { + auto policyType = parsePolicyType(policy); + return std::make_shared(bucketId, PolicyResult(policyType, metadata)); + } catch (const PolicyParsingException &) { + return std::make_shared(Errors::INVALID_POLICY); + } +} + +std::shared_ptr CyadCommandlineParser::parseDeleteBucket(const std::string &bucketId) { + namespace Errors = CyadCmdlineErrors; + + // Expect no additional options + const struct option long_options[] = { + { nullptr, 0, nullptr, 0 } + }; + + if (getopt_long(m_argc, m_argv, ":", long_options, nullptr) == -1) { + return std::make_shared(bucketId); + } else { + return std::make_shared(Errors::UNKNOWN_OPTION_DELETE_BUCKET); + } +} + +PolicyType CyadCommandlineParser::parsePolicyType(const std::string &rawPolicy) { + if (rawPolicy == "DENY") + return CYNARA_ADMIN_DENY; + if (rawPolicy == "NONE") + return CYNARA_ADMIN_NONE; + if (rawPolicy == "BUCKET") + return CYNARA_ADMIN_BUCKET; + if (rawPolicy == "ALLOW") + return CYNARA_ADMIN_ALLOW; + + // If base for std::stoi is set to 0, it detects base by itself from the format of the sequence + try { + return std::stoi(rawPolicy, nullptr, 0); + } catch (const std::logic_error &) { + throw PolicyParsingException(); + } +} + } /* namespace Cynara */ diff --git a/src/cyad/CommandlineParser/CyadCommandlineParser.h b/src/cyad/CommandlineParser/CyadCommandlineParser.h index 7b30348..4b629c4 100644 --- a/src/cyad/CommandlineParser/CyadCommandlineParser.h +++ b/src/cyad/CommandlineParser/CyadCommandlineParser.h @@ -32,12 +32,29 @@ namespace Cynara { namespace CyadCmdlineArgs { extern const char HELP; extern const char * const HELP_LONG; + + extern const char SET_BUCKET; + extern const char * const SET_BUCKET_LONG; + + extern const char DELETE_BUCKET; + extern const char * const DELETE_BUCKET_LONG; + + extern const char POLICY; + extern const char * const POLICY_LONG; + + extern const char METADATA; + extern const char * const METADATA_LONG; } namespace CyadCmdlineErrors { extern const char * const UNKNOWN_ERROR; extern const char * const NO_OPTION; extern const char * const UNKNOWN_OPTION; + extern const char * const UNKNOWN_OPTION_SET_BUCKET; + extern const char * const UNKNOWN_OPTION_DELETE_BUCKET; + extern const char * const NO_POLICY; + extern const char * const NO_BUCKET; + extern const char * const INVALID_POLICY; } class CyadCommandlineParser { @@ -46,6 +63,11 @@ public: virtual ~CyadCommandlineParser(); std::shared_ptr parseMain(void); + static PolicyType parsePolicyType(const std::string &rawPolicy); + +protected: + std::shared_ptr parseSetBucket(const std::string &bucketId); + std::shared_ptr parseDeleteBucket(const std::string &bucketId); private: int m_argc; diff --git a/src/cyad/CommandlineParser/PolicyParsingException.h b/src/cyad/CommandlineParser/PolicyParsingException.h new file mode 100644 index 0000000..958d44e --- /dev/null +++ b/src/cyad/CommandlineParser/PolicyParsingException.h @@ -0,0 +1,46 @@ +/* + * 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/cyad/CommandlineParser/PolicyParsingException.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief PolicyParsingException + */ + +#ifndef SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_ +#define SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_ + +#include + +namespace Cynara { + +class PolicyParsingException : public Exception { +public: + PolicyParsingException() { + m_message = "Invalid policy"; + } + + virtual const std::string &message(void) const { + return m_message; + } + +private: + std::string m_message; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_ */ diff --git a/test/cyad/commandline.cpp b/test/cyad/commandline.cpp index 620cf28..31b0771 100644 --- a/test/cyad/commandline.cpp +++ b/test/cyad/commandline.cpp @@ -38,3 +38,70 @@ TEST_F(CyadCommandlineTest, help) { auto result = std::dynamic_pointer_cast(parser.parseMain()); ASSERT_NE(nullptr, result); } + +TEST_F(CyadCommandlineTest, deleteBucket) { + prepare_argv({ "./cyad", "--delete-bucket=bucket" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("bucket", result->bucketId()); +} + +TEST_F(CyadCommandlineTest, setBucket) { + prepare_argv({ "./cyad", "--set-bucket=bucket", "--policy=42" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("bucket", result->bucketId()); + ASSERT_EQ(42, result->policyResult().policyType()); + ASSERT_TRUE(result->policyResult().metadata().empty()); +} + +TEST_F(CyadCommandlineTest, setBucketWithMetadata) { + const std::string ultimateAnswer = "Answer to The Ultimate Question of Life," + " the Universe, and Everything"; + + prepare_argv({ "./cyad", "--set-bucket=adams", "--policy=42", "--metadata=" + ultimateAnswer }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("adams", result->bucketId()); + ASSERT_EQ(42, result->policyResult().policyType()); + ASSERT_EQ(ultimateAnswer, result->policyResult().metadata()); +} + +TEST_F(CyadCommandlineTest, parsePolicyTypeBase10) { + auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType { + return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy); + }; + + ASSERT_EQ(CYNARA_ADMIN_DENY, parsePolicyType("0")); + ASSERT_EQ(CYNARA_ADMIN_NONE, parsePolicyType("1")); + ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("65534")); + ASSERT_EQ(CYNARA_ADMIN_ALLOW, parsePolicyType("65535")); +} + +TEST_F(CyadCommandlineTest, parsePolicyTypeBase16) { + auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType { + return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy); + }; + + ASSERT_EQ(CYNARA_ADMIN_DENY, parsePolicyType("0x0")); + ASSERT_EQ(CYNARA_ADMIN_NONE, parsePolicyType("0x1")); + ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("0xFFFE")); + ASSERT_EQ(CYNARA_ADMIN_ALLOW, parsePolicyType("0xFFFF")); +} + +TEST_F(CyadCommandlineTest, parsePolicyTypeHuman) { + auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType { + return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy); + }; + + ASSERT_EQ(CYNARA_ADMIN_DENY, parsePolicyType("DENY")); + ASSERT_EQ(CYNARA_ADMIN_NONE, parsePolicyType("NONE")); + ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("BUCKET")); + ASSERT_EQ(CYNARA_ADMIN_ALLOW, parsePolicyType("ALLOW")); +} diff --git a/test/cyad/commandline_errors.cpp b/test/cyad/commandline_errors.cpp index 5326119..5aa358f 100644 --- a/test/cyad/commandline_errors.cpp +++ b/test/cyad/commandline_errors.cpp @@ -48,3 +48,45 @@ TEST_F(CyadCommandlineTest, unknownOption) { Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION, parser.parseMain()); } + +TEST_F(CyadCommandlineTest, deleteBucketNoBucket) { + prepare_argv({ "./cyad", "--delete-bucket" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_BUCKET, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, deleteBucketUnknownOption) { + prepare_argv({ "./cyad", "--delete-bucket=bucket", "--unknown" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_DELETE_BUCKET, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setBucketNoBucket) { + prepare_argv({ "./cyad", "--set-bucket" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_BUCKET, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setBucketNoPolicy) { + prepare_argv({ "./cyad", "--set-bucket=bucket" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setBucketInvalidPolicy) { + prepare_argv({ "./cyad", "--set-bucket=bucket", "--policy=NaN" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::INVALID_POLICY, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setBucketUnknownOption) { + prepare_argv({ "./cyad", "--set-bucket=bucket", "--unknown", "--policy=42" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_SET_BUCKET, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setBucketMetadataNoPolicy) { + prepare_argv({ "./cyad", "--set-bucket=bucket", "--metadata=some-meta" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain()); +} -- 2.7.4 From ff191a303328c5211e9707e80f0d833d0791906f Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Mon, 15 Dec 2014 13:58:31 +0100 Subject: [PATCH 04/16] Implement --set-policy option in Cyad Policies can be added or altered one by one or in bulk mode. Option --bulk accepts file name as an argument. The "-" value means standard input. Change-Id: I479a29fd5ff43463f6f78d7865468bd84e1642ee --- .../CommandlineParser/CyadCommandlineParser.cpp | 107 ++++++++++++++++++++- src/cyad/CommandlineParser/CyadCommandlineParser.h | 19 ++++ src/cyad/CommandsDispatcher.h | 2 +- test/cyad/commandline.cpp | 76 +++++++++++++++ test/cyad/commandline_errors.cpp | 26 +++++ 5 files changed, 228 insertions(+), 2 deletions(-) diff --git a/src/cyad/CommandlineParser/CyadCommandlineParser.cpp b/src/cyad/CommandlineParser/CyadCommandlineParser.cpp index 713b506..c72967a 100644 --- a/src/cyad/CommandlineParser/CyadCommandlineParser.cpp +++ b/src/cyad/CommandlineParser/CyadCommandlineParser.cpp @@ -47,6 +47,24 @@ namespace CyadCmdlineArgs { const char METADATA = 'm'; const char * const METADATA_LONG = "metadata"; + + const char BUCKET = 'k'; + const char * const BUCKET_LONG = "bucket"; + + const char SET_POLICY = 's'; + const char * const SET_POLICY_LONG = "set-policy"; + + const char CLIENT = 'c'; + const char * const CLIENT_LONG = "client"; + + const char USER = 'u'; + const char * const USER_LONG = "user"; + + const char PRIVILEGE = 'r'; + const char * const PRIVILEGE_LONG = "privilege"; + + const char BULK = 'f'; + const char * const BULK_LONG = "bulk"; } namespace CyadCmdlineErrors { @@ -55,9 +73,12 @@ namespace CyadCmdlineErrors { const char * const UNKNOWN_OPTION = "Unknown option"; const char * const UNKNOWN_OPTION_SET_BUCKET = "Unknown option in --set-bucket"; const char * const UNKNOWN_OPTION_DELETE_BUCKET = "Unknown option in --delete-bucket"; + const char * const UNKNOWN_OPTION_SET_POLICY = "Unknown option in --set-policy"; const char * const NO_POLICY = "No --policy specified"; const char * const NO_BUCKET = "No bucket specified"; const char * const INVALID_POLICY = "Invalid --policy option"; + const char * const OPTION_MISSING_SET_POLICY = "One or more option missing in --set-policy"; + const char * const ARGUMENT_MISSING_SET_POLICY = "One or more argument missing in --set-policy"; } CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv) @@ -72,6 +93,7 @@ std::shared_ptr CyadCommandlineParser::parseMain(void) { { Args::HELP_LONG, no_argument, nullptr, Args::HELP }, { Args::SET_BUCKET_LONG, required_argument, nullptr, Args::SET_BUCKET }, { Args::DELETE_BUCKET_LONG, required_argument, nullptr, Args::DELETE_BUCKET }, + { Args::SET_POLICY_LONG, no_argument, nullptr, Args::SET_POLICY }, { nullptr, 0, nullptr, 0 } }; @@ -80,7 +102,8 @@ std::shared_ptr CyadCommandlineParser::parseMain(void) { std::stringstream optstr; optstr << ":" << Args::HELP << Args::SET_BUCKET << ":" - << Args::DELETE_BUCKET << ":"; + << Args::DELETE_BUCKET << ":" + << Args::SET_POLICY; while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) { switch (opt) { @@ -93,6 +116,9 @@ std::shared_ptr CyadCommandlineParser::parseMain(void) { case Args::DELETE_BUCKET: return parseDeleteBucket(optarg); + case Args::SET_POLICY: + return parseSetPolicy(); + case '?': // Unknown option return std::make_shared(CyadCmdlineErrors::UNKNOWN_OPTION); @@ -171,6 +197,85 @@ std::shared_ptr CyadCommandlineParser::parseDeleteBucket(const std: } } +std::shared_ptr CyadCommandlineParser::parseSetPolicy(void) { + namespace Args = CyadCmdlineArgs; + namespace Errors = CyadCmdlineErrors; + + const struct option long_options[] = { + { Args::CLIENT_LONG, required_argument, nullptr, Args::CLIENT }, + { Args::USER_LONG, required_argument, nullptr, Args::USER }, + { Args::PRIVILEGE_LONG, required_argument, nullptr, Args::PRIVILEGE }, + { Args::BUCKET_LONG, required_argument, nullptr, Args::BUCKET }, + { Args::POLICY_LONG, required_argument, nullptr, Args::POLICY }, + { Args::METADATA_LONG, required_argument, nullptr, Args::METADATA }, + { Args::BULK_LONG, required_argument, nullptr, Args::BULK }, + { nullptr, 0, nullptr, 0 } + }; + + typedef std::map OptionsValues; + OptionsValues values = { { Args::CLIENT, std::string() }, + { Args::USER, std::string() }, + { Args::PRIVILEGE, std::string() }, + { Args::POLICY, std::string() } }; + + std::string metadata; + std::string bucket; + + int opt; + std::stringstream optstr; + optstr << ":" + << Args::CLIENT << ":" + << Args::USER << ":" + << Args::PRIVILEGE << ":" + << Args::BUCKET << ":" + << Args::POLICY << ":" + << Args::METADATA << ":" + << Args::BULK << ":"; + + while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) { + switch(opt) { + case Args::CLIENT: + case Args::USER: + case Args::PRIVILEGE: + case Args::POLICY: + values[opt] = optarg; + break; + case Args::BUCKET: + bucket = optarg; + break; + case Args::METADATA: + metadata = optarg; + break; + case Args::BULK: + return std::make_shared(optarg); + case ':': // Missing argument + return std::make_shared(Errors::ARGUMENT_MISSING_SET_POLICY); + default: + return std::make_shared(Errors::UNKNOWN_OPTION_SET_POLICY); + } + } + + for (const auto &val : values) { + if (val.second.empty()) { + // TODO: Identify actual option + return std::make_shared(Errors::OPTION_MISSING_SET_POLICY); + } + } + + try { + auto policyType = parsePolicyType(values[Args::POLICY]); + auto policyResult = PolicyResult(policyType, metadata); + return std::make_shared(bucket, policyResult, + PolicyKey(values[Args::CLIENT], + values[Args::USER], + values[Args::PRIVILEGE])); + } catch (const PolicyParsingException &) { + return std::make_shared(Errors::INVALID_POLICY); + } + + return std::make_shared(Errors::UNKNOWN_ERROR); +} + PolicyType CyadCommandlineParser::parsePolicyType(const std::string &rawPolicy) { if (rawPolicy == "DENY") return CYNARA_ADMIN_DENY; diff --git a/src/cyad/CommandlineParser/CyadCommandlineParser.h b/src/cyad/CommandlineParser/CyadCommandlineParser.h index 4b629c4..891751e 100644 --- a/src/cyad/CommandlineParser/CyadCommandlineParser.h +++ b/src/cyad/CommandlineParser/CyadCommandlineParser.h @@ -44,6 +44,21 @@ namespace CyadCmdlineArgs { extern const char METADATA; extern const char * const METADATA_LONG; + + extern const char BUCKET; + extern const char * const BUCKET_LONG; + + extern const char CLIENT; + extern const char * const CLIENT_LONG; + + extern const char USER; + extern const char * const USER_LONG; + + extern const char PRIVILEGE; + extern const char * const PRIVILEGE_LONG; + + extern const char BULK; + extern const char * const BULK_LONG; } namespace CyadCmdlineErrors { @@ -52,9 +67,12 @@ namespace CyadCmdlineErrors { extern const char * const UNKNOWN_OPTION; extern const char * const UNKNOWN_OPTION_SET_BUCKET; extern const char * const UNKNOWN_OPTION_DELETE_BUCKET; + extern const char * const UNKNOWN_OPTION_SET_POLICY; extern const char * const NO_POLICY; extern const char * const NO_BUCKET; extern const char * const INVALID_POLICY; + extern const char * const OPTION_MISSING_SET_POLICY; + extern const char * const ARGUMENT_MISSING_SET_POLICY; } class CyadCommandlineParser { @@ -68,6 +86,7 @@ public: protected: std::shared_ptr parseSetBucket(const std::string &bucketId); std::shared_ptr parseDeleteBucket(const std::string &bucketId); + std::shared_ptr parseSetPolicy(void); private: int m_argc; diff --git a/src/cyad/CommandsDispatcher.h b/src/cyad/CommandsDispatcher.h index 4193a95..5193e1d 100644 --- a/src/cyad/CommandsDispatcher.h +++ b/src/cyad/CommandsDispatcher.h @@ -57,7 +57,7 @@ private: " -d, --delete-bucket= name of bucket to delete\n" "\n" "Policy set options (with -s or --set-policy)\n" - " -l, --client= client value\n" + " -c, --client= client value\n" " -u, --user= user value\n" " -r, --privilege= privilege value\n" " -p, --policy= policy\n" diff --git a/test/cyad/commandline.cpp b/test/cyad/commandline.cpp index 31b0771..60bb69a 100644 --- a/test/cyad/commandline.cpp +++ b/test/cyad/commandline.cpp @@ -73,6 +73,64 @@ TEST_F(CyadCommandlineTest, setBucketWithMetadata) { ASSERT_EQ(ultimateAnswer, result->policyResult().metadata()); } +TEST_F(CyadCommandlineTest, setPolicy) { + prepare_argv({ "./cyad", "--set-policy", "--bucket=some-bucket", + "--client=client", "--user=user", "--privilege=privilege", + "--policy=42" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("some-bucket", result->bucketId()); + + ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey()); + ASSERT_EQ(42, result->policyResult().policyType()); + ASSERT_TRUE(result->policyResult().metadata().empty()); +} + +TEST_F(CyadCommandlineTest, setPolicyWithMetadata) { + prepare_argv({ "./cyad", "--set-policy", "--bucket=some-bucket", + "--client=client", "--user=user", "--privilege=privilege", + "--policy=42", "--metadata=some-metadata" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("some-bucket", result->bucketId()); + + ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey()); + ASSERT_EQ(42, result->policyResult().policyType()); + ASSERT_EQ("some-metadata", result->policyResult().metadata()); +} + +TEST_F(CyadCommandlineTest, setPolicyInDefaultBucket) { + prepare_argv({ "./cyad", "--set-policy", "--bucket=", + "--client=client", "--user=user", "--privilege=privilege", + "--policy=ALLOW", "--metadata=some-metadata" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("", result->bucketId()); + ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey()); + ASSERT_EQ(CYNARA_ADMIN_ALLOW, result->policyResult().policyType()); + ASSERT_EQ("some-metadata", result->policyResult().metadata()); +} + +TEST_F(CyadCommandlineTest, setPolicyInDefaultBucketNoOption) { + prepare_argv({ "./cyad", "--set-policy", + "--client=client", "--user=user", "--privilege=privilege", + "--policy=ALLOW", "--metadata=some-metadata" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("", result->bucketId()); + ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey()); + ASSERT_EQ(CYNARA_ADMIN_ALLOW, result->policyResult().policyType()); + ASSERT_EQ("some-metadata", result->policyResult().metadata()); +} + TEST_F(CyadCommandlineTest, parsePolicyTypeBase10) { auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType { return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy); @@ -105,3 +163,21 @@ TEST_F(CyadCommandlineTest, parsePolicyTypeHuman) { ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("BUCKET")); ASSERT_EQ(CYNARA_ADMIN_ALLOW, parsePolicyType("ALLOW")); } + +TEST_F(CyadCommandlineTest, setPoliciesBulkFilename) { + prepare_argv({ "./cyad", "--set-policy", "--bulk=/tmp/input_file" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("/tmp/input_file", result->filename()); +} + +TEST_F(CyadCommandlineTest, setPoliciesBulkStdin) { + prepare_argv({ "./cyad", "--set-policy", "--bulk=-" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + + auto result = std::dynamic_pointer_cast(parser.parseMain()); + ASSERT_NE(nullptr, result); + ASSERT_EQ("-", result->filename()); +} diff --git a/test/cyad/commandline_errors.cpp b/test/cyad/commandline_errors.cpp index 5aa358f..fb2fa30 100644 --- a/test/cyad/commandline_errors.cpp +++ b/test/cyad/commandline_errors.cpp @@ -90,3 +90,29 @@ TEST_F(CyadCommandlineTest, setBucketMetadataNoPolicy) { Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain()); } + +TEST_F(CyadCommandlineTest, setPolicyNoOption) { + prepare_argv({ "./cyad", "--set-policy" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::OPTION_MISSING_SET_POLICY, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setPolicyUnknownOption) { + prepare_argv({ "./cyad", "--set-policy", "--unknown-option" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_SET_POLICY, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setPolicyArgumentMissing) { + prepare_argv({ "./cyad", "--set-policy", "--bucket" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::ARGUMENT_MISSING_SET_POLICY, parser.parseMain()); +} + +TEST_F(CyadCommandlineTest, setPolicyNoPolicy) { + // TODO: In the future, we can identify actual options being missed + prepare_argv({ "./cyad", "--set-policy", "--bucket=some-bucket", + "--client=client", "--user=user", "--privilege=privilege" }); + Cynara::CyadCommandlineParser parser(this->argc(), this->argv()); + ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::OPTION_MISSING_SET_POLICY, parser.parseMain()); +} -- 2.7.4 From b68bd97df691a9f556a80e2d350b5791f7b6f118 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Sat, 20 Dec 2014 13:42:34 +0100 Subject: [PATCH 05/16] Assemble all Cyad's components Change-Id: I1a711cad7d5aba0508ef41f308cddcc7a0704b28 --- src/cyad/CMakeLists.txt | 1 + src/cyad/Cyad.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cyad/Cyad.h | 53 +++++++++++++++++++++++++++++++++++++++++ src/cyad/main.cpp | 9 ++++--- 4 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 src/cyad/Cyad.cpp create mode 100644 src/cyad/Cyad.h diff --git a/src/cyad/CMakeLists.txt b/src/cyad/CMakeLists.txt index 2a53be4..99e371e 100644 --- a/src/cyad/CMakeLists.txt +++ b/src/cyad/CMakeLists.txt @@ -21,6 +21,7 @@ SET(CYAD_PATH ${CYNARA_PATH}/cyad) SET(CYAD_SOURCES ${CYAD_PATH}/AdminApiWrapper.cpp ${CYAD_PATH}/AdminPolicyParser.cpp + ${CYAD_PATH}/Cyad.cpp ${CYAD_PATH}/CynaraAdminPolicies.cpp ${CYAD_PATH}/CommandlineParser/CyadCommand.cpp ${CYAD_PATH}/CommandlineParser/CyadCommandlineParser.cpp diff --git a/src/cyad/Cyad.cpp b/src/cyad/Cyad.cpp new file mode 100644 index 0000000..092d9a7 --- /dev/null +++ b/src/cyad/Cyad.cpp @@ -0,0 +1,63 @@ +/* + * 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/cyad/Cyad.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief A command-line tool to manage Cynara's database + */ + +#include +#include + +#include + +#include + +#include "Cyad.h" + +namespace Cynara { + +Cyad::Cyad(int argc, char **argv) : m_parser(argc, argv), m_cynaraInitError(CYNARA_API_SUCCESS) { + try { + m_dispatcher.reset(new CommandsDispatcher(m_io, m_adminApiWrapper)); + } catch (const Cynara::AdminLibraryInitializationFailedException &ex) { + m_cynaraInitError = ex.errorCode(); + } +} + +Cyad::~Cyad() {} + +int Cyad::run(void) { + if (cynaraOperational() == false) { + m_io.cerr() << "Failed to initialize libcynara-admin: " << m_cynaraInitError << std::endl; + return m_cynaraInitError; + } + + try { + auto command = m_parser.parseMain(); + return command->run(*m_dispatcher); + } catch (const std::bad_alloc &) { + m_io.cerr() << "Cyad could not allocate memory" << std::endl; + return CYNARA_API_OUT_OF_MEMORY; + } +} + +bool Cyad::cynaraOperational(void) const { + return m_cynaraInitError == CYNARA_API_SUCCESS; +} + +} /* namespace Cynara */ diff --git a/src/cyad/Cyad.h b/src/cyad/Cyad.h new file mode 100644 index 0000000..ba98fd8 --- /dev/null +++ b/src/cyad/Cyad.h @@ -0,0 +1,53 @@ +/* + * 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/cyad/Cyad.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief A command-line tool to manage Cynara's database + */ + +#ifndef SRC_CYAD_CYAD_H_ +#define SRC_CYAD_CYAD_H_ + +#include + +#include +#include +#include +#include + +namespace Cynara { + +class Cyad { +public: + Cyad(int argc, char **argv); + ~Cyad(); + + int run(void); + bool cynaraOperational(void) const; + +private: + AdminApiWrapper m_adminApiWrapper; + DispatcherIO m_io; + std::unique_ptr m_dispatcher; + CyadCommandlineParser m_parser; + int m_cynaraInitError; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_CYAD_H_ */ diff --git a/src/cyad/main.cpp b/src/cyad/main.cpp index ab4a0a8..45aa48c 100644 --- a/src/cyad/main.cpp +++ b/src/cyad/main.cpp @@ -17,9 +17,12 @@ * @file src/cyad/main.cpp * @author Aleksander Zdyb * @version 1.0 - * @brief A commandline tool for managing Cynara's database + * @brief A command-line tool for managing Cynara's database */ -int main(int, char **) { - return 0; +#include + +int main(int argc, char **argv) { + Cynara::Cyad cyad(argc, argv); + return cyad.run(); } -- 2.7.4 From c12ada10f5b1e8c06f7f96e83054d1be5d9671ee Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Mon, 29 Dec 2014 20:25:53 +0100 Subject: [PATCH 06/16] Add missing include file in common install section types/PolicyDescription.h was missing in common/CMakeLists.txt install section. Change-Id: Ia7afde0ef8723d680d4aaa9ba9dee7f3533bf828 --- src/common/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index feb7e80..90f1b4b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -104,6 +104,7 @@ TARGET_LINK_LIBRARIES(${TARGET_CYNARA_COMMON} INSTALL(TARGETS ${TARGET_CYNARA_COMMON} DESTINATION ${LIB_INSTALL_DIR}) INSTALL(FILES ${COMMON_PATH}/types/ClientSession.h + ${COMMON_PATH}/types/PolicyDescription.h ${COMMON_PATH}/types/PolicyResult.h ${COMMON_PATH}/types/PolicyType.h DESTINATION ${INCLUDE_INSTALL_DIR}/cynara/types -- 2.7.4 From bc79171da4d2b7d36b5c643a111f8878750565ab Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Tue, 30 Dec 2014 12:04:39 +0100 Subject: [PATCH 07/16] Adjust logs to C++ string stream Now macros LOGx() accept: * sprintf style messages e.g. LOGE("Error: [%d]", 69); * C++ string stream e.g. LOGE("Error: [" << 69 << "]"); Change-Id: I9bbfd2dfd595c6f42f2bcba09f02d207da1c6062 --- src/common/log/log.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/common/log/log.h b/src/common/log/log.h index ccb0710..97ca1a3 100644 --- a/src/common/log/log.h +++ b/src/common/log/log.h @@ -26,22 +26,26 @@ #define CYNARA_COMMON_LOG_H #ifndef CYNARA_NO_LOGS +#include #include #endif extern int __log_level; #ifndef CYNARA_NO_LOGS - #define __LOG(LEVEL, ...) \ + #define __LOG(LEVEL, FORMAT, ...) \ do { \ - if(LEVEL <= __log_level) \ - sd_journal_print(LEVEL, __VA_ARGS__); \ + if(LEVEL <= __log_level) { \ + std::stringstream __LOG_MACRO_format; \ + __LOG_MACRO_format << FORMAT; \ + sd_journal_print(LEVEL, __LOG_MACRO_format.str().c_str(), ##__VA_ARGS__); \ + } \ } while (0) #else #define __LOG(LEVEL, ...) #endif -#define LEGM(...) __LOG(LOG_EMERG, __VA_ARGS__) /* system is unusable */ +#define LOGM(...) __LOG(LOG_EMERG, __VA_ARGS__) /* system is unusable */ #define LOGA(...) __LOG(LOG_ALERT, __VA_ARGS__) /* action must be taken immediately */ #define LOGC(...) __LOG(LOG_CRIT, __VA_ARGS__) /* critical conditions */ #define LOGE(...) __LOG(LOG_ERR, __VA_ARGS__) /* error conditions */ -- 2.7.4 From 4b2b3dd203631630b904527e29ff5c55c999cd0a Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Tue, 30 Dec 2014 12:21:00 +0100 Subject: [PATCH 08/16] Make logs available in devel package Header for logs is now installed for cynara related components that want to use cynara logs e.g. plugins. Change-Id: I174ce7ed4770cbf76511716e879885cffca32316 --- packaging/cynara.spec | 2 ++ src/common/CMakeLists.txt | 4 ++++ src/include/cynara-plugin.h | 1 + 3 files changed, 7 insertions(+) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index f62aed9..2d5a620 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -65,6 +65,7 @@ Requires: libcynara-creds-dbus = %{version}-%{release} Requires: libcynara-creds-socket = %{version}-%{release} Requires: libcynara-session = %{version}-%{release} Requires: pkgconfig(dbus-1) +Requires: pkgconfig(libsystemd-journal) Obsoletes: libcynara-admin-devel Obsoletes: libcynara-agent-devel Obsoletes: libcynara-client-async-devel @@ -307,6 +308,7 @@ fi %files -n cynara-devel %{_includedir}/cynara/*.h +%{_includedir}/cynara/log/*.h %{_includedir}/cynara/plugin/*.h %{_includedir}/cynara/types/*.h %{_libdir}/pkgconfig/*.pc diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 90f1b4b..f3670ad 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -103,6 +103,10 @@ TARGET_LINK_LIBRARIES(${TARGET_CYNARA_COMMON} INSTALL(TARGETS ${TARGET_CYNARA_COMMON} DESTINATION ${LIB_INSTALL_DIR}) INSTALL(FILES + ${COMMON_PATH}/log/log.h + DESTINATION ${INCLUDE_INSTALL_DIR}/cynara/log + ) +INSTALL(FILES ${COMMON_PATH}/types/ClientSession.h ${COMMON_PATH}/types/PolicyDescription.h ${COMMON_PATH}/types/PolicyResult.h diff --git a/src/include/cynara-plugin.h b/src/include/cynara-plugin.h index 20e5e5c..4318f23 100644 --- a/src/include/cynara-plugin.h +++ b/src/include/cynara-plugin.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include -- 2.7.4 From 36f3f22966978bc28bcf09bedd9fa68d612dcb3a Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 30 Dec 2014 13:27:55 +0100 Subject: [PATCH 09/16] Remove loading plugins from PluginManager constructor Loading plugins can be done also by offline API while executing listing of available policy descriptions. That is why loading plugins should be done only in case when database lock is aquired. PluginManager::loadPlugin() has been changed to public and is ran manually during cynara service startup. Change-Id: Ie5b9276049bda08fb14d2a7620613afe5e0942f4 --- src/common/plugin/PluginManager.cpp | 3 +-- src/common/plugin/PluginManager.h | 15 +++++++++------ src/service/main/Cynara.cpp | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/common/plugin/PluginManager.cpp b/src/common/plugin/PluginManager.cpp index 853b719..e843895 100644 --- a/src/common/plugin/PluginManager.cpp +++ b/src/common/plugin/PluginManager.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * @file src/service/plugin/PluginManager.cpp + * @file src/common/plugin/PluginManager.cpp * @author Zofia Abramowska * @version 1.0 * @brief Definition of PluginManager class @@ -50,7 +50,6 @@ namespace { namespace Cynara { PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) { - loadPlugins(); } PluginManager::~PluginManager(void) { diff --git a/src/common/plugin/PluginManager.h b/src/common/plugin/PluginManager.h index 87b0597..b17e75b 100644 --- a/src/common/plugin/PluginManager.h +++ b/src/common/plugin/PluginManager.h @@ -14,14 +14,14 @@ * limitations under the License. */ /** - * @file src/service/plugin/PluginManager.h + * @file src/common/plugin/PluginManager.h * @author Zofia Abramowska * @version 1.0 * @brief Declaration of PluginManager class */ -#ifndef SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ -#define SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ +#ifndef SRC_COMMON_PLUGIN_PLUGINMANAGER_H_ +#define SRC_COMMON_PLUGIN_PLUGINMANAGER_H_ #include #include @@ -39,10 +39,13 @@ typedef std::shared_ptr ExternalPluginPtr; class PluginManager { public: PluginManager(const std::string &pluginDir); + ~PluginManager(); + + void loadPlugins(void); + ExternalPluginPtr getPlugin(PolicyType pType); std::vector getPolicyDescriptions(void) const; void invalidateAll(void); - ~PluginManager(); private: typedef std::unique_ptr> PluginLibPtr; @@ -52,9 +55,9 @@ private: std::map m_plugins; PluginLibs m_pluginLibs; - void loadPlugins(void); void openPlugin(const std::string &path); }; } // namespace Cynara -#endif /* SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_ */ + +#endif /* SRC_COMMON_PLUGIN_PLUGINMANAGER_H_ */ diff --git a/src/service/main/Cynara.cpp b/src/service/main/Cynara.cpp index a6b96c6..15ebd99 100644 --- a/src/service/main/Cynara.cpp +++ b/src/service/main/Cynara.cpp @@ -66,6 +66,7 @@ void Cynara::init(void) { m_databaseLock.lock(); // Wait until database lock can be acquired m_storage->load(); + m_pluginManager->loadPlugins(); } void Cynara::run(void) { -- 2.7.4 From 02c31bea42d44fbfaa8e59ccfbc53ca5f96fa017 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 30 Dec 2014 14:11:16 +0100 Subject: [PATCH 10/16] Call acquireDatabase() in OfflineLogic API functions Call of OfflineLogic::acquireDatabase() has been moved from centralized point in Logic to every single call of OfflineLogic API functions, because some functions does not require database. So there is no need to load it. Now database is loaded only in case, when it is needed. Change-Id: I26131a257e85c79b97a96a748b4eb22ea96dd531 --- src/admin/logic/Logic.cpp | 1 - src/admin/logic/OfflineLogic.cpp | 6 ++++++ src/admin/logic/OfflineLogic.h | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 3f23370..ade44e6 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -88,7 +88,6 @@ int Logic::erasePolicies(const PolicyBucketId &startBucket, bool recursive, 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 { diff --git a/src/admin/logic/OfflineLogic.cpp b/src/admin/logic/OfflineLogic.cpp index c860ad8..64f6b5c 100644 --- a/src/admin/logic/OfflineLogic.cpp +++ b/src/admin/logic/OfflineLogic.cpp @@ -49,6 +49,7 @@ void OfflineLogic::acquireDatabase(void) { int OfflineLogic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, const ApiInterface::KeysByBucket &remove) { try { + acquireDatabase(); m_storage->insertPolicies(insertOrUpdate); m_storage->deletePolicies(remove); onPoliciesChanged(); @@ -64,6 +65,7 @@ int OfflineLogic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpda int OfflineLogic::insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult) { try { + acquireDatabase(); m_storage->addOrUpdateBucket(bucket, policyResult); onPoliciesChanged(); } catch (const DefaultBucketSetNoneException &) { @@ -79,6 +81,7 @@ int OfflineLogic::insertOrUpdateBucket(const PolicyBucketId &bucket, int OfflineLogic::removeBucket(const PolicyBucketId &bucket) { try { + acquireDatabase(); m_storage->deleteBucket(bucket); onPoliciesChanged(); } catch (const BucketNotExistsException &) { @@ -95,6 +98,7 @@ int OfflineLogic::removeBucket(const PolicyBucketId &bucket) { int OfflineLogic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, PolicyResult &result) { try { + acquireDatabase(); result = m_storage->checkPolicy(key, startBucket, recursive); } catch (const BucketNotExistsException &ex) { return CYNARA_API_BUCKET_NOT_FOUND; @@ -111,6 +115,7 @@ int OfflineLogic::listDescriptions(std::vector &descriptions) int OfflineLogic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, std::vector &policies) { try { + acquireDatabase(); policies = m_storage->listPolicies(bucket, filter); } catch (const BucketNotExistsException &ex) { return CYNARA_API_BUCKET_NOT_FOUND; @@ -122,6 +127,7 @@ int OfflineLogic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &fi int OfflineLogic::erasePolicies(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &filter) { try { + acquireDatabase(); m_storage->erasePolicies(startBucket, recursive, filter); onPoliciesChanged(); } catch (const BucketNotExistsException &) { diff --git a/src/admin/logic/OfflineLogic.h b/src/admin/logic/OfflineLogic.h index fc04d5e..2028f4e 100644 --- a/src/admin/logic/OfflineLogic.h +++ b/src/admin/logic/OfflineLogic.h @@ -38,8 +38,6 @@ class OfflineLogic : public ApiInterface { public: OfflineLogic(); - void acquireDatabase(void); - int setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, const ApiInterface::KeysByBucket &remove); int insertOrUpdateBucket(const PolicyBucketId &bucket, @@ -54,6 +52,7 @@ public: const PolicyKey &filter); protected: + void acquireDatabase(void); void onPoliciesChanged(void); private: -- 2.7.4 From 1756ee2eb523a977c3eeb9fa417a3fd34221bdc0 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 30 Dec 2014 18:41:12 +0100 Subject: [PATCH 11/16] Implement offline listing of policy descriptions PluginManager instance is created when list of policy descriptions is needed. Created object loads service plugins and creates required list. Change-Id: I9d7d5d31afb13f21c53545bd3ad8553c0a9a745b --- src/admin/logic/OfflineLogic.cpp | 9 ++++++++- src/admin/logic/OfflineLogic.h | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/admin/logic/OfflineLogic.cpp b/src/admin/logic/OfflineLogic.cpp index 64f6b5c..1e57aa4 100644 --- a/src/admin/logic/OfflineLogic.cpp +++ b/src/admin/logic/OfflineLogic.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,11 @@ void OfflineLogic::acquireDatabase(void) { m_storage->load(); } +void OfflineLogic::acquirePlugins(void) { + m_pluginManager.reset(new PluginManager(PathConfig::PluginPath::serviceDir)); + m_pluginManager->loadPlugins(); +} + int OfflineLogic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, const ApiInterface::KeysByBucket &remove) { try { @@ -108,7 +114,8 @@ int OfflineLogic::adminCheck(const PolicyBucketId &startBucket, bool recursive, } int OfflineLogic::listDescriptions(std::vector &descriptions) { - (void) descriptions; + acquirePlugins(); + descriptions = m_pluginManager->getPolicyDescriptions(); return CYNARA_API_SUCCESS; } diff --git a/src/admin/logic/OfflineLogic.h b/src/admin/logic/OfflineLogic.h index 2028f4e..da7b0aa 100644 --- a/src/admin/logic/OfflineLogic.h +++ b/src/admin/logic/OfflineLogic.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -53,14 +54,17 @@ public: protected: void acquireDatabase(void); + void acquirePlugins(void); void onPoliciesChanged(void); private: typedef std::unique_ptr StorageUniquePtr; typedef std::unique_ptr StorageBackendUniquePtr; + typedef std::unique_ptr PluginManagerUniquePtr; StorageUniquePtr m_storage; StorageBackendUniquePtr m_storageBackend; + PluginManagerUniquePtr m_pluginManager; }; } /* namespace Cynara */ -- 2.7.4 From acd1e531d78396ef02c5e8fc4aed03be77e2424f Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 30 Dec 2014 19:22:46 +0100 Subject: [PATCH 12/16] Remove never used offline-admin header Change-Id: I22f12755352d230a2ae5eacf8f8040b93a0e7ead --- src/include/cynara-offline-admin.h | 257 ------------------------------------- 1 file changed, 257 deletions(-) delete mode 100644 src/include/cynara-offline-admin.h diff --git a/src/include/cynara-offline-admin.h b/src/include/cynara-offline-admin.h deleted file mode 100644 index ce711f7..0000000 --- a/src/include/cynara-offline-admin.h +++ /dev/null @@ -1,257 +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/include/cynara-offline-admin.h - * \author Lukasz Wojciechowski - * \author Aleksander Zdyb - * \version 1.0 - * \brief This file contains administration APIs of cynara available - * with libcynara-offline-admin. - */ - -#ifndef CYNARA_OFFLINE_ADMIN_H -#define CYNARA_OFFLINE_ADMIN_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name cynara_offline_admin - * forward declaration of structure allowing initialization of library - * and usage of all libcynara-offline-admin API functions - */ -struct cynara_offline_admin; - -/** - * \par Description: - * Initialize cynara-offline-admin library. - * Creates structure used in following API calls. - * - * \par Purpose: - * This function must be invoked prior to other admin API calls. It creates structure needed by - * other cynara-offline-admin library API functions. - * - * \par Typical use case: - * Once before a service can call other cynara-offline-admin library functions. - * - * \par Method of function operation: - * This API initializes inner library structures and in case of success creates cynara_offline_admin - * structure and stores pointer to this structure at memory address passed - * in pp_cynara_offline_admin parameter. - * - * \par Sync (or) Async: - * This is a synchronous API. - * - * \par Important notes: - * Structure cynara_offline_admin created by cynara_offline_admin_initialize call should be released - * with cynara_offline_admin_finish. - * - * \param[out] pp_cynara_offline_admin address of pointer for created cynara_offline_admin - * structure. - * - * \return CYNARA_API_SUCCESS on success, or negative error code otherwise. - * - * \brief Initialize cynara-offline-admin library. - */ -int cynara_offline_admin_initialize(struct cynara_offline_admin **pp_cynara_offline_admin); - -/** - * \par Description: - * Releases cynara-offline-admin library and destroys structure created - * with cynara_offline_admin_initialize function. - * - * \par Purpose: - * This API should be used to clean up after usage of cynara-offline-admin library. - * - * \par Typical use case: - * Function should be called once, when done with cynara-offline-admin library API usage. - * - * \par Method of function operation: - * This API releases inner library structures and destroys cynara_offline_admin structure. - * - * \par Sync (or) Async: - * This is a synchronous API. - * - * \par Important notes: - * No invocations of cynara-offline-admin library API functions are allowed after call to - * cynara_offline_admin_finish. - * - * \param[in] p_cynara_offline_admin cynara_offline_admin structure created - * in cynara_offline_admin_initialize. - * - * \return CYNARA_API_SUCCESS on success, or negative error code otherwise. - * - * \brief Release cynara-offline-admin library. - */ -int cynara_offline_admin_finish(struct cynara_offline_admin *p_cynara_offline_admin); - -/** - * \par Description: - * Manages policies in cynara. - * - * \par Purpose: - * This API should be used to insert, update or delete policies in cynara. - * - * \par Typical use case: - * Enables altering policies by adding, updating or removing records. - * - * \par Method of function operation: - * Policies are arranged into buckets. Every policy is defined in context of some bucket identified - * with bucket field (string). A bucket consists of policies identified with tripple: (client, user, - * privilege), which is a (unique) key within considered bucket. - * - * Every policy can be one of two types: simple or bucket-pointing policy. - * Simple policies have result field with value of CYNARA_ADMIN_DENY or CYNARA_ADMIN_ALLOW. - * result_extra field should be NULL in this case. - * Bucket-pointing policies have result field with value of CYNARA_ADMIN_BUCKET and name of bucket - * they point to in result_extra field. - * - * Type of operation, which is run for every record (single policy) is defined by result field in - * cynara_admin_policy structure. - * In case of CYNARA_ADMIN_DENY or CYNARA_ADMIN_ALLOW a simple policy is updated or inserted into - * cynara database. - * In case of CYNARA_ADMIN_BUCKET, a bucket-pointing policy is updated or inserted into cynara - * database. - * In case of CYNARA_ADMIN_DELETE, a policy is removed from cynara database. - * One call of cynara_offline_admin_set_policies can manage many different policies - * in different buckets. - * - * However, considered buckets must exist before referring to them in policies. - * - * \par Sync (or) Async: - * This is a synchronous API. - * - * \par Important notes: - * When plugin API will be specified, there will be more valid types to pass as result. - * Numerical values of defines CYNARA_ADMIN_... may change, so usage of defines names is strongly - * recommended. - * - * \param[in] p_cynara_offline_admin cynara offline admin structure. - * \param[in] policies NULL terminated array of pointers to policy structures. - * - * \return CYNARA_API_SUCCESS on success, or negative error code otherwise. - * - * \brief Insert, update or delete policies in cynara database. - */ -int cynara_offline_admin_set_policies(struct cynara_offline_admin *p_cynara_offline_admin, - const struct cynara_admin_policy *const *policies); - -/** - * \par Description: - * Adds new, updates or removes existing bucket for policies in cynara. - * - * \par Purpose: - * This API should be used to add, remove or update buckets. - * - * \par Typical use case: - * Enables altering policies database by adding, updating or removing buckets. - * - * \par Method of function operation: - * Every bucket has a default policy. During search, if no policy matches the searched key (client, - * user, privilege), default policy is returned. - - * Operation run on a single bucket defined with bucket parameter. - - * Operation parameter defines what should happen with bucket. In case of: - * CYNARA_ADMIN_DENY, a bucket is inserted or updated with CYNARA_ADMIN_DENY default policy; - * CYNARA_ADMIN_ALLOW, a bucket is inserted or updated with CYNARA_ADMIN_ALLOW default policy; - * CYNARA_ADMIN_DELETE, a bucket is removed with all policies that were kept in it. - * - * \par Sync (or) Async: - * This is a synchronous API. - * - * \par Important notes: - * When plugin API will be specified, there will be more valid types to pass as operation / default - * policy. Numerical values of defines CYNARA_ADMIN_... may change, so usages of provided consts is - * strongly recommended. - * - * Default bucket identified with CYNARA_ADMIN_DEFAULT_BUCKET exists always. Its default policy - * is preset to DENY (can be altered, however). Default bucket cannot be removed. - * - * Extra parameter will be used to pass additional data to cynara extensions to build more complex - * policies, such as ALLOW but for 5 minutes only, or ALLOW if user confirms. - * - * \param[in] p_cynara_offline_admin cynara offline admin structure. - * \param[in] bucket bucket name - * \param[in] operation type of operation (default policy or CYNARA_ADMIN_DELETE) - * \param[in] extra additional data for default policy (will be available with cynara extensions) - * - * \return CYNARA_API_SUCCESS on success, or negative error code otherwise. - * - * \brief Add, remove or update buckets in cynara database. - */ -int cynara_offline_admin_set_bucket(struct cynara_offline_admin *p_cynara_offline_admin, - const char *bucket, int operation, const char *extra); - -/** - * \par Description: - * Raw check client, user access for given privilege without using plugins extensions. - * - * \par Purpose: - * This API should be used to check type of matching policy for check request. - * - * \par Typical use case: - * Administrator of cynara want to know, what would cynara return to client, if asked about given - * access. - * - * \par Method of function operation: - * Function works almost the same way as cynara_check() client function. - * The differences are: - * - user can specify bucket, from which search would be started (in case of cynara_check() - * it is always the default bucket) - * - user can specify if search should be recursive: disabling recursive check will constrain search - * to single bucket only, ignoring all policies leading to other buckets (in case of - * cynara_check() search is always recursive) - * - when matching policy in cynara is found, its result is returned without being interpreted by - * plugin extensions. - * - * \par Sync (or) Async: - * This is a synchronous API. - * - * \par Important notes: - * (*result_extra) may be set to NULL, if extra data are not used in matched policy - * If (*result_extra) is not NULL, it contains a string allocated by cynara offline admin library - * with malloc(3) function and must be released with free(3) function. - * - * \param[in] p_cynara_offline_admin cynara offline admin structure. - * \param[in] start_bucket name of bucket where search would start. - * \param[in] recursive FALSE (== 0) : search is not recursive (single bucket search); - * TRUE (!= 0) : search does not ignore policies leading to another buckets. - * \param[in] client application or process identifier. - * \param[in] user user running client. - * \param[in] privilege privilege that is a subject of a check. - * \param[out] result placeholder for matched policy type - * \param[out] result_extra placeholder for matched policy additional data (see Important Notes!) - * - * \return CYNARA_API_SUCCESS on success, or error code otherwise. - * - * \brief Raw check client, user access for given privilege without using plugins extensions. - */ -int cynara_offline_admin_check(struct cynara_offline_admin *p_cynara_offline_admin, - const char *start_bucket, const int recursive, - const char *client, const char *user, const char *privilege, - int *result, char **result_extra); - -#ifdef __cplusplus -} -#endif - -#endif /* CYNARA_OFFLINE_ADMIN_H */ -- 2.7.4 From 0674fa676d85b49170582cca37ccae35c749a147 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Wed, 31 Dec 2014 02:21:48 +0100 Subject: [PATCH 13/16] Bring back lost feature of loading client plugins Patch "Remove loading plugins from PluginManager constructor" removed loading plugins from PluginManager constructor. Loading plugins was manually added to cynara service start procedure. However PluginManager is used also in client libraries - that was forgotten and is fixed in this patch. Change-Id: I9bb93720fbfcf2275bff40699ea039c6ae1872dc --- src/client-common/cache/CapacityCache.cpp | 5 +++++ src/client-common/cache/CapacityCache.h | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/client-common/cache/CapacityCache.cpp b/src/client-common/cache/CapacityCache.cpp index 0a9a207..08d93ca 100644 --- a/src/client-common/cache/CapacityCache.cpp +++ b/src/client-common/cache/CapacityCache.cpp @@ -29,6 +29,11 @@ namespace Cynara { +CapacityCache::CapacityCache(std::size_t capacity) : m_capacity(capacity), + m_pluginManager(PathConfig::PluginPath::clientDir) { + m_pluginManager.loadPlugins(); +} + int CapacityCache::get(const ClientSession &session, const PolicyKey &key) { auto resultIt = m_keyValue.find(keyToString(key)); //Do we have entry in cache? diff --git a/src/client-common/cache/CapacityCache.h b/src/client-common/cache/CapacityCache.h index 59ff772..524e2ee 100644 --- a/src/client-common/cache/CapacityCache.h +++ b/src/client-common/cache/CapacityCache.h @@ -38,8 +38,7 @@ class CapacityCache : public PluginCache { public: static const std::size_t CACHE_DEFAULT_CAPACITY = 10000; - CapacityCache(std::size_t capacity = CACHE_DEFAULT_CAPACITY) : - m_capacity(capacity), m_pluginManager(PathConfig::PluginPath::clientDir) {} + CapacityCache(std::size_t capacity = CACHE_DEFAULT_CAPACITY); int get(const ClientSession &session, const PolicyKey &key); int update(const ClientSession& session, -- 2.7.4 From 5999e3ccaad8da0b7c70240714cbe168905f0437 Mon Sep 17 00:00:00 2001 From: Marcin Niesluchowski Date: Mon, 5 Jan 2015 12:22:21 +0100 Subject: [PATCH 14/16] Fix bug keeping write and read queue on disconnect Read and write binary queues are not cleared in asynchronous client after disconnect happens. Add clearing function in connect() and completeConnection() functions of SocketClientAsync class, when connection state changes. Change-Id: I18f5d13a1a21d0b99ebe456bfafd4487df9c1767 --- src/client-async/sockets/SocketClientAsync.cpp | 18 +++++++++++++++--- src/client-async/sockets/SocketClientAsync.h | 4 +++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/client-async/sockets/SocketClientAsync.cpp b/src/client-async/sockets/SocketClientAsync.cpp index 148b13a..7be87d1 100644 --- a/src/client-async/sockets/SocketClientAsync.cpp +++ b/src/client-async/sockets/SocketClientAsync.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -35,11 +35,17 @@ SocketClientAsync::SocketClientAsync(const std::string &socketPath, ProtocolPtr } Socket::ConnectionStatus SocketClientAsync::connect(void) { - return m_socket.connect(); + Socket::ConnectionStatus status = m_socket.connect(); + if (status != Socket::ConnectionStatus::ALREADY_CONNECTED) + clear(); + return status; } Socket::ConnectionStatus SocketClientAsync::completeConnection(void) { - return m_socket.completeConnection(); + Socket::ConnectionStatus status = m_socket.completeConnection(); + if (status == Socket::ConnectionStatus::CONNECTION_FAILED) + clear(); + return status; } int SocketClientAsync::getSockFd(void) { @@ -71,4 +77,10 @@ ResponsePtr SocketClientAsync::getResponse(void) { return m_protocol->extractResponseFromBuffer(m_readQueue); } +void SocketClientAsync::clear(void) +{ + m_readQueue->clear(); + m_writeQueue->clear(); +} + } // namespace Cynara diff --git a/src/client-async/sockets/SocketClientAsync.h b/src/client-async/sockets/SocketClientAsync.h index eaacf84..511221b 100644 --- a/src/client-async/sockets/SocketClientAsync.h +++ b/src/client-async/sockets/SocketClientAsync.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -58,6 +58,8 @@ private: ProtocolPtr m_protocol; BinaryQueuePtr m_readQueue; BinaryQueuePtr m_writeQueue; + + void clear(void); }; } // namespace Cynara -- 2.7.4 From 2dea730a1b51ef962e5a032049e6ae777d03162a Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 13 Jan 2015 18:05:20 +0100 Subject: [PATCH 15/16] Remove checking PolicyType in libcynara-admin Two libcynara-admin API functions: * cynara_admin_set_policies * cynara_admin_set_bucket have checked validity of PolicyType. Except for special values (like NONE, BUCKET, DELETE) they accepted only ALLOW and DENY policy types. No other policy types defined by plugins were able to be set. This patch removes described checks leaving only special values handling. All other types (including ALLOW and DENY) are passed to cynara service. The only check that is done verifies if given policy type can be casted into Cynara::PolicyType. Change-Id: Iedb0434bd35d4085e977fe86d07ed33a1f89cdc7 --- src/admin/api/admin-api.cpp | 58 ++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index a41171b..d15a736 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -85,6 +86,15 @@ int cynara_admin_finish(struct cynara_admin *p_cynara_admin) { return CYNARA_API_SUCCESS; } +bool int2PolicyType(int type, Cynara::PolicyType &policyType) { + if (type < std::numeric_limits::min()) + return false; + if (type > std::numeric_limits::max()) + return false; + policyType = static_cast(type); + return true; +} + CYNARA_API int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, const struct cynara_admin_policy *const *policies) { @@ -117,28 +127,26 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, return CYNARA_API_INVALID_PARAM; switch (policy->result) { + case CYNARA_ADMIN_NONE: + return CYNARA_API_INVALID_PARAM; case CYNARA_ADMIN_DELETE: remove[policy->bucket].push_back(key(policy)); break; - case CYNARA_ADMIN_DENY: - insertOrUpdate[policy->bucket].push_back(Cynara::Policy(key(policy), - Cynara::PredefinedPolicyType::DENY)); - break; - case CYNARA_ADMIN_ALLOW: - insertOrUpdate[policy->bucket].push_back(Cynara::Policy(key(policy), - Cynara::PredefinedPolicyType::ALLOW)); - break; case CYNARA_ADMIN_BUCKET: if (!policy->result_extra) return CYNARA_API_INVALID_PARAM; - insertOrUpdate[policy->bucket].push_back(Cynara::Policy(key(policy), - Cynara::PolicyResult( - Cynara::PredefinedPolicyType::BUCKET, - policy->result_extra))); - break; - case CYNARA_ADMIN_NONE: default: - return CYNARA_API_INVALID_PARAM; + { + std::string extraStr = policy->result_extra ? policy->result_extra : ""; + Cynara::PolicyType policyType; + if (!int2PolicyType(policy->result, policyType)) + return CYNARA_API_INVALID_PARAM; + + insertOrUpdate[policy->bucket].push_back(Cynara::Policy(key(policy), + Cynara::PolicyResult( + policyType, + extraStr))); + } } } @@ -155,17 +163,10 @@ int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *buc return CYNARA_API_INVALID_PARAM; return Cynara::tryCatch([&]() { - std::string extraStr = extra ? extra : ""; switch (operation) { case CYNARA_ADMIN_DELETE: return p_cynara_admin->impl->removeBucket(bucket); - case CYNARA_ADMIN_DENY: - return p_cynara_admin->impl->insertOrUpdateBucket(bucket, - Cynara::PolicyResult(Cynara::PredefinedPolicyType::DENY, extraStr)); - case CYNARA_ADMIN_ALLOW: - return p_cynara_admin->impl->insertOrUpdateBucket(bucket, - Cynara::PolicyResult(Cynara::PredefinedPolicyType::ALLOW, extraStr)); case CYNARA_ADMIN_NONE: if (bucket != Cynara::defaultPolicyBucketId) { return p_cynara_admin->impl->insertOrUpdateBucket(bucket, @@ -173,8 +174,17 @@ int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *buc } return CYNARA_API_OPERATION_NOT_ALLOWED; case CYNARA_ADMIN_BUCKET: - default: return CYNARA_API_INVALID_PARAM; + default: + { + std::string extraStr = extra ? extra : ""; + Cynara::PolicyType policyType; + if (!int2PolicyType(operation, policyType)) + return CYNARA_API_INVALID_PARAM; + + return p_cynara_admin->impl->insertOrUpdateBucket(bucket, + Cynara::PolicyResult(policyType, extraStr)); + } } }); } -- 2.7.4 From e4876487e05d76dd9dfbedd8016936ed112a6b18 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 13 Jan 2015 20:38:08 +0100 Subject: [PATCH 16/16] Verify PolicyType on service and offline client side Verification of PolicyTypes was removed from libcynara-admin library. Now it is added to Cynara service and cynara offline admin with full plugin support. It means, that validation passes only for predefined types or types provided by loaded cynara service plugins. In case, the validation fails, new CodeResponse::Code::NO_POLICY_TYPE value is returned from service to libcynara admin side and CYNARA_API_INVALID_PARAM is returned from cynara_admin_set_policies() or cynara_admin_set_bucket() functions. Change-Id: Id1a85aafaa4feb31d8513e819c78736813a9ff38 --- src/admin/logic/OfflineLogic.cpp | 34 ++++++++++++- src/admin/logic/OfflineLogic.h | 7 ++- src/admin/logic/OnlineLogic.cpp | 5 +- src/common/exceptions/UnknownPolicyTypeException.h | 56 ++++++++++++++++++++++ src/common/plugin/PluginManager.cpp | 10 +++- src/common/plugin/PluginManager.h | 6 ++- src/common/response/CodeResponse.h | 3 +- src/service/logic/Logic.cpp | 30 +++++++++++- src/service/logic/Logic.h | 11 ++++- 9 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 src/common/exceptions/UnknownPolicyTypeException.h diff --git a/src/admin/logic/OfflineLogic.cpp b/src/admin/logic/OfflineLogic.cpp index 1e57aa4..f421f2a 100644 --- a/src/admin/logic/OfflineLogic.cpp +++ b/src/admin/logic/OfflineLogic.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -16,6 +16,7 @@ /** * @file src/admin/logic/OfflineLogic.cpp * @author Aleksander Zdyb + * @author Lukasz Wojciechowski * @version 1.0 * @brief This file contains implementation of OfflineLogic class */ @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -52,10 +54,34 @@ void OfflineLogic::acquirePlugins(void) { m_pluginManager->loadPlugins(); } +void OfflineLogic::checkPoliciesTypes(const ApiInterface::PoliciesByBucket &policies, + bool allowBucket, bool allowNone) { + for (const auto &group : policies) { + for (const auto &policy : group.second) { + checkSinglePolicyType(policy.result().policyType(), allowBucket, allowNone); + } + } +} + +void OfflineLogic::checkSinglePolicyType(const PolicyType &policyType, bool allowBucket, + bool allowNone) { + if (allowBucket && policyType == PredefinedPolicyType::BUCKET) + return; + if (allowNone && policyType == PredefinedPolicyType::NONE) + return; + for (const auto &descr : predefinedPolicyDescr) { + if (descr.type == policyType) + return; + } + m_pluginManager->checkPolicyType(policyType); +} + int OfflineLogic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, const ApiInterface::KeysByBucket &remove) { try { acquireDatabase(); + acquirePlugins(); + checkPoliciesTypes(insertOrUpdate, true, false); m_storage->insertPolicies(insertOrUpdate); m_storage->deletePolicies(remove); onPoliciesChanged(); @@ -63,6 +89,8 @@ int OfflineLogic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpda return CYNARA_API_BUCKET_NOT_FOUND; } catch (const DatabaseException &) { return CYNARA_API_OPERATION_FAILED; + } catch (const UnknownPolicyTypeException &ex) { + return CYNARA_API_INVALID_PARAM; } return CYNARA_API_SUCCESS; @@ -72,6 +100,8 @@ int OfflineLogic::insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult) { try { acquireDatabase(); + acquirePlugins(); + checkSinglePolicyType(policyResult.policyType(), true, true); m_storage->addOrUpdateBucket(bucket, policyResult); onPoliciesChanged(); } catch (const DefaultBucketSetNoneException &) { @@ -80,6 +110,8 @@ int OfflineLogic::insertOrUpdateBucket(const PolicyBucketId &bucket, return CYNARA_API_OPERATION_NOT_ALLOWED; } catch (const DatabaseException &) { return CYNARA_API_OPERATION_FAILED; + } catch (const UnknownPolicyTypeException &ex) { + return CYNARA_API_INVALID_PARAM; } return CYNARA_API_SUCCESS; diff --git a/src/admin/logic/OfflineLogic.h b/src/admin/logic/OfflineLogic.h index da7b0aa..6dc2a7e 100644 --- a/src/admin/logic/OfflineLogic.h +++ b/src/admin/logic/OfflineLogic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -16,6 +16,7 @@ /** * @file src/admin/logic/OfflineLogic.h * @author Aleksander Zdyb + * @author Lukasz Wojciechowski * @version 1.0 * @brief This file contains definition of OfflineLogic class */ @@ -27,6 +28,7 @@ #include #include +#include #include #include @@ -56,6 +58,9 @@ protected: void acquireDatabase(void); void acquirePlugins(void); void onPoliciesChanged(void); + void checkPoliciesTypes(const ApiInterface::PoliciesByBucket &policies, bool allowBucket, + bool allowNone); + void checkSinglePolicyType(const PolicyType &policyType, bool allowBucket, bool allowNone); private: typedef std::unique_ptr StorageUniquePtr; diff --git a/src/admin/logic/OnlineLogic.cpp b/src/admin/logic/OnlineLogic.cpp index b9be92d..9671111 100644 --- a/src/admin/logic/OnlineLogic.cpp +++ b/src/admin/logic/OnlineLogic.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -104,6 +104,9 @@ static int interpretCodeResponse(const CodeResponse::Code &code) { case CodeResponse::Code::NO_BUCKET: LOGE("Trying to use unexisting bucket."); return CYNARA_API_BUCKET_NOT_FOUND; + case CodeResponse::Code::NO_POLICY_TYPE: + LOGE("Trying to use unknown policy type."); + return CYNARA_API_INVALID_PARAM; case CodeResponse::Code::FAILED: LOGC("Cynara service answered: Operation failed."); return CYNARA_API_OPERATION_FAILED; diff --git a/src/common/exceptions/UnknownPolicyTypeException.h b/src/common/exceptions/UnknownPolicyTypeException.h new file mode 100644 index 0000000..5ca1037 --- /dev/null +++ b/src/common/exceptions/UnknownPolicyTypeException.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 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/exceptions/UnknownPolicyTypeException.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Implementation of UnknownPolicyTypeException + */ + +#ifndef SRC_COMMON_EXCEPTIONS_UNKNOWNPOLICYTYPEEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_UNKNOWNPOLICYTYPEEXCEPTION_H_ + +#include + +#include "Exception.h" +#include "types/PolicyType.h" + +namespace Cynara { + +class UnknownPolicyTypeException : public Exception { +public: + UnknownPolicyTypeException() = delete; + UnknownPolicyTypeException(const PolicyType &policyType) + : m_policyType(policyType), m_message("UnknownPolicyTypeException") { + } + virtual ~UnknownPolicyTypeException() {}; + + virtual const std::string &message(void) const { + return m_message; + } + + const PolicyType &policyType(void) const { + return m_policyType; + } + +private: + PolicyType m_policyType; + std::string m_message; +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_EXCEPTIONS_UNKNOWNPOLICYTYPEEXCEPTION_H_ */ diff --git a/src/common/plugin/PluginManager.cpp b/src/common/plugin/PluginManager.cpp index e843895..38a83ff 100644 --- a/src/common/plugin/PluginManager.cpp +++ b/src/common/plugin/PluginManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -16,6 +16,7 @@ /** * @file src/common/plugin/PluginManager.cpp * @author Zofia Abramowska + * @author Lukasz Wojciechowski * @version 1.0 * @brief Definition of PluginManager class */ @@ -28,6 +29,7 @@ #include #include +#include #include #include "PluginManager.h" @@ -79,6 +81,12 @@ void PluginManager::invalidateAll(void) { } } +void PluginManager::checkPolicyType(PolicyType pType) const { + const auto it = m_plugins.find(pType); + if (it == m_plugins.end() || it->second == nullptr) + throw UnknownPolicyTypeException(pType); +} + void PluginManager::loadPlugins(void) { struct dirent **nameList = NULL; int fileAmount = scandir(m_dir.c_str(), &nameList, pluginFilter, alphasort); diff --git a/src/common/plugin/PluginManager.h b/src/common/plugin/PluginManager.h index b17e75b..ecd1e6c 100644 --- a/src/common/plugin/PluginManager.h +++ b/src/common/plugin/PluginManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -16,6 +16,7 @@ /** * @file src/common/plugin/PluginManager.h * @author Zofia Abramowska + * @author Lukasz Wojciechowski * @version 1.0 * @brief Declaration of PluginManager class */ @@ -32,6 +33,7 @@ #include #include +#include namespace Cynara { typedef std::shared_ptr ExternalPluginPtr; @@ -47,6 +49,8 @@ public: std::vector getPolicyDescriptions(void) const; void invalidateAll(void); + void checkPolicyType(PolicyType pType) const; + private: typedef std::unique_ptr> PluginLibPtr; typedef std::list PluginLibs; diff --git a/src/common/response/CodeResponse.h b/src/common/response/CodeResponse.h index 7a6020f..f5790f4 100644 --- a/src/common/response/CodeResponse.h +++ b/src/common/response/CodeResponse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -34,6 +34,7 @@ public: enum Code { OK, NO_BUCKET, + NO_POLICY_TYPE, NOT_ALLOWED, FAILED }; diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index c6a045f..5e3f82a 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -301,6 +302,7 @@ void Logic::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr re auto code = CodeResponse::Code::OK; try { + checkSinglePolicyType(request->result().policyType(), true, true); m_storage->addOrUpdateBucket(request->bucketId(), request->result()); onPoliciesChanged(); } catch (const DatabaseException &ex) { @@ -309,6 +311,8 @@ void Logic::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr re code = CodeResponse::Code::NOT_ALLOWED; } catch (const InvalidBucketIdException &ex) { code = CodeResponse::Code::NOT_ALLOWED; + } catch (const UnknownPolicyTypeException &ex) { + code = CodeResponse::Code::NO_POLICY_TYPE; } context->returnResponse(context, std::make_shared(code, @@ -348,6 +352,7 @@ void Logic::execute(RequestContextPtr context, RemoveBucketRequestPtr request) { void Logic::execute(RequestContextPtr context, SetPoliciesRequestPtr request) { auto code = CodeResponse::Code::OK; try { + checkPoliciesTypes(request->policiesToBeInsertedOrUpdated(), true, false); m_storage->insertPolicies(request->policiesToBeInsertedOrUpdated()); m_storage->deletePolicies(request->policiesToBeRemoved()); onPoliciesChanged(); @@ -355,11 +360,34 @@ void Logic::execute(RequestContextPtr context, SetPoliciesRequestPtr request) { code = CodeResponse::Code::FAILED; } catch (const BucketNotExistsException &ex) { code = CodeResponse::Code::NO_BUCKET; + } catch (const UnknownPolicyTypeException &ex) { + code = CodeResponse::Code::NO_POLICY_TYPE; } context->returnResponse(context, std::make_shared(code, request->sequenceNumber())); } +void Logic::checkPoliciesTypes(const std::map> &policies, + bool allowBucket, bool allowNone) { + for (const auto &group : policies) { + for (const auto &policy : group.second) { + checkSinglePolicyType(policy.result().policyType(), allowBucket, allowNone); + } + } +} + +void Logic::checkSinglePolicyType(const PolicyType &policyType, bool allowBucket, bool allowNone) { + if (allowBucket && policyType == PredefinedPolicyType::BUCKET) + return; + if (allowNone && policyType == PredefinedPolicyType::NONE) + return; + for (const auto &descr : predefinedPolicyDescr) { + if (descr.type == policyType) + return; + } + m_pluginManager->checkPolicyType(policyType); +} + void Logic::contextClosed(RequestContextPtr context) { LOGD("context closed"); diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index a0ea510..fc577bd 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2015 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. @@ -23,8 +23,14 @@ #ifndef SRC_SERVICE_LOGIC_LOGIC_H_ #define SRC_SERVICE_LOGIC_LOGIC_H_ +#include +#include + +#include +#include #include #include +#include #include
#include @@ -94,6 +100,9 @@ private: const PluginData &agentData, const RequestContextPtr &request, const ServicePluginInterfacePtr &plugin); + void checkPoliciesTypes(const std::map> &policies, + bool allowBucket, bool allowNone); + void checkSinglePolicyType(const PolicyType &policyType, bool allowBucket, bool allowNone); void handleAgentTalkerDisconnection(const AgentTalkerPtr &agentTalkerPtr); void handleClientDisconnection(const CheckContextPtr &checkContextPtr); -- 2.7.4