SET(LIB_CYNARA_SOURCES
${CYNARA_LIB_CYNARA_PATH}/api/client-api.cpp
- ${CYNARA_LIB_CYNARA_PATH}/cache/NoCache.cpp
+ ${CYNARA_LIB_CYNARA_PATH}/cache/CapacityCache.cpp
+ ${CYNARA_LIB_CYNARA_PATH}/cache/PolicyGetter.cpp
${CYNARA_LIB_CYNARA_PATH}/logic/Logic.cpp
)
/*
* @file CacheInterface.h
* @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
* @version 1.0
- * @brief This file contains cache interface definition.
+ * @brief This file contains cache interface definitions.
*/
#ifndef SRC_CLIENT_CACHE_CACHEINTERFACE_H_
#define SRC_CLIENT_CACHE_CACHEINTERFACE_H_
+#include <map>
#include <memory>
#include <string>
+#include <cynara-client.h>
#include <types/PolicyKey.h>
#include <types/PolicyResult.h>
-
-#include <cynara-client.h>
+#include <types/PolicyType.h>
namespace Cynara {
-class CacheInterface;
-typedef std::shared_ptr<CacheInterface> CacheInterfacePtr;
+class InterpreterInterface;
+typedef std::shared_ptr<InterpreterInterface> InterpreterInterfacePtr;
+
+class PluginCache;
+typedef std::shared_ptr<PluginCache> PluginCachePtr;
+
+class ResultGetterInterface;
+typedef std::shared_ptr<ResultGetterInterface> ResultGetterInterfacePtr;
+
+class ResultGetterInterface {
+public:
+ virtual cynara_api_result requestResult(const PolicyKey &key, PolicyResult &result) noexcept = 0;
+ virtual ~ResultGetterInterface() = default;
+};
+
+class InterpreterInterface {
+public:
+ virtual bool isCacheable(const PolicyResult &result) noexcept = 0;
+ virtual bool isUsable(const PolicyResult &result) noexcept = 0;
+ virtual cynara_api_result toResult(const PolicyResult &result) noexcept = 0;
+
+ virtual ~InterpreterInterface() = default;
+};
-class CacheInterface {
+class PluginCache {
public:
- CacheInterface() = default;
- virtual ~CacheInterface() = default;
+ PluginCache(ResultGetterInterfacePtr getter) : m_getter(getter) {}
+ virtual cynara_api_result get(const std::string &session, const PolicyKey &key) = 0;
+ void registerPlugin(const PolicyType policyType, InterpreterInterfacePtr plugin) {
+ m_plugins[policyType] = plugin;
+ }
+ virtual void clear(void) {
+ m_plugins.clear();
+ }
+ virtual ~PluginCache() = default;
- virtual cynara_api_result check(const std::string &session, const PolicyKey &key) = 0;
- virtual cynara_api_result updateAndCheck(const std::string &session, const PolicyKey &key,
- const PolicyResult &result) = 0;
- virtual void clear(void) = 0;
+protected:
+ std::map<PolicyType, InterpreterInterfacePtr> m_plugins;
+ ResultGetterInterfacePtr m_getter;
};
} // namespace Cynara
-#endif /* SRC_CLIENT_CACHE_CACHEINTERFACE_H_ */
+#endif // SRC_CLIENT_CACHE_CACHEINTERFACE_H_
--- /dev/null
+/*
+ * 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 CapacityCache.cpp
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @version 1.0
+ * @brief This file contains capacity cache implementation.
+ */
+
+#include <cinttypes>
+
+#include <log/log.h>
+
+#include <cache/CapacityCache.h>
+
+namespace Cynara {
+
+cynara_api_result CapacityCache::get(const std::string &session, const PolicyKey &key) {
+ //This can be very time heavy. This part is welcomed to be optimized.
+ if (session != m_session) {
+ LOGD("Session changed from %s to %s.", m_session.c_str(), session.c_str());
+ m_keyValue.clear();
+ m_keyUsage.clear();
+ m_session = session;
+ }
+ auto resultIt = m_keyValue.find(keyToString(key));
+ //Do we have entry in cache?
+ if (resultIt == m_keyValue.end()) {
+ LOGD("No entry for client=%s user=%s privilege=%s.",
+ key.client().toString().c_str(),
+ key.user().toString().c_str(),
+ key.privilege().toString().c_str());
+ return update(key);
+ } else {
+ LOGD("Entry available for client=%s user=%s privilege=%s",
+ key.client().toString().c_str(),
+ key.user().toString().c_str(),
+ key.privilege().toString().c_str());
+
+ auto pluginIt = m_plugins.find(resultIt->second.first.policyType());
+ if (pluginIt == m_plugins.end()) {
+ LOGE("No plugin registered for given PolicyType : %" PRIu16,
+ resultIt->second.first.policyType());
+ return cynara_api_result::CYNARA_API_ACCESS_DENIED;
+ }
+
+ //Is it still usable?
+ InterpreterInterfacePtr plugin = pluginIt->second;
+ if (plugin->isUsable(resultIt->second.first)) {
+ LOGD("Entry usable.");
+ m_keyUsage.splice(m_keyUsage.begin(), m_keyUsage, resultIt->second.second);
+ return plugin->toResult(resultIt->second.first);
+ } else {
+ //remove from list and map and update
+ LOGD("Entry not usable.");
+ auto usage_it = resultIt->second.second;
+ m_keyUsage.erase(usage_it);
+ m_keyValue.erase(resultIt);
+ return update(key);
+ }
+ }
+}
+
+void CapacityCache::clear(void) {
+ m_keyUsage.clear();
+ m_keyValue.clear();
+ m_session.clear();
+}
+
+std::string CapacityCache::keyToString(const PolicyKey &key) {
+ const char separator = '\1';
+ auto clientStr = key.client().toString();
+ auto privilegeStr = key.privilege().toString();
+ auto userStr = key.user().toString();
+ return clientStr + privilegeStr + userStr + separator +
+ std::to_string(clientStr.size()) + separator +
+ std::to_string(privilegeStr.size()) + separator +
+ std::to_string(userStr.size());
+}
+
+void CapacityCache::evict(void) {
+
+ auto lastUsedKey = m_keyUsage.back();
+ m_keyUsage.pop_back();
+
+ auto value_it = m_keyValue.find(lastUsedKey);
+ m_keyValue.erase(value_it);
+}
+
+cynara_api_result CapacityCache::update(const PolicyKey &key) {
+ cynara_api_result ret;
+ PolicyResult result;
+ if ((ret = m_getter->requestResult(key, result)) != cynara_api_result::CYNARA_API_SUCCESS) {
+ LOGE("Error fetching new entry.");
+ return ret;
+ }
+ LOGD("Fetched new entry.");
+ auto pluginIt = m_plugins.find(result.policyType());
+
+ //No registered plugin for returned type of policy
+ if (pluginIt == m_plugins.end()) {
+ LOGE("No registered plugin for given PolicyType: %" PRIu16,
+ result.policyType());
+ return cynara_api_result::CYNARA_API_ACCESS_DENIED;
+ }
+ auto plugin = pluginIt->second;
+
+ if (m_capacity != 0) {
+ if (plugin->isCacheable(result)) {
+ LOGD("Entry cacheable");
+ if (m_keyValue.size() == m_capacity) {
+ LOGD("Capacity reached.");
+ evict();
+ }
+ m_keyUsage.push_front(keyToString(key));
+ m_keyValue[keyToString(key)] = std::make_pair(result, m_keyUsage.begin());
+ }
+ }
+ return plugin->toResult(result);
+}
+
+} // namespace Cynara
--- /dev/null
+/*
+ * 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 CapacityCache.h
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @version 1.0
+ * @brief This file contains capacity cache header.
+ */
+
+#ifndef SRC_CLIENT_CACHE_CAPACITYCACHE_H_
+#define SRC_CLIENT_CACHE_CAPACITYCACHE_H_
+
+#include <list>
+#include <map>
+
+#include <cache/CacheInterface.h>
+
+namespace Cynara {
+
+class CapacityCache : public PluginCache {
+public:
+ static const std::size_t CACHE_DEFAULT_CAPACITY = 10000;
+
+ CapacityCache(ResultGetterInterfacePtr getter,
+ std::size_t capacity = CACHE_DEFAULT_CAPACITY) :
+ PluginCache(getter),
+ m_capacity(capacity) {}
+
+ cynara_api_result get(const std::string &session,
+ const PolicyKey &key);
+ void clear(void);
+
+private:
+ typedef std::list<std::string> KeyUsageList;
+ typedef std::map<std::string,
+ std::pair<PolicyResult,
+ KeyUsageList::iterator>> KeyValueMap;
+
+ static std::string keyToString(const PolicyKey &key);
+ void evict(void);
+ cynara_api_result update(const PolicyKey &key);
+
+ std::size_t m_capacity;
+ std::string m_session;
+
+ KeyUsageList m_keyUsage;
+ KeyValueMap m_keyValue;
+};
+
+} //namespace Cynara
+
+#endif // SRC_CLIENT_CACHE_CAPACITYCACHE_H_
+
+
+
+
--- /dev/null
+/*
+ * 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 NaiveInterpreter.h
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @version 1.0
+ * @brief This file contains PolicyType naive interpreter implementation.
+ */
+#ifndef SRC_CLIENT_CACHE_NAIVEINTERPRETER_H_
+#define SRC_CLIENT_CACHE_NAIVEINTERPRETER_H_
+
+#include <attributes/attributes.h>
+#include <cache/CacheInterface.h>
+
+namespace Cynara {
+
+class NaiveInterpreter : public InterpreterInterface {
+ bool isUsable(const PolicyResult &result UNUSED) noexcept {
+ return true;
+ }
+ bool isCacheable(const PolicyResult &result UNUSED) noexcept {
+ return true;
+ }
+ cynara_api_result toResult(const PolicyResult &result) noexcept {
+ if (result.policyType() == PredefinedPolicyType::ALLOW)
+ return cynara_api_result::CYNARA_API_SUCCESS;
+ else
+ return cynara_api_result::CYNARA_API_ACCESS_DENIED;
+ }
+};
+
+} // namespace Cynara
+
+#endif // SRC_CLIENT_CACHE_NAIVEINTERPRETER_H_
+
+
+++ /dev/null
-/*
- * 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 NoCache.cpp
- * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
- * @version 1.0
- * @brief This file contains implementation of NoCache class - stub for no-cache version
- */
-
-#include <common.h>
-#include <types/PolicyType.h>
-
-#include "NoCache.h"
-
-namespace Cynara {
-
-cynara_api_result NoCache::updateAndCheck(const std::string &session UNUSED,
- const PolicyKey &key UNUSED,
- const PolicyResult &result) {
- if (result.policyType() == PredefinedPolicyType::ALLOW)
- return cynara_api_result::CYNARA_API_SUCCESS;
- else
- return cynara_api_result::CYNARA_API_ACCESS_DENIED;
-}
-
-} // namespace Cynara
+++ /dev/null
-/*
- * 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 NoCache.h
- * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
- * @version 1.0
- * @brief This file contains definition of NoCache class - stub for no-cache version
- */
-
-#ifndef SRC_CLIENT_CACHE_NOCACHE_H_
-#define SRC_CLIENT_CACHE_NOCACHE_H_
-
-#include <string.h>
-
-#include <common.h>
-#include <types/PolicyKey.h>
-#include <types/PolicyResult.h>
-
-#include <cache/CacheInterface.h>
-#include <cynara-client.h>
-
-namespace Cynara {
-
-class NoCache : public CacheInterface {
-public:
- NoCache() = default;
- virtual ~NoCache() = default;
-
- virtual cynara_api_result check(const std::string &session UNUSED,
- const PolicyKey &key UNUSED) {
- return cynara_api_result::CYNARA_API_SERVICE_NOT_AVAILABLE;
- }
-
- virtual cynara_api_result updateAndCheck(const std::string &session, const PolicyKey &key,
- const PolicyResult &result);
-
- virtual void clear(void) {
- }
-};
-
-} // namespace Cynara
-
-#endif /* SRC_CLIENT_CACHE_NOCACHE_H_ */
--- /dev/null
+/*
+ * 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 PolicyGetter.cpp
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @version 1.0
+ * @brief This file contains PolicyResult getter class implementation.
+ */
+
+#include <cinttypes>
+
+#include <exceptions/ServerConnectionErrorException.h>
+#include <log/log.h>
+#include <request/CheckRequest.h>
+#include <request/pointers.h>
+#include <response/CheckResponse.h>
+#include <response/pointers.h>
+
+#include <cache/PolicyGetter.h>
+
+namespace Cynara {
+
+cynara_api_result PolicyGetter::requestResult(const PolicyKey &key, PolicyResult &result) noexcept {
+ ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber();
+
+ //Ask cynara service
+ CheckResponsePtr checkResponse;
+ try {
+ RequestPtr request = std::make_shared<CheckRequest>(key, sequenceNumber);
+ ResponsePtr response = m_socketClient->askCynaraServer(request);
+ if (!response) {
+ LOGW("Disconnected by cynara server.");
+ return cynara_api_result::CYNARA_API_SERVICE_NOT_AVAILABLE;
+ }
+ checkResponse = std::dynamic_pointer_cast<CheckResponse>(response);
+ if (!checkResponse) {
+ LOGC("Critical error. Casting Response to CheckResponse failed.");
+ return cynara_api_result::CYNARA_API_ACCESS_DENIED;
+ }
+
+ LOGD("checkResponse: policyType = %" PRIu16 ", metadata = %s",
+ checkResponse->m_resultRef.policyType(),
+ checkResponse->m_resultRef.metadata().c_str());
+ } catch (const ServerConnectionErrorException &ex) {
+ LOGE("Cynara service not available.");
+ return cynara_api_result::CYNARA_API_SERVICE_NOT_AVAILABLE;
+ }
+
+ result = checkResponse->m_resultRef;
+ return cynara_api_result::CYNARA_API_SUCCESS;
+}
+
+} // namespace Cynara
--- /dev/null
+/*
+ * 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 PolicyGetter.h
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @version 1.0
+ * @brief This file contains Cynara PolicyResult getter implementation.
+ */
+
+#ifndef SRC_CLIENT_CACHE_POLICYGETTER_H_
+#define SRC_CLIENT_CACHE_POLICYGETTER_H_
+
+#include <log/log.h>
+
+#include <cache/CacheInterface.h>
+#include <sockets/SocketClient.h>
+
+
+namespace Cynara {
+
+class PolicyGetter : public ResultGetterInterface {
+public:
+ PolicyGetter(const SocketClientPtr &socketClient) : m_socketClient(socketClient) {}
+ cynara_api_result requestResult(const PolicyKey &key, PolicyResult &result) noexcept;
+
+private:
+ ProtocolFrameSequenceNumber generateSequenceNumber(void) {
+ static ProtocolFrameSequenceNumber sequenceNumber = 0;
+ return ++sequenceNumber;
+ }
+
+ SocketClientPtr m_socketClient;
+};
+
+} //namespace Cynara
+
+#endif // SRC_CLIENT_CACHE_POLICYGETTER_H_
+
+
+
+
#include <memory>
#include <common.h>
-#include <exceptions/ServerConnectionErrorException.h>
-#include <exceptions/UnexpectedErrorException.h>
-#include <log/log.h>
#include <protocol/Protocol.h>
#include <protocol/ProtocolClient.h>
-#include <request/CheckRequest.h>
-#include <request/pointers.h>
-#include <response/CheckResponse.h>
-#include <response/pointers.h>
#include <sockets/SocketClient.h>
#include <types/PolicyKey.h>
-#include <types/PolicyResult.h>
-#include <cache/NoCache.h>
+#include <cache/CapacityCache.h>
+#include <cache/NaiveInterpreter.h>
+#include <cache/PolicyGetter.h>
#include "Logic.h"
namespace Cynara {
const std::string clientSocketPath("/run/cynara/cynara.socket");
Logic::Logic() {
- m_socketClient = std::make_shared<SocketClient>(clientSocketPath,
- std::make_shared<ProtocolClient>());
- m_cache = std::make_shared<NoCache>();
+ m_cache = std::make_shared<CapacityCache>(
+ std::make_shared<PolicyGetter>(
+ std::make_shared<SocketClient>(clientSocketPath,
+ std::make_shared<ProtocolClient>())));
+ auto naiveInterpreter = std::make_shared<NaiveInterpreter>();
+ m_cache->registerPlugin(PredefinedPolicyType::ALLOW, naiveInterpreter);
+ m_cache->registerPlugin(PredefinedPolicyType::DENY, naiveInterpreter);
+ m_cache->registerPlugin(PredefinedPolicyType::BUCKET, naiveInterpreter);
}
-ProtocolFrameSequenceNumber generateSequenceNumber(void) {
- static ProtocolFrameSequenceNumber sequenceNumber = 0;
- return ++sequenceNumber;
-}
-
-cynara_api_result Logic::check(const std::string &client, const std::string &session UNUSED,
+cynara_api_result Logic::check(const std::string &client, const std::string &session,
const std::string &user, const std::string &privilege) noexcept
{
PolicyKey key(client, user, privilege);
- auto cacheResponse = m_cache->check(session, key);
- if(cacheResponse != cynara_api_result::CYNARA_API_SERVICE_NOT_AVAILABLE)
- return cacheResponse;
-
- ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber();
-
- //Ask cynara service
- CheckResponsePtr checkResponse;
- try {
- RequestPtr request = std::make_shared<CheckRequest>(key, sequenceNumber);
- ResponsePtr response = m_socketClient->askCynaraServer(request);
- if (!response) {
- LOGW("Disconnected by cynara server.");
- onDisconnected();
- return cynara_api_result::CYNARA_API_SERVICE_NOT_AVAILABLE;
- }
- checkResponse = std::dynamic_pointer_cast<CheckResponse>(response);
- if (!checkResponse) {
- LOGC("Critical error. Casting Response to CheckResponse failed.");
- throw UnexpectedErrorException("Error casting Response to CheckResponse");
- }
-
- LOGD("checkResponse: policyType = %d, metadata = %s",
- (int)checkResponse->m_resultRef.policyType(),
- checkResponse->m_resultRef.metadata().c_str());
- } catch (const ServerConnectionErrorException &ex) {
- LOGE("Cynara service not available.");
+ auto ret = m_cache->get(session, key);
+ if (ret == cynara_api_result::CYNARA_API_SERVICE_NOT_AVAILABLE)
onDisconnected();
- return cynara_api_result::CYNARA_API_SERVICE_NOT_AVAILABLE;
- } catch (const std::exception &ex) {
- LOGE("Error during check of privilege: %s", ex.what());
- return cynara_api_result::CYNARA_API_ACCESS_DENIED;
- }
-
- return m_cache->updateAndCheck(session, key, checkResponse->m_resultRef);
+ return ret;
}
void Logic::onDisconnected(void) {
#include <string>
-#include <sockets/SocketClient.h>
-
#include <api/ApiInterface.h>
#include <cache/CacheInterface.h>
class Logic : public ApiInterface {
private:
- SocketClientPtr m_socketClient;
- CacheInterfacePtr m_cache;
+ PluginCachePtr m_cache;
void onDisconnected(void);
typedef std::string PolicyMetadata;
public:
+ PolicyResult() : m_type(PredefinedPolicyType::DENY) {}
PolicyResult(const PolicyType &policyType) : m_type(policyType) {}
PolicyResult(const PolicyType &policyType, const PolicyMetadata &metadata)
: m_type(policyType), m_metadata(metadata) {}