Common logging setup for client and service
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 29 Jan 2015 17:12:01 +0000 (18:12 +0100)
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Tue, 17 Feb 2015 11:12:22 +0000 (12:12 +0100)
[Issue#] N/A
[Feature/Bug] N/A
[Problem] Client may use different logging method than service.
[Cause] Service reads environment flags from config file. Client doesn't
[Solution] Make the client read that file too and setup log system properly.

[Verification] Make changes to /etc/sysconfig/central-key-manager file and see
if both service and client uses the same logging setup (provider and log level)
File format is the following:
"
CKM_LOG_PROVIDER=<provider>
CKM_LOG_LEVEL=<level>
"
where:
<provider> is one of JOURNALD, DLOG, CONSOLE
<level> is <0..5>, 0 means not logs at all, 1 means errors only, 5 means all

Change-Id: I1662fe636f9987778345f8a02afa6fb77f7f1fe0

CMakeLists.txt
packaging/key-manager.spec
src/manager/CMakeLists.txt
src/manager/client/client-common.cpp
src/manager/common/log-setup.cpp [new file with mode: 0644]
src/manager/common/log-setup.h [new file with mode: 0644]
src/manager/dpl/log/include/dpl/log/log.h
src/manager/dpl/log/src/log.cpp
systemd/CMakeLists.txt
systemd/central-key-manager.service.in [moved from systemd/central-key-manager.service with 85% similarity]

index 45962b9..f10a0db 100644 (file)
@@ -65,6 +65,10 @@ ELSE (DEFINED SECURITY_MDFPP_STATE_ENABLE)
     MESSAGE("SECURITY_MDFPP_STATE_ENABLE DISABLED !")
 ENDIF (DEFINED SECURITY_MDFPP_STATE_ENABLE)
 
+IF (DEFINED SYSTEMD_ENV_FILE)
+    ADD_DEFINITIONS(-DSYSTEMD_ENV_FILE="${SYSTEMD_ENV_FILE}")
+ENDIF (DEFINED SYSTEMD_ENV_FILE)
+
 SET(TARGET_KEY_MANAGER "key-manager")
 SET(TARGET_KEY_MANAGER_CLIENT "key-manager-client")
 SET(TARGET_KEY_MANAGER_CONTROL_CLIENT "key-manager-control-client")
index 5f6571c..0a49d11 100644 (file)
@@ -102,7 +102,9 @@ export LDFLAGS+="-Wl,--rpath=%{_libdir} "
 %if "%{sec_product_feature_security_mdfpp_enable}" == "1"
         -DSECURITY_MDFPP_STATE_ENABLE=1 \
 %endif
-        -DSYSTEMD_UNIT_DIR=%{_unitdir}
+        -DSYSTEMD_UNIT_DIR=%{_unitdir} \
+        -DSYSTEMD_ENV_FILE="/etc/sysconfig/central-key-manager"
+
 make %{?jobs:-j%jobs}
 
 %install
index 3daf79f..a84dce3 100644 (file)
@@ -20,6 +20,7 @@ SET(COMMON_SOURCES
     ${COMMON_PATH}/common/certificate-impl.cpp
     ${COMMON_PATH}/common/key-impl.cpp
     ${COMMON_PATH}/common/pkcs12-impl.cpp
+    ${COMMON_PATH}/common/log-setup.cpp
     ${COMMON_PATH}/dpl/log/src/abstract_log_provider.cpp
     ${COMMON_PATH}/dpl/log/src/dlog_log_provider.cpp
     ${COMMON_PATH}/dpl/log/src/log.cpp
index 514d104..dc30609 100644 (file)
@@ -34,6 +34,7 @@
 #include <dpl/singleton.h>
 
 #include <message-buffer.h>
+#include <log-setup.h>
 
 #include <ckm/ckm-error.h>
 #include <ckmc/ckmc-type.h>
@@ -44,10 +45,6 @@ namespace {
 
 const int POLL_TIMEOUT = 600000;
 
-void centKeyClientEnableLogSystem(void) {
-    CKM::Singleton<CKM::Log::LogSystem>::Instance().SetTag("CKM_CLIENT");
-}
-
 } // namespace anonymous
 
 namespace CKM {
@@ -353,7 +350,7 @@ void try_catch_async(const std::function<void()>& func, const std::function<void
 static void init_lib(void) __attribute__ ((constructor));
 static void init_lib(void)
 {
-    centKeyClientEnableLogSystem();
+    CKM::SetupClientLogSystem();
 }
 
 static void fini_lib(void) __attribute__ ((destructor));
diff --git a/src/manager/common/log-setup.cpp b/src/manager/common/log-setup.cpp
new file mode 100644 (file)
index 0000000..ec99499
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       log-setup.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <log-setup.h>
+#include <fstream>
+#include <dpl/log/log.h>
+#include <stdexcept>
+
+namespace CKM {
+
+namespace {
+
+const std::string PROVIDER_MATCH("CKM_LOG_PROVIDER=");
+const std::string LEVEL_MATCH("CKM_LOG_LEVEL=");
+
+// see the explanation in SetupClientLogSystem() function
+bool logSystemReady = false;
+
+/*
+ * Reads central-key-manager service environment file. This configuration may be later applied to
+ * client so that it uses the same logging method.
+ */
+class EnvFileParser
+{
+public:
+    EnvFileParser();
+    virtual ~EnvFileParser() {}
+
+    std::string getProvider() const { return m_provider; }
+    std::string getLevel() const { return m_level; }
+
+private:
+    std::string m_provider;
+    std::string m_level;
+};
+
+EnvFileParser::EnvFileParser()
+{
+#ifdef SYSTEMD_ENV_FILE
+    std::ifstream is(SYSTEMD_ENV_FILE);
+    LogDebug("Reading env file: " SYSTEMD_ENV_FILE);
+
+    while(is.good()) {
+        std::string line;
+
+        std::getline(is, line);
+
+        if (0 == line.compare(0, PROVIDER_MATCH.size(), PROVIDER_MATCH)) {
+            m_provider = line.substr(PROVIDER_MATCH.size());
+            LogDebug("Log provider: " << m_provider);
+        }
+        else if (0 == line.compare(0, LEVEL_MATCH.size(), LEVEL_MATCH)) {
+            m_level = line.substr(LEVEL_MATCH.size());
+            LogDebug("Log level: " << m_level);
+        }
+    }
+#else
+    LogWarning("Log configuration file is undefined");
+#endif
+}
+
+} // namespace anonymous
+
+void SetupClientLogSystem()
+{
+    /*
+     * This function is called from library constructors. This will prevent from executing the code
+     * more than once from single binary (because both client libraries use their constructors to
+     * initialize log system). To make it work the code has to be in a common library linked by both
+     * clients.
+     */
+    if (logSystemReady)
+        return;
+
+    CKM::Singleton<CKM::Log::LogSystem>::Instance().SetTag("CKM_CLIENT");
+
+    CKM::EnvFileParser parser;
+    const std::string provider = parser.getProvider();
+    if (!provider.empty()) {
+        try {
+            CKM::Singleton<CKM::Log::LogSystem>::Instance().SelectProvider(provider);
+            // reset tag after changing log provider
+            CKM::Singleton<CKM::Log::LogSystem>::Instance().SetTag("CKM_CLIENT");
+        } catch(const std::out_of_range&) {
+            LogError("Unsupported log provider: " << provider);
+        }
+    }
+    const std::string level = parser.getLevel();
+    if (!level.empty())
+        CKM::Singleton<CKM::Log::LogSystem>::Instance().SetLogLevel(level.c_str());
+
+    logSystemReady = true;
+}
+
+} /* namespace CKM */
diff --git a/src/manager/common/log-setup.h b/src/manager/common/log-setup.h
new file mode 100644 (file)
index 0000000..b78480f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       log-setup.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <string>
+#include <symbol-visibility.h>
+
+namespace CKM {
+
+void COMMON_API SetupClientLogSystem();
+
+} /* namespace CKM */
index ac7f23d..43064a5 100644 (file)
@@ -32,6 +32,7 @@
 
 namespace CKM {
 namespace Log {
+
 /**
  * CKM log system
  */
@@ -68,7 +69,21 @@ class COMMON_API LogSystem
      */
     void RemoveProvider(AbstractLogProvider *provider);
 
+    /**
+     * Selects given provider by name (overwrites environment setting)
+     *
+     * Throws std::out_of_range exception if not found.
+     */
+    void SelectProvider(const std::string& name);
+
+    /**
+     * Sets log level (overwrites environment settings)
+     */
+    void SetLogLevel(const char* level);
+
   private:
+    void RemoveProviders();
+
     typedef std::list<AbstractLogProvider *> AbstractLogProviderPtrList;
     AbstractLogProviderPtrList m_providers;
     AbstractLogProvider::LogLevel m_level;
index 6b5b8a1..d4571e6 100644 (file)
@@ -67,15 +67,7 @@ std::unordered_map<std::string, provider_fn> new_provider = {
 
 LogSystem::LogSystem()
 {
-    try {
-        m_level = static_cast<AbstractLogProvider::LogLevel>(std::stoi(getenv(CKM_LOG_LEVEL)));
-    } catch(const std::exception&) {
-        m_level = AbstractLogProvider::LogLevel::Debug;
-    }
-#ifndef BUILD_TYPE_DEBUG
-    if (m_level > AbstractLogProvider::LogLevel::Error)
-        m_level = AbstractLogProvider::LogLevel::Error;
-#endif // BUILD_TYPE_DEBUG
+    SetLogLevel(getenv(CKM_LOG_LEVEL));
 
     AbstractLogProvider* prv = NULL;
     try {
@@ -88,25 +80,13 @@ LogSystem::LogSystem()
 
 LogSystem::~LogSystem()
 {
-    // Delete all providers
-    for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
-         iterator != m_providers.end();
-         ++iterator)
-    {
-        delete *iterator;
-    }
-
-    m_providers.clear();
+    RemoveProviders();
 }
 
 void LogSystem::SetTag(const char* tag)
 {
-    for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
-         iterator != m_providers.end();
-         ++iterator)
-    {
-        (*iterator)->SetTag(tag);
-    }
+    for (auto it : m_providers)
+        it->SetTag(tag);
 }
 
 void LogSystem::AddProvider(AbstractLogProvider *provider)
@@ -119,6 +99,34 @@ void LogSystem::RemoveProvider(AbstractLogProvider *provider)
     m_providers.remove(provider);
 }
 
+void LogSystem::SelectProvider(const std::string& name)
+{
+    // let it throw
+    provider_fn& prv = new_provider.at(name);
+
+    RemoveProviders();
+    AddProvider(prv());
+}
+
+void LogSystem::SetLogLevel(const char* level)
+{
+    try {
+        m_level = static_cast<AbstractLogProvider::LogLevel>(std::stoi(level));
+    } catch(const std::exception&) {
+        m_level = AbstractLogProvider::LogLevel::Debug;
+    }
+
+    if (m_level < AbstractLogProvider::LogLevel::None)
+        m_level = AbstractLogProvider::LogLevel::None;
+    else if (m_level > AbstractLogProvider::LogLevel::Pedantic)
+        m_level = AbstractLogProvider::LogLevel::Pedantic;
+
+#ifndef BUILD_TYPE_DEBUG
+    if (m_level > AbstractLogProvider::LogLevel::Error)
+        m_level = AbstractLogProvider::LogLevel::Error;
+#endif // BUILD_TYPE_DEBUG
+}
+
 void LogSystem::Log(AbstractLogProvider::LogLevel level,
                     const char *message,
                     const char *filename,
@@ -129,5 +137,14 @@ void LogSystem::Log(AbstractLogProvider::LogLevel level,
         it->Log(level, message, filename, line, function);
 }
 
+void LogSystem::RemoveProviders()
+{
+    // Delete all providers
+    for (auto it : m_providers)
+        delete it;
+
+    m_providers.clear();
 }
+
+} // namespace Log
 } // namespace CKM
index 7886c1d..f9005e7 100644 (file)
@@ -1,3 +1,6 @@
+CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/central-key-manager.service.in
+               ${CMAKE_SOURCE_DIR}/systemd/central-key-manager.service @ONLY)
+
 INSTALL(FILES
     ${CMAKE_SOURCE_DIR}/systemd/central-key-manager.service
     ${CMAKE_SOURCE_DIR}/systemd/central-key-manager.target
similarity index 85%
rename from systemd/central-key-manager.service
rename to systemd/central-key-manager.service.in
index 3b55621..469db7a 100644 (file)
@@ -8,7 +8,7 @@ ExecStart=/usr/bin/key-manager
 Sockets=central-key-manager-api-storage.socket
 Sockets=central-key-manager-api-control.socket
 Sockets=central-key-manager-api-ocsp.socket
-EnvironmentFile=-/etc/sysconfig/central-key-manager
+EnvironmentFile=-@SYSTEMD_ENV_FILE@
 
 [Install]
 WantedBy=multi-user.target