From 4f39cf7bf1c01a29aba8d77c25696bced57004ae Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 9 Dec 2014 12:37:44 +0100 Subject: [PATCH 01/16] Introduce AdminApiWrapper BaseAdminApiWrapper provides interface for wrapping functions of cynara-admin API. The wrapping is needed mainly for testing purposes. AdminApiWrapper is a target implementation, while FakeAdminApiWrapper is a mock for testing. Change-Id: I0b4afb89d8b4bec62693cf070f2a5a90f1148b79 --- src/cyad/AdminApiWrapper.cpp | 59 +++++++++++++++++++++++++++++++++++++++++ src/cyad/AdminApiWrapper.h | 52 ++++++++++++++++++++++++++++++++++++ src/cyad/BaseAdminApiWrapper.h | 48 +++++++++++++++++++++++++++++++++ src/cyad/CMakeLists.txt | 1 + test/cyad/FakeAdminApiWrapper.h | 47 ++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+) create mode 100644 src/cyad/AdminApiWrapper.cpp create mode 100644 src/cyad/AdminApiWrapper.h create mode 100644 src/cyad/BaseAdminApiWrapper.h create mode 100644 test/cyad/FakeAdminApiWrapper.h diff --git a/src/cyad/AdminApiWrapper.cpp b/src/cyad/AdminApiWrapper.cpp new file mode 100644 index 0000000..6a31b4b --- /dev/null +++ b/src/cyad/AdminApiWrapper.cpp @@ -0,0 +1,59 @@ +/* + * 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/AdminApiWrapper.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Wrapper around cynara-admin API + */ + +#include + +#include "AdminApiWrapper.h" + +namespace Cynara { + +AdminApiWrapper::AdminApiWrapper() {} + +AdminApiWrapper::~AdminApiWrapper() {} + +int AdminApiWrapper::cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) { + return ::cynara_admin_initialize(pp_cynara_admin); +} + +int AdminApiWrapper::cynara_admin_finish(struct cynara_admin *p_cynara_admin) { + return ::cynara_admin_finish(p_cynara_admin); +} + +int AdminApiWrapper::cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, + const struct cynara_admin_policy *const *policies) { + return ::cynara_admin_set_policies(p_cynara_admin, policies); +} + +int AdminApiWrapper::cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, + const char *bucket, int operation, const char *extra) { + return ::cynara_admin_set_bucket(p_cynara_admin, bucket, operation, extra); +} + +int AdminApiWrapper::cynara_admin_check(struct cynara_admin *p_cynara_admin, + const char *start_bucket, const int recursive, + const char *client, const char *user, const char *privilege, + int *result, char **result_extra) { + return ::cynara_admin_check(p_cynara_admin, start_bucket, recursive, client, user, privilege, + result, result_extra); +} + +} /* namespace Cynara */ diff --git a/src/cyad/AdminApiWrapper.h b/src/cyad/AdminApiWrapper.h new file mode 100644 index 0000000..d688271 --- /dev/null +++ b/src/cyad/AdminApiWrapper.h @@ -0,0 +1,52 @@ +/* + * 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/AdminApiWrapper.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Wrapper around cynara-admin API + */ + +#ifndef SRC_CYAD_ADMINAPIWRAPPER_H_ +#define SRC_CYAD_ADMINAPIWRAPPER_H_ + +#include "BaseAdminApiWrapper.h" + +struct cynara_admin; +struct cynara_admin_policy; + +namespace Cynara { + +class AdminApiWrapper : public BaseAdminApiWrapper { +public: + AdminApiWrapper(); + virtual ~AdminApiWrapper(); + + virtual int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin); + virtual int cynara_admin_finish(struct cynara_admin *p_cynara_admin); + virtual int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, + const struct cynara_admin_policy *const *policies); + virtual int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *bucket, + int operation, const char *extra); + virtual int cynara_admin_check(struct cynara_admin *p_cynara_admin, + const char *start_bucket, const int recursive, + const char *client, const char *user, const char *privilege, + int *result, char **result_extra); +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_ADMINAPIWRAPPER_H_ */ diff --git a/src/cyad/BaseAdminApiWrapper.h b/src/cyad/BaseAdminApiWrapper.h new file mode 100644 index 0000000..a24aec2 --- /dev/null +++ b/src/cyad/BaseAdminApiWrapper.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file src/cyad/BaseAdminApiWrapper.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Wrapper around cynara-admin API (base) + */ + +#ifndef SRC_CYAD_BASEADMINAPIWRAPPER_H_ +#define SRC_CYAD_BASEADMINAPIWRAPPER_H_ + +struct cynara_admin; +struct cynara_admin_policy; + +namespace Cynara { + +class BaseAdminApiWrapper { +public: + virtual ~BaseAdminApiWrapper() {}; + virtual int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) = 0; + virtual int cynara_admin_finish(struct cynara_admin *p_cynara_admin) = 0; + virtual int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, + const struct cynara_admin_policy *const *policies) = 0; + virtual int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *bucket, + int operation, const char *extra) = 0; + virtual int cynara_admin_check(struct cynara_admin *p_cynara_admin, + const char *start_bucket, const int recursive, + const char *client, const char *user, const char *privilege, + int *result, char **result_extra) = 0; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_BASEADMINAPIWRAPPER_H_ */ diff --git a/src/cyad/CMakeLists.txt b/src/cyad/CMakeLists.txt index 1e379da..1000a0a 100644 --- a/src/cyad/CMakeLists.txt +++ b/src/cyad/CMakeLists.txt @@ -19,6 +19,7 @@ SET(CYAD_PATH ${CYNARA_PATH}/cyad) SET(CYAD_SOURCES + ${CYAD_PATH}/AdminApiWrapper.cpp ${CYAD_PATH}/main.cpp ) diff --git a/test/cyad/FakeAdminApiWrapper.h b/test/cyad/FakeAdminApiWrapper.h new file mode 100644 index 0000000..8e9b86b --- /dev/null +++ b/test/cyad/FakeAdminApiWrapper.h @@ -0,0 +1,47 @@ +/* + * 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/FakeAdminApiWrapper.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Wrapper around cynara-admin API (mock) + */ + +#ifndef TEST_CYAD_FAKEADMINAPIWRAPPER_H_ +#define TEST_CYAD_FAKEADMINAPIWRAPPER_H_ + +#include +#include + +#include + +class FakeAdminApiWrapper : public Cynara::BaseAdminApiWrapper { +public: + using BaseAdminApiWrapper::BaseAdminApiWrapper; + + MOCK_METHOD1(cynara_admin_initialize, int(struct cynara_admin **pp_cynara_admin)); + MOCK_METHOD1(cynara_admin_finish, int(struct cynara_admin *p_cynara_admin)); + MOCK_METHOD2(cynara_admin_set_policies, int(struct cynara_admin *p_cynara_admin, + const struct cynara_admin_policy *const *policies)); + MOCK_METHOD4(cynara_admin_set_bucket, int(struct cynara_admin *p_cynara_admin, + const char *bucket, int operation, const char *extra)); + MOCK_METHOD8(cynara_admin_check, int(struct cynara_admin *p_cynara_admin, + const char *start_bucket, const int recursive, + const char *client, const char *user, const char *privilege, + int *result, char **result_extra)); +}; + +#endif /* TEST_CYAD_FAKEADMINAPIWRAPPER_H_ */ -- 2.7.4 From 6d58a7c2c18f159ab5b6606509f25df7c8e2b54c Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 9 Dec 2014 13:22:55 +0100 Subject: [PATCH 02/16] Introduce CynaraAdminPolicies This is a collection of cynara_admin_policy structs. It helps to manage memory and creates a convenient wrapper while still allowing to pass it to API calls. Change-Id: I61e39dbab88cbbbef07a0bd5ace4967d20336b17 --- src/cyad/CMakeLists.txt | 1 + src/cyad/CynaraAdminPolicies.cpp | 97 ++++++++++++++++++++++++++++++++++++++++ src/cyad/CynaraAdminPolicies.h | 60 +++++++++++++++++++++++++ test/CMakeLists.txt | 3 ++ test/cyad/helpers.cpp | 64 ++++++++++++++++++++++++++ test/cyad/helpers.h | 41 +++++++++++++++++ test/cyad/policy_collection.cpp | 68 ++++++++++++++++++++++++++++ 7 files changed, 334 insertions(+) create mode 100644 src/cyad/CynaraAdminPolicies.cpp create mode 100644 src/cyad/CynaraAdminPolicies.h create mode 100644 test/cyad/helpers.cpp create mode 100644 test/cyad/helpers.h create mode 100644 test/cyad/policy_collection.cpp diff --git a/src/cyad/CMakeLists.txt b/src/cyad/CMakeLists.txt index 1000a0a..d221c75 100644 --- a/src/cyad/CMakeLists.txt +++ b/src/cyad/CMakeLists.txt @@ -20,6 +20,7 @@ SET(CYAD_PATH ${CYNARA_PATH}/cyad) SET(CYAD_SOURCES ${CYAD_PATH}/AdminApiWrapper.cpp + ${CYAD_PATH}/CynaraAdminPolicies.cpp ${CYAD_PATH}/main.cpp ) diff --git a/src/cyad/CynaraAdminPolicies.cpp b/src/cyad/CynaraAdminPolicies.cpp new file mode 100644 index 0000000..4d83014 --- /dev/null +++ b/src/cyad/CynaraAdminPolicies.cpp @@ -0,0 +1,97 @@ +/* + * 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/CynaraAdminPolicies.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Collection of cynara_admin_policy structs + */ + +#include +#include +#include +#include +#include + +#include + +#include "CynaraAdminPolicies.h" + +namespace Cynara { + +CynaraAdminPolicies::CynaraAdminPolicies() : m_sealed(false) {} + +CynaraAdminPolicies::~CynaraAdminPolicies() { + auto freePolicy = [] (cynara_admin_policy *admin_policy) { + if (admin_policy == nullptr) + return; + + free(admin_policy->bucket); + free(admin_policy->client); + free(admin_policy->user); + free(admin_policy->privilege); + free(admin_policy->result_extra); + + delete admin_policy; + }; + + std::for_each(m_policies.begin(), m_policies.end(), freePolicy); +} + +void CynaraAdminPolicies::add(const PolicyBucketId &bucketId, const PolicyResult &policyResult, + const PolicyKey &policyKey) { + if (sealed()) { + throw std::logic_error("Collection is sealed"); + } + + // TODO: Optimize -- try not to malloc every item + cynara_admin_policy *policy = new cynara_admin_policy(); + + auto duplicateString = [] (const std::string &str) -> char * { + auto ret = strdup(str.c_str()); + if (ret == nullptr) + throw std::bad_alloc(); + return ret; + }; + + policy->bucket = duplicateString(bucketId); + policy->client = duplicateString(policyKey.client().toString()); + policy->user = duplicateString(policyKey.user().toString()); + policy->privilege = duplicateString(policyKey.privilege().toString()); + policy->result = policyResult.policyType(); + + if (policyResult.metadata().empty()) + policy->result_extra = nullptr; + else + policy->result_extra = duplicateString(policyResult.metadata()); + + m_policies.push_back(policy); +} + +void CynaraAdminPolicies::seal(void) { + m_policies.push_back(nullptr); + m_sealed = true; +} + +cynara_admin_policy* const *CynaraAdminPolicies::data(void) const { + if (sealed() == false) { + throw std::logic_error("Collection is not sealed"); + } + + return m_policies.data(); +} + +} /* namespace Cynara */ diff --git a/src/cyad/CynaraAdminPolicies.h b/src/cyad/CynaraAdminPolicies.h new file mode 100644 index 0000000..8541783 --- /dev/null +++ b/src/cyad/CynaraAdminPolicies.h @@ -0,0 +1,60 @@ +/* + * 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/CynaraAdminPolicies.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Collection of cynara_admin_policy structs + */ + +#ifndef SRC_CYAD_CYNARAADMINPOLICIES_H_ +#define SRC_CYAD_CYNARAADMINPOLICIES_H_ + +#include + +#include +#include +#include +#include + +struct cynara_admin_policy; + +namespace Cynara { + +class CynaraAdminPolicies { +public: + CynaraAdminPolicies(); + virtual ~CynaraAdminPolicies(); + + void add(const PolicyBucketId &bucketId, const PolicyResult &policyResult, + const PolicyKey &policyKey); + + void seal(void); + + cynara_admin_policy* const *data(void) const; + + bool sealed(void) const { + return m_sealed; + } + +private: + std::vector m_policies; + bool m_sealed; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_CYNARAADMINPOLICIES_H_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6f8ef37..a60837c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -48,6 +48,7 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/common/types/PolicyDescription.cpp ${CYNARA_SRC}/common/types/PolicyResult.cpp ${CYNARA_SRC}/common/types/PolicyType.cpp + ${CYNARA_SRC}/cyad/CynaraAdminPolicies.cpp ${CYNARA_SRC}/helpers/creds-commons/CredsCommonsInner.cpp ${CYNARA_SRC}/helpers/creds-commons/creds-commons.cpp ${CYNARA_SRC}/storage/BucketDeserializer.cpp @@ -70,6 +71,8 @@ SET(CYNARA_TESTS_SOURCES common/protocols/admin/listresponse.cpp common/types/policybucket.cpp credsCommons/parser/Parser.cpp + cyad/helpers.cpp + cyad/policy_collection.cpp helpers.cpp storage/performance/bucket.cpp storage/storage/policies.cpp diff --git a/test/cyad/helpers.cpp b/test/cyad/helpers.cpp new file mode 100644 index 0000000..1f600cb --- /dev/null +++ b/test/cyad/helpers.cpp @@ -0,0 +1,64 @@ +/* + * 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/helpers.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Helper functions, matchers and operators + */ + +#include +#include + +#include + +#include "helpers.h" + +bool operator==(const cynara_admin_policy &lhs, const cynara_admin_policy &rhs) { + auto strEq = [] (const char *lhs, const char *rhs) -> bool { + if (lhs != nullptr && rhs != nullptr) + return strcmp(lhs, rhs) == 0; + else + return lhs == rhs; + }; + + return lhs.result == rhs.result + && strEq(lhs.bucket, rhs.bucket) + && strEq(lhs.client, rhs.client) + && strEq(lhs.user, rhs.user) + && strEq(lhs.privilege, rhs.privilege) + && strEq(lhs.result_extra, rhs.result_extra); +} + +bool operator!=(const cynara_admin_policy &lhs, const cynara_admin_policy &rhs) { + return !(lhs == rhs); +} + +namespace Cynara { + +namespace Helpers { + +void freeAdminPolicyMembers(cynara_admin_policy *admin_policy) { + free(admin_policy->bucket); + free(admin_policy->client); + free(admin_policy->user); + free(admin_policy->privilege); + free(admin_policy->result_extra); +} + +} /* namespace Helpers */ + +} /* namespace Cynara */ diff --git a/test/cyad/helpers.h b/test/cyad/helpers.h new file mode 100644 index 0000000..b4fd02c --- /dev/null +++ b/test/cyad/helpers.h @@ -0,0 +1,41 @@ +/* + * 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/helpers.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Helper functions, matchers and operators + */ + +#ifndef TEST_CYAD_HELPERS_H_ +#define TEST_CYAD_HELPERS_H_ + +struct cynara_admin_policy; + +bool operator==(const cynara_admin_policy &lhs, const cynara_admin_policy &rhs); +bool operator!=(const cynara_admin_policy &lhs, const cynara_admin_policy &rhs); + +namespace Cynara { + +namespace Helpers { + +void freeAdminPolicyMembers(cynara_admin_policy *admin_policy); + +} /* namespace Helpers */ + +} /* namespace Cynara */ + +#endif /* TEST_CYAD_HELPERS_H_ */ diff --git a/test/cyad/policy_collection.cpp b/test/cyad/policy_collection.cpp new file mode 100644 index 0000000..425e025 --- /dev/null +++ b/test/cyad/policy_collection.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file test/cyad/policy_collection.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Tests for CynaraAdminPolicies + */ + +#include +#include + +#include +#include + +#include +#include + +#include + +#include "helpers.h" + +TEST(CynaraAdminPolicies, notSealed) { + Cynara::CynaraAdminPolicies policies; + ASSERT_THROW(policies.data(), std::logic_error); +} + +TEST(CynaraAdminPolicies, sealEmpty) { + Cynara::CynaraAdminPolicies policies; + policies.seal(); + ASSERT_EQ(nullptr, policies.data()[0]); +} + +TEST(CynaraAdminPolicies, addToSealed) { + Cynara::CynaraAdminPolicies policies; + policies.seal(); + ASSERT_THROW(policies.add("", { CYNARA_ADMIN_ALLOW, "" }, { "", "", ""} ), std::logic_error); +} + +TEST(CynaraAdminPolicies, addOne) { + using ::testing::ElementsAreArray; + + Cynara::CynaraAdminPolicies policies; + policies.add("test-bucket", { CYNARA_ADMIN_ALLOW, "" }, { "client", "user", "privilege"} ); + policies.seal(); + ASSERT_NO_THROW(policies.data()); + + cynara_admin_policy policy = { strdup("test-bucket"), strdup("client"), strdup("user"), + strdup("privilege"), CYNARA_ADMIN_ALLOW, nullptr }; + + ASSERT_EQ(policy, *policies.data()[0]); + ASSERT_EQ(nullptr, policies.data()[1]); + + Cynara::Helpers::freeAdminPolicyMembers(&policy); +} -- 2.7.4 From 8069773e3b5568c07c4ea8b9e1412fc909e641fc Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 9 Dec 2014 13:42:33 +0100 Subject: [PATCH 03/16] Introduce DispatcherIO BaseDispatcherIO provides interface for wrapping and aggregating I/O streams. The wrapping is needed mainly for testing purposes, but in near future will be used for printing messages, errors, etc. DispatcherIO is a target implementation, while FakeDispatcherIO is a stub for testing. Change-Id: I1ce231c3bbaf5f7f483358478cdf1eb5ff618589 --- src/cyad/BaseDispatcherIO.h | 49 ++++++++++++++++++++++++++++ src/cyad/CMakeLists.txt | 1 + src/cyad/DispatcherIO.cpp | 40 +++++++++++++++++++++++ src/cyad/DispatcherIO.h | 54 +++++++++++++++++++++++++++++++ test/cyad/FakeDispatcherIO.h | 76 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 220 insertions(+) create mode 100644 src/cyad/BaseDispatcherIO.h create mode 100644 src/cyad/DispatcherIO.cpp create mode 100644 src/cyad/DispatcherIO.h create mode 100644 test/cyad/FakeDispatcherIO.h diff --git a/src/cyad/BaseDispatcherIO.h b/src/cyad/BaseDispatcherIO.h new file mode 100644 index 0000000..3cd8af5 --- /dev/null +++ b/src/cyad/BaseDispatcherIO.h @@ -0,0 +1,49 @@ +/* + * 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/BaseDispatcherIO.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Aggregates I/O methods (base) + */ + +#ifndef SRC_CYAD_BASEDISPATCHERIO_H_ +#define SRC_CYAD_BASEDISPATCHERIO_H_ + +#include +#include +#include +#include + +namespace Cynara { + +class BaseDispatcherIO { +public: + typedef std::string Filename; + typedef std::shared_ptr InputStreamPtr; + + BaseDispatcherIO() = default; + virtual ~BaseDispatcherIO() {} + + virtual InputStreamPtr openFile(const Filename &filename) = 0; + virtual std::ostream &cout(void) = 0; + virtual std::istream &cin(void) = 0; + virtual std::ostream &cerr(void) = 0; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_BASEDISPATCHERIO_H_ */ diff --git a/src/cyad/CMakeLists.txt b/src/cyad/CMakeLists.txt index d221c75..d5f220c 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}/CynaraAdminPolicies.cpp + ${CYAD_PATH}/DispatcherIO.cpp ${CYAD_PATH}/main.cpp ) diff --git a/src/cyad/DispatcherIO.cpp b/src/cyad/DispatcherIO.cpp new file mode 100644 index 0000000..80837e8 --- /dev/null +++ b/src/cyad/DispatcherIO.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 src/cyad/DispatcherIO.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Aggregates I/O methods + */ + +#include + +#include "DispatcherIO.h" + +namespace Cynara { + +BaseDispatcherIO::InputStreamPtr DispatcherIO::openFile(const BaseDispatcherIO::Filename &filename) +{ + BaseDispatcherIO::InputStreamPtr streamPtr; + if (filename == "-") { + streamPtr.reset(&std::cin, [] (BaseDispatcherIO::InputStreamPtr::element_type *) {}); + } else { + streamPtr.reset(new std::ifstream(filename)); + } + return streamPtr; +} + +} /* namespace Cynara */ diff --git a/src/cyad/DispatcherIO.h b/src/cyad/DispatcherIO.h new file mode 100644 index 0000000..b29dfe1 --- /dev/null +++ b/src/cyad/DispatcherIO.h @@ -0,0 +1,54 @@ +/* + * 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/DispatcherIO.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Aggregates I/O methods + */ + +#ifndef SRC_CYAD_DISPATCHERIO_H_ +#define SRC_CYAD_DISPATCHERIO_H_ + +#include + +#include "BaseDispatcherIO.h" + +namespace Cynara { + +class DispatcherIO : public BaseDispatcherIO { +public: + + using BaseDispatcherIO::BaseDispatcherIO; + + BaseDispatcherIO::InputStreamPtr openFile(const BaseDispatcherIO::Filename &filename); + + std::ostream &cout(void) { + return std::cout; + } + + std::istream &cin(void) { + return std::cin; + } + + std::ostream &cerr(void) { + return std::cerr; + } +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_DISPATCHERIO_H_ */ diff --git a/test/cyad/FakeDispatcherIO.h b/test/cyad/FakeDispatcherIO.h new file mode 100644 index 0000000..eb6299b --- /dev/null +++ b/test/cyad/FakeDispatcherIO.h @@ -0,0 +1,76 @@ +/* + * 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/FakeDispatcherIO.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Aggregates I/O methods (stub) + */ + +#ifndef TEST_CYAD_FAKEDISPATCHERIO_H_ +#define TEST_CYAD_FAKEDISPATCHERIO_H_ + +#include +#include + +#include + +class FakeDispatcherIO : public Cynara::BaseDispatcherIO { +public: + + FakeDispatcherIO() : m_inputFile(new std::stringstream()) {} + ~FakeDispatcherIO() = default; + + BaseDispatcherIO::InputStreamPtr openFile(const BaseDispatcherIO::Filename &) { + return m_inputFile; + } + + std::ostream &cout(void) { + return m_out; + } + + std::istream &cin(void) { + return m_cin; + } + + std::ostream &cerr(void) { + return m_err; + } + + std::ostream &file(void) { + return *m_inputFile; + } + + std::stringstream &cerrRaw(void) { + return m_err; + } + + std::stringstream &coutRaw(void) { + return m_out; + } + + std::stringstream &cinRaw(void) { + return m_cin; + } + +private: + std::stringstream m_out; + std::stringstream m_err; + std::stringstream m_cin; + std::shared_ptr m_inputFile; +}; + +#endif /* TEST_CYAD_FAKEDISPATCHERIO_H_ */ -- 2.7.4 From d48d7a933ae8f323ec9a2f3ffac1a410d9f20aa5 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Sat, 6 Dec 2014 14:58:00 +0100 Subject: [PATCH 04/16] Make BucketDeserializer::parseKey() public This static function will be needed in Cyad. Change-Id: Iccc28a9ea6754e23ba7878a07546d426af9e0c9a --- src/storage/BucketDeserializer.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/storage/BucketDeserializer.h b/src/storage/BucketDeserializer.h index 465ecef..666e14e 100644 --- a/src/storage/BucketDeserializer.h +++ b/src/storage/BucketDeserializer.h @@ -38,8 +38,6 @@ public: } PolicyCollection loadPolicies(void); - -protected: static PolicyKey parseKey(const std::string &line, std::size_t &beginToken); private: -- 2.7.4 From 4bd8f4c6596f891d616b9820a995b4110ec77eae Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 9 Dec 2014 14:17:49 +0100 Subject: [PATCH 05/16] Introduce AdminPolicyParser::parse() This function parses input stream and returns a CynaraAdminPolicies collection. It uses parsing functions from cynara-storage library. Change-Id: I3615563a2a8184a5c39b88952af795abd8399748 --- src/cyad/AdminPolicyParser.cpp | 62 ++++++++++++++++++++++++++++++ src/cyad/AdminPolicyParser.h | 41 ++++++++++++++++++++ src/cyad/CMakeLists.txt | 1 + test/CMakeLists.txt | 2 + test/cyad/helpers.h | 14 +++++++ test/cyad/policy_parser.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 205 insertions(+) create mode 100644 src/cyad/AdminPolicyParser.cpp create mode 100644 src/cyad/AdminPolicyParser.h create mode 100644 test/cyad/policy_parser.cpp diff --git a/src/cyad/AdminPolicyParser.cpp b/src/cyad/AdminPolicyParser.cpp new file mode 100644 index 0000000..517dc04 --- /dev/null +++ b/src/cyad/AdminPolicyParser.cpp @@ -0,0 +1,62 @@ +/* + * 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/AdminPolicyParser.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Parses policies from input stream + */ + +#include +#include +#include + +#include "AdminPolicyParser.h" + +namespace Cynara { + +namespace AdminPolicyParser { + +CynaraAdminPolicies parse(const std::shared_ptr &input) { + CynaraAdminPolicies policies; + + for (std::size_t lineNum = 1; !input->eof(); ++lineNum) { + std::string line; + std::getline(*input, line, StorageSerializer::recordSeparator()); + + if (line.empty()) + break; + + try { + std::size_t beginToken = 0; + auto bucketId = StorageDeserializer::parseBucketId(line, beginToken); + auto policyKey = BucketDeserializer::parseKey(line, beginToken); + auto policyType = StorageDeserializer::parsePolicyType(line, beginToken); + auto metadata = StorageDeserializer::parseMetadata(line, beginToken); + + policies.add(bucketId, PolicyResult(policyType, metadata), policyKey); + } catch (const BucketRecordCorruptedException &ex) { + throw ex.withLineNumber(lineNum); + } + } + + policies.seal(); + return policies; +} + +} /* namespace AdminPolicyParser */ + +} /* namespace Cynara */ diff --git a/src/cyad/AdminPolicyParser.h b/src/cyad/AdminPolicyParser.h new file mode 100644 index 0000000..f448408 --- /dev/null +++ b/src/cyad/AdminPolicyParser.h @@ -0,0 +1,41 @@ +/* + * 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/AdminPolicyParser.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Parses policies from input stream + */ + +#ifndef SRC_CYAD_ADMINPOLICYPARSER_H_ +#define SRC_CYAD_ADMINPOLICYPARSER_H_ + +#include +#include + +#include + +namespace Cynara { + +namespace AdminPolicyParser { + +CynaraAdminPolicies parse(const std::shared_ptr &input); + +} /* namespace AdminPolicyParser */ + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_ADMINPOLICYPARSER_H_ */ diff --git a/src/cyad/CMakeLists.txt b/src/cyad/CMakeLists.txt index d5f220c..788e8f2 100644 --- a/src/cyad/CMakeLists.txt +++ b/src/cyad/CMakeLists.txt @@ -20,6 +20,7 @@ SET(CYAD_PATH ${CYNARA_PATH}/cyad) SET(CYAD_SOURCES ${CYAD_PATH}/AdminApiWrapper.cpp + ${CYAD_PATH}/AdminPolicyParser.cpp ${CYAD_PATH}/CynaraAdminPolicies.cpp ${CYAD_PATH}/DispatcherIO.cpp ${CYAD_PATH}/main.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a60837c..6e6d12c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -48,6 +48,7 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/common/types/PolicyDescription.cpp ${CYNARA_SRC}/common/types/PolicyResult.cpp ${CYNARA_SRC}/common/types/PolicyType.cpp + ${CYNARA_SRC}/cyad/AdminPolicyParser.cpp ${CYNARA_SRC}/cyad/CynaraAdminPolicies.cpp ${CYNARA_SRC}/helpers/creds-commons/CredsCommonsInner.cpp ${CYNARA_SRC}/helpers/creds-commons/creds-commons.cpp @@ -73,6 +74,7 @@ SET(CYNARA_TESTS_SOURCES credsCommons/parser/Parser.cpp cyad/helpers.cpp cyad/policy_collection.cpp + cyad/policy_parser.cpp helpers.cpp storage/performance/bucket.cpp storage/storage/policies.cpp diff --git a/test/cyad/helpers.h b/test/cyad/helpers.h index b4fd02c..eb29f9a 100644 --- a/test/cyad/helpers.h +++ b/test/cyad/helpers.h @@ -23,11 +23,25 @@ #ifndef TEST_CYAD_HELPERS_H_ #define TEST_CYAD_HELPERS_H_ +#include +#include + struct cynara_admin_policy; bool operator==(const cynara_admin_policy &lhs, const cynara_admin_policy &rhs); bool operator!=(const cynara_admin_policy &lhs, const cynara_admin_policy &rhs); + +MATCHER_P(AdmPolicyListEq, policies, "") { + unsigned i = 0; + while (policies[i] != nullptr && arg[i] != nullptr) { + if (*policies[i] != *arg[i]) + return false; + ++i; + } + return policies[i] == nullptr && arg[i] == nullptr; +} + namespace Cynara { namespace Helpers { diff --git a/test/cyad/policy_parser.cpp b/test/cyad/policy_parser.cpp new file mode 100644 index 0000000..ab95987 --- /dev/null +++ b/test/cyad/policy_parser.cpp @@ -0,0 +1,85 @@ +/* + * 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 AdminPolicyParser + */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "helpers.h" + +TEST(AdminPolicyParser, parseInvalid) { + auto input = std::make_shared(); + + *input << "invalid input" << std::endl; + + ASSERT_THROW(Cynara::AdminPolicyParser::parse(input), Cynara::BucketRecordCorruptedException); +} + +TEST(AdminPolicyParser, parse0) { + auto input = std::make_shared(); + + Cynara::CynaraAdminPolicies expectedPolicies; + expectedPolicies.seal(); + + auto policies = Cynara::AdminPolicyParser::parse(input); + + ASSERT_TRUE(policies.sealed()); + ASSERT_THAT(policies.data(), AdmPolicyListEq(expectedPolicies.data())); +} + +TEST(AdminPolicyParser, parse1) { + auto input = std::make_shared(); + + *input << "b;c;u;p;0;m" << std::endl; + + Cynara::CynaraAdminPolicies expectedPolicies; + expectedPolicies.add("b", { 0, "m" }, { "c", "u", "p" }); + expectedPolicies.seal(); + + auto policies = Cynara::AdminPolicyParser::parse(input); + + ASSERT_TRUE(policies.sealed()); + ASSERT_THAT(policies.data(), AdmPolicyListEq(expectedPolicies.data())); +} + +TEST(AdminPolicyParser, parse2) { + auto input = std::make_shared(); + + *input << "b1;c1;u1;p1;0;m1" << std::endl; + *input << "b2;c2;u2;p2;0;m2" << std::endl; + + Cynara::CynaraAdminPolicies expectedPolicies; + expectedPolicies.add("b1", { 0, "m1" }, { "c1", "u1", "p1" }); + expectedPolicies.add("b2", { 0, "m2" }, { "c2", "u2", "p2" }); + expectedPolicies.seal(); + + auto policies = Cynara::AdminPolicyParser::parse(input); + + ASSERT_TRUE(policies.sealed()); + ASSERT_THAT(policies.data(), AdmPolicyListEq(expectedPolicies.data())); +} -- 2.7.4 From e3bd02b695ee50b6da7fc0a21c4fa4bca3aa5787 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Sat, 20 Dec 2014 12:49:27 +0100 Subject: [PATCH 06/16] Introduce CommandsDispatcher Change-Id: I220422f667c32c673e0b55b04d9faac39d840037 --- .../AdminLibraryInitializationFailedException.h | 54 ++++++++++++++++ src/cyad/CMakeLists.txt | 2 + src/cyad/CommandlineParser/CyadCommand.cpp | 41 ++++++++++++ src/cyad/CommandlineParser/CyadCommand.h | 72 ++++++++++++++++++++++ src/cyad/CommandsDispatcher.cpp | 61 ++++++++++++++++++ src/cyad/CommandsDispatcher.h | 56 +++++++++++++++++ src/include/cynara-error.h | 32 +++++----- test/CMakeLists.txt | 3 + test/cyad/CyadCommandlineDispatcherTest.h | 36 +++++++++++ test/cyad/commands_dispatcher.cpp | 58 +++++++++++++++++ 10 files changed, 401 insertions(+), 14 deletions(-) create mode 100644 src/cyad/AdminLibraryInitializationFailedException.h create mode 100644 src/cyad/CommandlineParser/CyadCommand.cpp create mode 100644 src/cyad/CommandlineParser/CyadCommand.h create mode 100644 src/cyad/CommandsDispatcher.cpp create mode 100644 src/cyad/CommandsDispatcher.h create mode 100644 test/cyad/CyadCommandlineDispatcherTest.h create mode 100644 test/cyad/commands_dispatcher.cpp diff --git a/src/cyad/AdminLibraryInitializationFailedException.h b/src/cyad/AdminLibraryInitializationFailedException.h new file mode 100644 index 0000000..570660f --- /dev/null +++ b/src/cyad/AdminLibraryInitializationFailedException.h @@ -0,0 +1,54 @@ +/* + * 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/AdminLibraryInitializationFailedException.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Exception thrown when cynara_admin_initialize() fails + */ + +#ifndef SRC_CYAD_ADMINLIBRARYINITIALIZATIONFAILEDEXCEPTION_H_ +#define SRC_CYAD_ADMINLIBRARYINITIALIZATIONFAILEDEXCEPTION_H_ + +#include + +#include + +namespace Cynara { + +class AdminLibraryInitializationFailedException: public Exception { +public: + AdminLibraryInitializationFailedException(int errorCode) : m_errorCode(errorCode) { + m_message = "Initialization of cynara-admin failed: [" + std::to_string(m_errorCode) + "]"; + } + virtual ~AdminLibraryInitializationFailedException() {}; + + virtual const std::string &message(void) const { + return m_message; + } + + int errorCode(void) const { + return m_errorCode; + } + +private: + int m_errorCode; + std::string m_message; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_ADMINLIBRARYINITIALIZATIONFAILEDEXCEPTION_H_ */ diff --git a/src/cyad/CMakeLists.txt b/src/cyad/CMakeLists.txt index 788e8f2..1ce4d1e 100644 --- a/src/cyad/CMakeLists.txt +++ b/src/cyad/CMakeLists.txt @@ -22,6 +22,8 @@ SET(CYAD_SOURCES ${CYAD_PATH}/AdminApiWrapper.cpp ${CYAD_PATH}/AdminPolicyParser.cpp ${CYAD_PATH}/CynaraAdminPolicies.cpp + ${CYAD_PATH}/CommandlineParser/CyadCommand.cpp + ${CYAD_PATH}/CommandsDispatcher.cpp ${CYAD_PATH}/DispatcherIO.cpp ${CYAD_PATH}/main.cpp ) diff --git a/src/cyad/CommandlineParser/CyadCommand.cpp b/src/cyad/CommandlineParser/CyadCommand.cpp new file mode 100644 index 0000000..6723e7e --- /dev/null +++ b/src/cyad/CommandlineParser/CyadCommand.cpp @@ -0,0 +1,41 @@ +/* + * 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/CyadCommand.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief A representation of Cyad command + */ + +#include + +#include "CyadCommand.h" + +namespace Cynara { + +int CyadCommand::run(CommandsDispatcher &dispatcher) { + return dispatcher.execute(*this); +} + +int ErrorCyadCommand::run(CommandsDispatcher &dispatcher) { + return dispatcher.execute(*this); +} + +int HelpCyadCommand::run(CommandsDispatcher &dispatcher) { + return dispatcher.execute(*this); +} + +} /* namespace Cynara */ diff --git a/src/cyad/CommandlineParser/CyadCommand.h b/src/cyad/CommandlineParser/CyadCommand.h new file mode 100644 index 0000000..2a233d7 --- /dev/null +++ b/src/cyad/CommandlineParser/CyadCommand.h @@ -0,0 +1,72 @@ +/* + * 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/CyadCommand.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief A representation of Cyad command + */ + +#ifndef SRC_CYAD_COMMANDLINEPARSER_CYADCOMMAND_H_ +#define SRC_CYAD_COMMANDLINEPARSER_CYADCOMMAND_H_ + +#include + +namespace Cynara { + +class CommandsDispatcher; + +class CyadCommand { +public: + CyadCommand() = default; + virtual ~CyadCommand() {} + + virtual int run(CommandsDispatcher &dispatcher); + + virtual bool isError(void) const { + return false; + } +}; + +class ErrorCyadCommand : public CyadCommand { +public: + ErrorCyadCommand(const std::string &message) : m_message(message) {} + virtual ~ErrorCyadCommand() {} + + virtual int run(CommandsDispatcher &dispatcher); + + virtual bool isError(void) const { + return true; + } + + virtual const std::string &message(void) const { + return m_message; + } + +private: + std::string m_message; +}; + +class HelpCyadCommand : public CyadCommand { +public: + using CyadCommand::CyadCommand; + + virtual int run(CommandsDispatcher &dispatcher); +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_COMMANDLINEPARSER_CYADCOMMAND_H_ */ diff --git a/src/cyad/CommandsDispatcher.cpp b/src/cyad/CommandsDispatcher.cpp new file mode 100644 index 0000000..dee8ce3 --- /dev/null +++ b/src/cyad/CommandsDispatcher.cpp @@ -0,0 +1,61 @@ +/* + * 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/CommandsDispatcher.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief CommandsDispatcher class (implementation) + */ + +#include + +#include + +#include "CommandsDispatcher.h" + +namespace Cynara { + +CommandsDispatcher::CommandsDispatcher(BaseDispatcherIO &io, BaseAdminApiWrapper &adminApiWrapper) + : m_io(io), m_adminApiWrapper(adminApiWrapper), m_cynaraAdmin(nullptr) +{ + auto ret = m_adminApiWrapper.cynara_admin_initialize(&m_cynaraAdmin); + if (ret != CYNARA_API_SUCCESS) + throw AdminLibraryInitializationFailedException(ret); +} + +CommandsDispatcher::~CommandsDispatcher() { + m_adminApiWrapper.cynara_admin_finish(m_cynaraAdmin); +} + +int CommandsDispatcher::execute(CyadCommand &) { + m_io.cout() << "Whatever you wanted, it's not implemented" << std::endl; + return CYNARA_API_UNKNOWN_ERROR; +} + +int CommandsDispatcher::execute(HelpCyadCommand &) { + m_io.cout() << helpMessage << std::endl; + return CYNARA_API_SUCCESS; +} + +int CommandsDispatcher::execute(ErrorCyadCommand &result) { + m_io.cout() << "There was an error in command-line options:" << std::endl; + m_io.cout() << result.message() << std::endl; + + m_io.cout() << std::endl << helpMessage << std::endl; + return CYNARA_API_INVALID_COMMANDLINE_PARAM; +} + +} /* namespace Cynara */ diff --git a/src/cyad/CommandsDispatcher.h b/src/cyad/CommandsDispatcher.h new file mode 100644 index 0000000..a776682 --- /dev/null +++ b/src/cyad/CommandsDispatcher.h @@ -0,0 +1,56 @@ +/* + * 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/CommandsDispatcher.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief CommandsDispatcher class + */ + +#ifndef SRC_CYAD_COMMANDSDISPATCHER_H_ +#define SRC_CYAD_COMMANDSDISPATCHER_H_ + +#include +#include +#include + +struct cynara_admin; +struct cynara_admin_policy; + +namespace Cynara { + +class CommandsDispatcher { +public: + CommandsDispatcher(BaseDispatcherIO &io, BaseAdminApiWrapper &adminApiWrapper); + virtual ~CommandsDispatcher(); + + virtual int execute(CyadCommand &); + virtual int execute(HelpCyadCommand &); + virtual int execute(ErrorCyadCommand &); + +private: + // TODO: Get argv[0] instead of hardcoded name + const std::string helpMessage = "Usage: cyad [OPTIONS]\n\n" + "Help options:\n" + " -h, --help print help message"; + BaseDispatcherIO &m_io; + BaseAdminApiWrapper &m_adminApiWrapper; + struct cynara_admin *m_cynaraAdmin; +}; + +} /* namespace Cynara */ + +#endif /* SRC_CYAD_COMMANDSDISPATCHER_H_ */ diff --git a/src/include/cynara-error.h b/src/include/cynara-error.h index 8ac7de1..66d75f0 100644 --- a/src/include/cynara-error.h +++ b/src/include/cynara-error.h @@ -18,6 +18,7 @@ * @author Lukasz Wojciechowski * @author Zofia Abramowska * @author Radoslaw Bartosiak + * @author Aleksander Zdyb * @version 1.0 * @brief This file contains error codes returned by APIs of Cynara. */ @@ -33,46 +34,49 @@ */ /*! \brief indicating access that was checked is allowed */ -#define CYNARA_API_ACCESS_ALLOWED 2 +#define CYNARA_API_ACCESS_ALLOWED 2 /*! \brief indicating that access that was checked is denied */ -#define CYNARA_API_ACCESS_DENIED 1 +#define CYNARA_API_ACCESS_DENIED 1 /*! \brief indicating the result of the one specific API is successful */ -#define CYNARA_API_SUCCESS 0 +#define CYNARA_API_SUCCESS 0 /*! \brief indicating that value is not present in cache */ -#define CYNARA_API_CACHE_MISS -1 +#define CYNARA_API_CACHE_MISS -1 /*! \brief indicating that pending requests reached maximum */ -#define CYNARA_API_MAX_PENDING_REQUESTS -2 +#define CYNARA_API_MAX_PENDING_REQUESTS -2 /*! \brief indicating system is running out of memory state */ -#define CYNARA_API_OUT_OF_MEMORY -3 +#define CYNARA_API_OUT_OF_MEMORY -3 /*! \brief indicating the API's parameter is malformed */ -#define CYNARA_API_INVALID_PARAM -4 +#define CYNARA_API_INVALID_PARAM -4 /*! \brief indicating that service is not available */ -#define CYNARA_API_SERVICE_NOT_AVAILABLE -5 +#define CYNARA_API_SERVICE_NOT_AVAILABLE -5 /*! \brief indicating that provided method is not supported by library */ -#define CYNARA_API_METHOD_NOT_SUPPORTED -6 +#define CYNARA_API_METHOD_NOT_SUPPORTED -6 /*! \brief cynara service does not allow to perform requested operation */ -#define CYNARA_API_OPERATION_NOT_ALLOWED -7 +#define CYNARA_API_OPERATION_NOT_ALLOWED -7 /*! \brief cynara service failed to perform requested operation */ -#define CYNARA_API_OPERATION_FAILED -8 +#define CYNARA_API_OPERATION_FAILED -8 /*! \brief cynara service hasn't found requested bucket */ -#define CYNARA_API_BUCKET_NOT_FOUND -9 +#define CYNARA_API_BUCKET_NOT_FOUND -9 /*! \brief indicating an unknown error */ -#define CYNARA_API_UNKNOWN_ERROR -10 +#define CYNARA_API_UNKNOWN_ERROR -10 /*! \brief indicating configuration error */ -#define CYNARA_API_CONFIGURATION_ERROR -11 +#define CYNARA_API_CONFIGURATION_ERROR -11 + +/*! \brief indicating invalid parameter in command-line */ +#define CYNARA_API_INVALID_COMMANDLINE_PARAM -12 /** @}*/ #endif /* CYNARA_ERROR_H */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6e6d12c..f99d555 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,6 +49,8 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/common/types/PolicyResult.cpp ${CYNARA_SRC}/common/types/PolicyType.cpp ${CYNARA_SRC}/cyad/AdminPolicyParser.cpp + ${CYNARA_SRC}/cyad/CommandlineParser/CyadCommand.cpp + ${CYNARA_SRC}/cyad/CommandsDispatcher.cpp ${CYNARA_SRC}/cyad/CynaraAdminPolicies.cpp ${CYNARA_SRC}/helpers/creds-commons/CredsCommonsInner.cpp ${CYNARA_SRC}/helpers/creds-commons/creds-commons.cpp @@ -72,6 +74,7 @@ SET(CYNARA_TESTS_SOURCES common/protocols/admin/listresponse.cpp common/types/policybucket.cpp credsCommons/parser/Parser.cpp + cyad/commands_dispatcher.cpp cyad/helpers.cpp cyad/policy_collection.cpp cyad/policy_parser.cpp diff --git a/test/cyad/CyadCommandlineDispatcherTest.h b/test/cyad/CyadCommandlineDispatcherTest.h new file mode 100644 index 0000000..504af80 --- /dev/null +++ b/test/cyad/CyadCommandlineDispatcherTest.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file test/cyad/CyadCommandlineDispatcherTest.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Test fixture for CyadCommandlineDispatcher + */ + +#ifndef TEST_CYAD_CYADCOMMANDLINEDISPATCHERTEST_H_ +#define TEST_CYAD_CYADCOMMANDLINEDISPATCHERTEST_H_ + +#include +#include + +#include "FakeDispatcherIO.h" + +class CyadCommandlineDispatcherTest : public ::testing::Test { +protected: + FakeDispatcherIO m_io; +}; + +#endif /* TEST_CYAD_CYADCOMMANDLINEDISPATCHERTEST_H_ */ diff --git a/test/cyad/commands_dispatcher.cpp b/test/cyad/commands_dispatcher.cpp new file mode 100644 index 0000000..9a948e6 --- /dev/null +++ b/test/cyad/commands_dispatcher.cpp @@ -0,0 +1,58 @@ +/* + * 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/commands_dispatcher.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief Tests for CommandsDispatcher + */ + +#include +#include + +#include + +#include +#include + +#include "CyadCommandlineDispatcherTest.h" +#include "FakeAdminApiWrapper.h" + +/** + * @brief Dispatcher should not touch admin API on help or error + * @test Scenario: + * - Prepare some parsing results not requiring API calls + * - Check if no API calls were made + */ +TEST_F(CyadCommandlineDispatcherTest, noApi) { + 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::CyadCommand result; + Cynara::HelpCyadCommand helpResult; + Cynara::ErrorCyadCommand errorResult("Fake error"); + + dispatcher.execute(result); + dispatcher.execute(helpResult); + dispatcher.execute(errorResult); +} -- 2.7.4 From 83664a6430bce4c76aa30ad49cdd603cce908530 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Sat, 20 Dec 2014 13:05:23 +0100 Subject: [PATCH 07/16] Add --set-bucket and --delete-bucket to Cyad Change-Id: I54b8199b3daf59bf9a8f81222391e42980ba2f41 --- src/cyad/CommandlineParser/CyadCommand.cpp | 8 ++++ src/cyad/CommandlineParser/CyadCommand.h | 41 ++++++++++++++++ src/cyad/CommandsDispatcher.cpp | 15 ++++++ src/cyad/CommandsDispatcher.h | 10 ++++ test/cyad/commands_dispatcher.cpp | 75 ++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+) diff --git a/src/cyad/CommandlineParser/CyadCommand.cpp b/src/cyad/CommandlineParser/CyadCommand.cpp index 6723e7e..8d27cf8 100644 --- a/src/cyad/CommandlineParser/CyadCommand.cpp +++ b/src/cyad/CommandlineParser/CyadCommand.cpp @@ -38,4 +38,12 @@ int HelpCyadCommand::run(CommandsDispatcher &dispatcher) { return dispatcher.execute(*this); } +int SetBucketCyadCommand::run(CommandsDispatcher &dispatcher) { + return dispatcher.execute(*this); +} + +int DeleteBucketCyadCommand::run(CommandsDispatcher &dispatcher) { + return dispatcher.execute(*this); +} + } /* namespace Cynara */ diff --git a/src/cyad/CommandlineParser/CyadCommand.h b/src/cyad/CommandlineParser/CyadCommand.h index 2a233d7..e5d3277 100644 --- a/src/cyad/CommandlineParser/CyadCommand.h +++ b/src/cyad/CommandlineParser/CyadCommand.h @@ -25,6 +25,9 @@ #include +#include +#include + namespace Cynara { class CommandsDispatcher; @@ -67,6 +70,44 @@ public: virtual int run(CommandsDispatcher &dispatcher); }; +class SetBucketCyadCommand : public CyadCommand { +public: + SetBucketCyadCommand(const PolicyBucketId &bucketId, const PolicyResult &policyResult) + : m_bucketId(bucketId), m_policyResult(policyResult) {} + + virtual ~SetBucketCyadCommand() {} + + virtual int run(CommandsDispatcher &dispatcher); + + const PolicyBucketId &bucketId(void) const { + return m_bucketId; + } + + const PolicyResult &policyResult(void) const { + return m_policyResult; + } + +private: + PolicyBucketId m_bucketId; + PolicyResult m_policyResult; +}; + +class DeleteBucketCyadCommand : public CyadCommand { +public: + explicit DeleteBucketCyadCommand(const PolicyBucketId &bucketId) : m_bucketId(bucketId) {} + + virtual ~DeleteBucketCyadCommand() {} + + virtual int run(CommandsDispatcher &dispatcher); + + const PolicyBucketId &bucketId(void) const { + return m_bucketId; + } + +private: + PolicyBucketId m_bucketId; +}; + } /* namespace Cynara */ #endif /* SRC_CYAD_COMMANDLINEPARSER_CYADCOMMAND_H_ */ diff --git a/src/cyad/CommandsDispatcher.cpp b/src/cyad/CommandsDispatcher.cpp index dee8ce3..b8e256c 100644 --- a/src/cyad/CommandsDispatcher.cpp +++ b/src/cyad/CommandsDispatcher.cpp @@ -21,6 +21,7 @@ */ #include +#include #include @@ -58,4 +59,18 @@ int CommandsDispatcher::execute(ErrorCyadCommand &result) { return CYNARA_API_INVALID_COMMANDLINE_PARAM; } +int CommandsDispatcher::execute(DeleteBucketCyadCommand &result) { + return m_adminApiWrapper.cynara_admin_set_bucket(m_cynaraAdmin, result.bucketId().c_str(), + CYNARA_ADMIN_DELETE, nullptr); +} + +int CommandsDispatcher::execute(SetBucketCyadCommand &result) { + const auto &policyResult = result.policyResult(); + const char *metadata = policyResult.metadata().empty() ? nullptr + : policyResult.metadata().c_str(); + return m_adminApiWrapper.cynara_admin_set_bucket(m_cynaraAdmin, + result.bucketId().c_str(), + policyResult.policyType(), metadata); +} + } /* namespace Cynara */ diff --git a/src/cyad/CommandsDispatcher.h b/src/cyad/CommandsDispatcher.h index a776682..36dfc60 100644 --- a/src/cyad/CommandsDispatcher.h +++ b/src/cyad/CommandsDispatcher.h @@ -40,10 +40,20 @@ public: virtual int execute(CyadCommand &); virtual int execute(HelpCyadCommand &); virtual int execute(ErrorCyadCommand &); + virtual int execute(DeleteBucketCyadCommand &); + virtual int execute(SetBucketCyadCommand &); private: // TODO: Get argv[0] instead of hardcoded name const std::string helpMessage = "Usage: cyad [OPTIONS]\n\n" + "Bucket set options (with -b or --set-bucket)\n" + " -b, --set-bucket= name of bucket\n" + " -p, --policy= default policy\n" + " -m, --metadata= metadata for default policy\n" + "\n" + "Bucket delete options (with -d or --delete-bucket)\n" + " -d, --delete-bucket= name of bucket to delete\n" + "\n" "Help options:\n" " -h, --help print help message"; BaseDispatcherIO &m_io; diff --git a/test/cyad/commands_dispatcher.cpp b/test/cyad/commands_dispatcher.cpp index 9a948e6..6f70770 100644 --- a/test/cyad/commands_dispatcher.cpp +++ b/test/cyad/commands_dispatcher.cpp @@ -20,11 +20,17 @@ * @brief Tests for CommandsDispatcher */ +#include +#include + #include #include #include +#include +#include +#include #include #include @@ -56,3 +62,72 @@ TEST_F(CyadCommandlineDispatcherTest, noApi) { dispatcher.execute(helpResult); dispatcher.execute(errorResult); } + +TEST_F(CyadCommandlineDispatcherTest, deleteBucket) { + using ::testing::_; + using ::testing::Return; + using ::testing::StrEq; + using ::testing::IsNull; + + 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::DeleteBucketCyadCommand result("test-bucket"); + + EXPECT_CALL(adminApi, + cynara_admin_set_bucket(_, StrEq("test-bucket"), CYNARA_ADMIN_DELETE, IsNull())) + .WillOnce(Return(CYNARA_API_SUCCESS)); + + dispatcher.execute(result); +} + +TEST_F(CyadCommandlineDispatcherTest, setBucket) { + using ::testing::_; + using ::testing::Return; + using ::testing::StrEq; + using ::testing::IsNull; + using Cynara::PolicyBucketId; + using Cynara::PolicyType; + using Cynara::PolicyResult; + + 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); + + typedef std::tuple BucketData; + typedef std::vector Buckets; + const Buckets buckets = { BucketData("test-bucket-1", { CYNARA_ADMIN_ALLOW, "" }), + BucketData("test-bucket-2", { CYNARA_ADMIN_DENY, "" }), + BucketData("test-bucket-3", { CYNARA_ADMIN_BUCKET, "other-bucket" }), + BucketData("test-bucket-2", { CYNARA_ADMIN_NONE, "" }), + BucketData("test-bucket-4", { 42, "douglas-noel-adams" }) }; + + for (const auto &bucket : buckets) { + const auto &bucketId = std::get<0>(bucket); + const auto &policyResult = std::get<1>(bucket); + + SCOPED_TRACE(bucketId); + + Cynara::SetBucketCyadCommand result(bucketId, policyResult); + + if (policyResult.metadata().empty() == false) { + EXPECT_CALL(adminApi, + cynara_admin_set_bucket(_, StrEq(bucketId.c_str()), policyResult.policyType(), + StrEq(policyResult.metadata().c_str()))) + .WillOnce(Return(CYNARA_API_SUCCESS)); + } else { + EXPECT_CALL(adminApi, + cynara_admin_set_bucket(_, StrEq(bucketId.c_str()), policyResult.policyType(), + IsNull())) + .WillOnce(Return(CYNARA_API_SUCCESS)); + } + + dispatcher.execute(result); + } +} -- 2.7.4 From 470d42b69949640809a7c4ca179c65968a2b475d Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Fri, 12 Dec 2014 13:53:25 +0100 Subject: [PATCH 08/16] Add --set-policy option to Cyad Change-Id: I62dedb73c9f486cc071d2f80d93721fd81a07d13 --- src/cyad/CommandlineParser/CyadCommand.cpp | 4 +++ src/cyad/CommandlineParser/CyadCommand.h | 29 +++++++++++++++++ src/cyad/CommandsDispatcher.cpp | 10 ++++++ src/cyad/CommandsDispatcher.h | 8 +++++ test/cyad/commands_dispatcher.cpp | 50 ++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+) diff --git a/src/cyad/CommandlineParser/CyadCommand.cpp b/src/cyad/CommandlineParser/CyadCommand.cpp index 8d27cf8..8ab6934 100644 --- a/src/cyad/CommandlineParser/CyadCommand.cpp +++ b/src/cyad/CommandlineParser/CyadCommand.cpp @@ -46,4 +46,8 @@ int DeleteBucketCyadCommand::run(CommandsDispatcher &dispatcher) { return dispatcher.execute(*this); } +int SetPolicyCyadCommand::run(CommandsDispatcher &dispatcher) { + return dispatcher.execute(*this); +} + } /* namespace Cynara */ diff --git a/src/cyad/CommandlineParser/CyadCommand.h b/src/cyad/CommandlineParser/CyadCommand.h index e5d3277..2870582 100644 --- a/src/cyad/CommandlineParser/CyadCommand.h +++ b/src/cyad/CommandlineParser/CyadCommand.h @@ -26,6 +26,7 @@ #include #include +#include #include namespace Cynara { @@ -108,6 +109,34 @@ private: PolicyBucketId m_bucketId; }; +class SetPolicyCyadCommand : public CyadCommand { +public: + SetPolicyCyadCommand(const PolicyBucketId &bucketId, const PolicyResult &policyResult, + const PolicyKey &policyKey) + : m_bucketId(bucketId), m_policyResult(policyResult), m_policyKey(policyKey) {} + + virtual ~SetPolicyCyadCommand() {} + + virtual int run(CommandsDispatcher &dispatcher); + + const PolicyBucketId &bucketId(void) const { + return m_bucketId; + } + + const PolicyResult &policyResult(void) const { + return m_policyResult; + } + + const PolicyKey &policyKey(void) const { + return m_policyKey; + } + +private: + PolicyBucketId m_bucketId; + PolicyResult m_policyResult; + PolicyKey m_policyKey; +}; + } /* namespace Cynara */ #endif /* SRC_CYAD_COMMANDLINEPARSER_CYADCOMMAND_H_ */ diff --git a/src/cyad/CommandsDispatcher.cpp b/src/cyad/CommandsDispatcher.cpp index b8e256c..436e144 100644 --- a/src/cyad/CommandsDispatcher.cpp +++ b/src/cyad/CommandsDispatcher.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "CommandsDispatcher.h" @@ -73,4 +74,13 @@ int CommandsDispatcher::execute(SetBucketCyadCommand &result) { policyResult.policyType(), metadata); } +int CommandsDispatcher::execute(SetPolicyCyadCommand &result) { + CynaraAdminPolicies policies; + + policies.add(result.bucketId(), result.policyResult(), result.policyKey()); + policies.seal(); + + return m_adminApiWrapper.cynara_admin_set_policies(m_cynaraAdmin, policies.data()); +} + } /* namespace Cynara */ diff --git a/src/cyad/CommandsDispatcher.h b/src/cyad/CommandsDispatcher.h index 36dfc60..63d2441 100644 --- a/src/cyad/CommandsDispatcher.h +++ b/src/cyad/CommandsDispatcher.h @@ -42,6 +42,7 @@ public: virtual int execute(ErrorCyadCommand &); virtual int execute(DeleteBucketCyadCommand &); virtual int execute(SetBucketCyadCommand &); + virtual int execute(SetPolicyCyadCommand &); private: // TODO: Get argv[0] instead of hardcoded name @@ -54,6 +55,13 @@ private: "Bucket delete options (with -d or --delete-bucket)\n" " -d, --delete-bucket= name of bucket to delete\n" "\n" + "Policy set options (with -s or --set-policy)\n" + " -l, --client= client value\n" + " -u, --user= user value\n" + " -r, --privilege= privilege value\n" + " -p, --policy= policy\n" + " -m, --metadata= metadata for policy\n" + "\n" "Help options:\n" " -h, --help print help message"; BaseDispatcherIO &m_io; diff --git a/test/cyad/commands_dispatcher.cpp b/test/cyad/commands_dispatcher.cpp index 6f70770..d459dad 100644 --- a/test/cyad/commands_dispatcher.cpp +++ b/test/cyad/commands_dispatcher.cpp @@ -31,11 +31,13 @@ #include #include +#include #include #include #include "CyadCommandlineDispatcherTest.h" #include "FakeAdminApiWrapper.h" +#include "helpers.h" /** * @brief Dispatcher should not touch admin API on help or error @@ -131,3 +133,51 @@ TEST_F(CyadCommandlineDispatcherTest, setBucket) { dispatcher.execute(result); } } + +TEST_F(CyadCommandlineDispatcherTest, setPolicy) { + 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::SetPolicyCyadCommand result("test-bucket", { CYNARA_ADMIN_ALLOW, "" }, + { "client", "user", "privilege" }); + + Cynara::CynaraAdminPolicies expectedPolicies; + expectedPolicies.add("test-bucket", { CYNARA_ADMIN_ALLOW, "" }, + { "client", "user", "privilege"} ); + expectedPolicies.seal(); + + EXPECT_CALL(adminApi, cynara_admin_set_policies(_, AdmPolicyListEq(expectedPolicies.data()))) + .WillOnce(Return(CYNARA_API_SUCCESS)); + + dispatcher.execute(result); +} + +TEST_F(CyadCommandlineDispatcherTest, setPolicyWithMetadata) { + 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::SetPolicyCyadCommand result("test-bucket", { CYNARA_ADMIN_ALLOW, "metadata" }, + Cynara::PolicyKey("client", "user", "privilege")); + + Cynara::CynaraAdminPolicies expectedPolicies; + expectedPolicies.add("test-bucket", { CYNARA_ADMIN_ALLOW, "metadata" }, + { "client", "user", "privilege"} ); + expectedPolicies.seal(); + + EXPECT_CALL(adminApi, cynara_admin_set_policies(_, AdmPolicyListEq(expectedPolicies.data()))) + .WillOnce(Return(CYNARA_API_SUCCESS)); + + dispatcher.execute(result); +} -- 2.7.4 From 4c8af90c302f2f8ed13d542f3804e40cee90a800 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Fri, 12 Dec 2014 14:25:08 +0100 Subject: [PATCH 09/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 10/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 11/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 12/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 13/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 14/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 15/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 16/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