Serialize the config objects

This commit serializes the config object into cereal
path and restores the config object when the phosphor-ldap-conf
restarts.

TestedBy: Unit tested
          Serialize the object
          Restart the phosphor-ldap-conf restores the object.
          Ldap/Local authentication works fine.

Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
Change-Id: Ie6e940ddd6851085dc4213677dfb20e3afa0964f
diff --git a/configure.ac b/configure.ac
index 6813056..72acd4a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -85,7 +85,7 @@
 
 AC_ARG_VAR(LDAP_CONF_PERSIST_PATH, [directory path to persist LDAP enabled property.])
 AS_IF([test "x$LDAP_CONF_PERSIST_PATH" == "x"], \
-    [LDAP_CONF_PERSIST_PATH="/var/lib/phosphor-user-manager/ldap/conf"])
+    [LDAP_CONF_PERSIST_PATH="/var/lib/phosphor-ldap-conf"])
 AC_DEFINE_UNQUOTED([LDAP_CONF_PERSIST_PATH], ["$LDAP_CONF_PERSIST_PATH"], \
     [path of directory having persisted LDAP configuration enabled property.])
 
diff --git a/phosphor-ldap-config/Makefile.am b/phosphor-ldap-config/Makefile.am
index 7080ac5..3052b6d 100644
--- a/phosphor-ldap-config/Makefile.am
+++ b/phosphor-ldap-config/Makefile.am
@@ -9,8 +9,7 @@
                 main.cpp \
                 utils.cpp \
                 ldap_config.cpp \
-                ldap_config_mgr.cpp \
-                ldap_config_serialize.cpp
+                ldap_config_mgr.cpp
 
 phosphor_ldap_conf_LDFLAGS = $(SDBUSPLUS_LIBS) \
                              $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
diff --git a/phosphor-ldap-config/ldap_config.cpp b/phosphor-ldap-config/ldap_config.cpp
index 746f324..126cc46 100644
--- a/phosphor-ldap-config/ldap_config.cpp
+++ b/phosphor-ldap-config/ldap_config.cpp
@@ -1,11 +1,19 @@
 #include "ldap_config_mgr.hpp"
 #include "ldap_config.hpp"
-#include "ldap_config_serialize.hpp"
 #include "utils.hpp"
+
+#include <cereal/types/string.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/archives/binary.hpp>
 #include <filesystem>
 #include <fstream>
 #include <sstream>
 
+// Register class version
+// From cereal documentation;
+// "This macro should be placed at global scope"
+CEREAL_CLASS_VERSION(phosphor::ldap::Config, CLASS_VERSION);
+
 namespace phosphor
 {
 namespace ldap
@@ -38,8 +46,8 @@
                ConfigMgr& parent) :
     Ifaces(bus, path, true),
     secureLDAP(secureLDAP), lDAPBindPassword(std::move(lDAPBindDNPassword)),
-    configFilePath(filePath), tlsCacertFile(caCertFile), bus(bus),
-    parent(parent)
+    tlsCacertFile(caCertFile), configFilePath(filePath), objectPath(path),
+    bus(bus), parent(parent)
 {
     ConfigIface::lDAPServerURI(lDAPServerURI);
     ConfigIface::lDAPBindDN(lDAPBindDN);
@@ -49,16 +57,57 @@
     EnableIface::enabled(lDAPServiceEnabled);
     ConfigIface::userNameAttribute(userNameAttr);
     ConfigIface::groupNameAttribute(groupNameAttr);
-    // Don't update the bindDN password under ConfigIface::
+    // NOTE: Don't update the bindDN password under ConfigIface
     if (enabled())
     {
         writeConfig();
     }
+    // save the config.
+    configPersistPath = parent.dbusPersistentPath;
+    configPersistPath += objectPath;
+
+    // create the persistent directory
+    fs::create_directories(configPersistPath);
+
+    configPersistPath += "/config";
+
+    std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
+    // remove the read permission from others
+    auto permission =
+        fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
+    fs::permissions(configPersistPath, permission);
+
+    serialize();
+
     // Emit deferred signal.
     this->emit_object_added();
     parent.startOrStopService(nslcdService, enabled());
 }
 
+Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
+               const char* caCertFile, ConfigIface::Type lDAPType,
+               ConfigMgr& parent) :
+    Ifaces(bus, path, true),
+    tlsCacertFile(caCertFile), configFilePath(filePath), objectPath(path),
+    bus(bus), parent(parent)
+{
+    ConfigIface::lDAPType(lDAPType);
+
+    configPersistPath = parent.dbusPersistentPath;
+    configPersistPath += objectPath;
+
+    // create the persistent directory
+    fs::create_directories(configPersistPath);
+
+    configPersistPath += "/config";
+
+    std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
+    // remove the read permission from others
+    auto permission =
+        fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
+    fs::permissions(configPersistPath, permission);
+}
+
 void Config::writeConfig()
 {
     std::stringstream confData;
@@ -195,6 +244,7 @@
             writeConfig();
             parent.startOrStopService(nslcdService, enabled());
         }
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -245,6 +295,8 @@
             writeConfig();
             parent.startOrStopService(nslcdService, enabled());
         }
+        // save the object.
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -290,6 +342,8 @@
             writeConfig();
             parent.startOrStopService(nslcdService, enabled());
         }
+        // save the object.
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -331,6 +385,8 @@
             writeConfig();
             parent.startOrStopService(nslcdService, enabled());
         }
+        // save the object.
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -365,6 +421,8 @@
 
             parent.startOrStopService(nslcdService, enabled());
         }
+        // save the object.
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -401,8 +459,8 @@
         // TODO in later commit, one of the config would be active
         // at any moment of time.
         parent.startOrStopService(nslcdService, value);
-        // save the enabled property.
-        serialize(*this, parent.dbusPersistentPath);
+        // save the object.
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -433,6 +491,8 @@
 
             parent.startOrStopService(nslcdService, enabled());
         }
+        // save the object.
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -463,6 +523,8 @@
 
             parent.startOrStopService(nslcdService, enabled());
         }
+        // save the object.
+        serialize();
     }
     catch (const InternalFailure& e)
     {
@@ -476,5 +538,86 @@
     return val;
 }
 
+template <class Archive>
+void Config::save(Archive& archive, const std::uint32_t version) const
+{
+    archive(this->enabled());
+    archive(lDAPServerURI());
+    archive(lDAPBindDN());
+    archive(lDAPBaseDN());
+    archive(lDAPSearchScope());
+    archive(lDAPBindPassword);
+    archive(userNameAttribute());
+    archive(groupNameAttribute());
+}
+
+template <class Archive>
+void Config::load(Archive& archive, const std::uint32_t version)
+{
+
+    bool bVal;
+    archive(bVal);
+    EnableIface::enabled(bVal);
+
+    std::string str;
+    archive(str);
+    ConfigIface::lDAPServerURI(str);
+
+    archive(str);
+    ConfigIface::lDAPBindDN(str);
+
+    archive(str);
+    ConfigIface::lDAPBaseDN(str);
+
+    ConfigIface::SearchScope scope;
+    archive(scope);
+    ConfigIface::lDAPSearchScope(scope);
+
+    archive(str);
+    lDAPBindPassword = str;
+
+    archive(str);
+    ConfigIface::userNameAttribute(str);
+
+    archive(str);
+    ConfigIface::groupNameAttribute(str);
+}
+
+void Config::serialize()
+{
+    std::ofstream os(configPersistPath.string(),
+                     std::ios::binary | std::ios::out);
+    cereal::BinaryOutputArchive oarchive(os);
+    oarchive(*this);
+    return;
+}
+
+bool Config::deserialize()
+{
+    try
+    {
+        if (fs::exists(configPersistPath))
+        {
+            std::ifstream is(configPersistPath.c_str(),
+                             std::ios::in | std::ios::binary);
+            cereal::BinaryInputArchive iarchive(is);
+            iarchive(*this);
+            return true;
+        }
+        return false;
+    }
+    catch (cereal::Exception& e)
+    {
+        log<level::ERR>(e.what());
+        std::error_code ec;
+        fs::remove(configPersistPath, ec);
+        return false;
+    }
+    catch (const fs::filesystem_error& e)
+    {
+        return false;
+    }
+}
+
 } // namespace ldap
 } // namespace phosphor
diff --git a/phosphor-ldap-config/ldap_config.hpp b/phosphor-ldap-config/ldap_config.hpp
index 858d1a3..6eceb50 100644
--- a/phosphor-ldap-config/ldap_config.hpp
+++ b/phosphor-ldap-config/ldap_config.hpp
@@ -11,6 +11,7 @@
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/server/object.hpp>
 #include <string>
+#include <filesystem>
 
 namespace phosphor
 {
@@ -24,7 +25,7 @@
 using Ifaces = sdbusplus::server::object::object<ConfigIface, EnableIface>;
 using CreateIface = sdbusplus::server::object::object<
     sdbusplus::xyz::openbmc_project::User::Ldap::server::Create>;
-
+namespace fs = std::filesystem;
 class ConfigMgr;
 class MockConfigMgr;
 
@@ -74,6 +75,18 @@
            bool lDAPServiceEnabled, std::string groupNameAttribute,
            std::string userNameAttribute, ConfigMgr& parent);
 
+    /** @brief Constructor to put object onto bus at a D-Bus path.
+     *  @param[in] bus - Bus to attach to.
+     *  @param[in] path - The D-Bus object path to attach at.
+     *  @param[in] filePath - LDAP configuration file.
+     *  @param[in] lDAPType - Specifies the LDAP server type which can be AD
+     *              or openLDAP.
+     *  @param[in] parent - parent of config object.
+     */
+    Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
+           const char* caCertFile, ConfigIface::Type lDAPType,
+           ConfigMgr& parent);
+
     using ConfigIface::groupNameAttribute;
     using ConfigIface::lDAPBaseDN;
     using ConfigIface::lDAPBindDN;
@@ -140,12 +153,43 @@
      */
     std::string lDAPBindDNPassword(std::string value) override;
 
-    bool secureLDAP;
+    /** @brief Function required by Cereal to perform deserialization.
+     *  @tparam Archive - Cereal archive type (binary in our case).
+     *  @param[in] archive - reference to Cereal archive.
+     *  @param[in] version - Class version that enables handling
+     *                       a serialized data across code levels
+     */
+    template <class Archive>
+    void load(Archive& archive, const std::uint32_t version);
+
+    /** @brief Function required by Cereal to perform serialization.
+     *  @tparam Archive - Cereal archive type (binary in our case).
+     *  @param[in] archive - reference to Cereal archive.
+     *  @param[in] version - Class version that enables handling
+     *                       a serialized data across code levels
+     */
+    template <class Archive>
+    void save(Archive& archive, const std::uint32_t version) const;
+
+    /** @brief Serialize and persist this object at the persist
+     *         location.
+     */
+    void serialize();
+
+    /** @brief Deserialize LDAP config data from the persistent location
+     *         into this object
+     *  @return bool - true if the deserialization was successful, false
+     *                 otherwise.
+     */
+    bool deserialize();
 
   private:
+    bool secureLDAP;
     std::string lDAPBindPassword{};
-    std::string configFilePath{};
     std::string tlsCacertFile{};
+    std::string configFilePath{};
+    std::string objectPath{};
+    std::filesystem::path configPersistPath{};
 
     /** @brief Persistent sdbusplus D-Bus bus connection. */
     sdbusplus::bus::bus& bus;
diff --git a/phosphor-ldap-config/ldap_config_mgr.cpp b/phosphor-ldap-config/ldap_config_mgr.cpp
index a60e8f8..65d4bda 100644
--- a/phosphor-ldap-config/ldap_config_mgr.cpp
+++ b/phosphor-ldap-config/ldap_config_mgr.cpp
@@ -1,6 +1,5 @@
 #include "ldap_config_mgr.hpp"
 #include "ldap_config.hpp"
-#include "ldap_config_serialize.hpp"
 
 #include "utils.hpp"
 #include <filesystem>
@@ -73,12 +72,6 @@
     }
 }
 
-void ConfigMgr::deleteObject()
-{
-    // TODO Not needed the delete functionality.
-    // will do in later commit
-}
-
 std::string ConfigMgr::createConfig(
     std::string lDAPServerURI, std::string lDAPBindDN, std::string lDAPBaseDN,
     std::string lDAPBindDNPassword, CreateIface::SearchScope lDAPSearchScope,
@@ -167,17 +160,31 @@
     {
         openLDAPConfigPtr = std::make_unique<Config>(
             bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(),
-            tlsCacertFile.c_str(), false, "", "", "", "",
-            ConfigIface::SearchScope::sub, ConfigIface::Type::OpenLdap, false,
-            "", "", *this);
+            tlsCacertFile.c_str(), ConfigIface::Type::OpenLdap, *this);
+        openLDAPConfigPtr->emit_object_added();
     }
     if (!ADConfigPtr)
     {
         ADConfigPtr = std::make_unique<Config>(
             bus, ADDbusObjectPath.c_str(), configFilePath.c_str(),
-            tlsCacertFile.c_str(), false, "", "", "", "",
-            ConfigIface::SearchScope::sub, ConfigIface::Type::ActiveDirectory,
-            false, "", "", *this);
+            tlsCacertFile.c_str(), ConfigIface::Type::ActiveDirectory, *this);
+        ADConfigPtr->emit_object_added();
+    }
+}
+
+void ConfigMgr::restore()
+{
+    createDefaultObjects();
+    // Restore the ldap config and their mappings
+    if (ADConfigPtr->deserialize())
+    {
+        // Restore the role mappings in later commit
+        ADConfigPtr->emit_object_added();
+    }
+    if (openLDAPConfigPtr->deserialize())
+    {
+        // Restore the role mappings in later commit
+        openLDAPConfigPtr->emit_object_added();
     }
 }
 
diff --git a/phosphor-ldap-config/ldap_config_mgr.hpp b/phosphor-ldap-config/ldap_config_mgr.hpp
index a3895ae..812528b 100644
--- a/phosphor-ldap-config/ldap_config_mgr.hpp
+++ b/phosphor-ldap-config/ldap_config_mgr.hpp
@@ -99,13 +99,9 @@
      */
     virtual void startOrStopService(const std::string& service, bool value);
 
-    /** @brief delete the config D-Bus object.
+    /** @brief Populate existing config into D-Bus properties
      */
-    void deleteObject();
-
-    /* Create the default active directory and the openldap config
-     * objects. */
-    virtual void createDefaultObjects();
+    virtual void restore();
 
     /* ldap service enabled property would be saved under
      * this path.
@@ -130,6 +126,10 @@
     std::unique_ptr<Config> openLDAPConfigPtr = nullptr;
     /** @brief Pointer to a AD Config D-Bus object */
     std::unique_ptr<Config> ADConfigPtr = nullptr;
+
+    /* Create the default active directory and the openldap config
+     * objects. */
+    virtual void createDefaultObjects();
 };
 } // namespace ldap
 } // namespace phosphor
diff --git a/phosphor-ldap-config/ldap_config_serialize.cpp b/phosphor-ldap-config/ldap_config_serialize.cpp
deleted file mode 100644
index 6c80a74..0000000
--- a/phosphor-ldap-config/ldap_config_serialize.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-#include <cereal/types/string.hpp>
-#include <cereal/types/vector.hpp>
-#include <cereal/archives/binary.hpp>
-#include <fstream>
-
-#include "ldap_config_serialize.hpp"
-#include "ldap_config.hpp"
-#include <phosphor-logging/log.hpp>
-#include "config.h"
-
-// Register class version
-// From cereal documentation;
-// "This macro should be placed at global scope"
-CEREAL_CLASS_VERSION(phosphor::ldap::Config, CLASS_VERSION);
-
-namespace phosphor
-{
-namespace ldap
-{
-
-using namespace phosphor::logging;
-
-/** @brief Function required by Cereal to perform serialization.
- *  @tparam Archive - Cereal archive type (binary in our case).
- *  @param[in] archive - reference to Cereal archive.
- *  @param[in] config - const reference to ldap config.
- *  @param[in] version - Class version that enables handling
- *                       a serialized data across code levels
- */
-template <class Archive>
-void save(Archive& archive, const Config& config, const std::uint32_t version)
-{
-    archive(config.enabled());
-}
-
-/** @brief Function required by Cereal to perform deserialization.
- *  @tparam Archive - Cereal archive type (binary in our case).
- *  @param[in] archive - reference to Cereal archive.
- *  @param[in] config -  reference of ldap config object.
- *  @param[in] version - Class version that enables handling
- *                       a serialized data across code levels
- */
-template <class Archive>
-void load(Archive& archive, Config& config, const std::uint32_t version)
-{
-    bool enabled = false;
-    archive(enabled);
-    config.enabled(enabled);
-}
-
-fs::path serialize(const Config& config, const fs::path& path)
-{
-    fs::create_directories(path.parent_path());
-
-    std::ofstream os(path.string(), std::ios::binary);
-    cereal::BinaryOutputArchive oarchive(os);
-    oarchive(config);
-    return path;
-}
-
-bool deserialize(const fs::path& path, Config& config)
-{
-    try
-    {
-        if (fs::exists(path))
-        {
-            std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
-            cereal::BinaryInputArchive iarchive(is);
-            iarchive(config);
-            return true;
-        }
-        return false;
-    }
-    catch (cereal::Exception& e)
-    {
-        log<level::ERR>(e.what());
-        std::error_code ec;
-        fs::remove(path, ec);
-        return false;
-    }
-    catch (const fs::filesystem_error& e)
-    {
-        return false;
-    }
-}
-
-} // namespace ldap
-} // namespace phosphor
diff --git a/phosphor-ldap-config/ldap_config_serialize.hpp b/phosphor-ldap-config/ldap_config_serialize.hpp
deleted file mode 100644
index b20ccd4..0000000
--- a/phosphor-ldap-config/ldap_config_serialize.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include <filesystem>
-#include "ldap_config.hpp"
-
-namespace phosphor
-{
-namespace ldap
-{
-
-namespace fs = std::filesystem;
-
-/** @brief Serialize and persist LDAP service status property.
- *  @param[in] config - const reference to LDAP config object.
- *  @param[in] path -  path of persistent location where D-Bus property would be
- *                     saved.
- *  @return fs::path - pathname of persisted LDAP Config file.
- */
-fs::path serialize(const Config& config, const fs::path& path);
-
-/** @brief Deserialize LDAP service status into a D-Bus object
- *  @param[in] path - pathname of persisted LDAP Config file.
- *  @param[in] config - reference of the object which needs to be deserialized.
- *  @return bool - true if the deserialization was successful, false otherwise.
- */
-bool deserialize(const fs::path& path, Config& config);
-
-} // namespace ldap
-} // namespace phosphor
diff --git a/phosphor-ldap-config/main.cpp b/phosphor-ldap-config/main.cpp
index e0ac638..3a2d5f5 100644
--- a/phosphor-ldap-config/main.cpp
+++ b/phosphor-ldap-config/main.cpp
@@ -27,7 +27,7 @@
 
     phosphor::ldap::ConfigMgr mgr(bus, LDAP_CONFIG_ROOT, LDAP_CONFIG_FILE,
                                   LDAP_CONF_PERSIST_PATH, TLS_CACERT_FILE);
-    mgr.createDefaultObjects();
+    mgr.restore();
 
     bus.request_name(LDAP_CONFIG_BUSNAME);
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 581b1eb..9d11428 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -30,7 +30,6 @@
 ldap_config_test_SOURCES  = ldap_config_test.cpp utils_test.cpp
 ldap_config_test_LDADD  = $(top_builddir)/phosphor-ldap-config/ldap_config.o \
                           $(top_builddir)/phosphor-ldap-config/utils.o \
-                          $(top_builddir)/phosphor-ldap-config/ldap_config_serialize.o \
                           $(top_builddir)/phosphor-ldap-config/ldap_config_mgr.o
 
 check_PROGRAMS += ldap_mapper_test
diff --git a/test/ldap_config_test.cpp b/test/ldap_config_test.cpp
index cd06bf8..1e0171d 100644
--- a/test/ldap_config_test.cpp
+++ b/test/ldap_config_test.cpp
@@ -1,7 +1,6 @@
 #include "config.h"
 #include "phosphor-ldap-config/ldap_config.hpp"
 #include "phosphor-ldap-config/ldap_config_mgr.hpp"
-#include "phosphor-ldap-config/ldap_config_serialize.hpp"
 
 #include <phosphor-logging/log.hpp>
 #include <phosphor-logging/elog-errors.hpp>
@@ -87,8 +86,7 @@
     }
     void restore()
     {
-        // TODO enable it in later commit.
-        // phosphor::ldap::ConfigMgr::restore();
+        phosphor::ldap::ConfigMgr::restore();
         return;
     }
 
@@ -104,8 +102,7 @@
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -119,6 +116,7 @@
     EXPECT_CALL(manager, stopService("nslcd.service")).Times(2);
     EXPECT_CALL(manager, restartService("nslcd.service")).Times(2);
     EXPECT_CALL(manager, restartService("nscd.service")).Times(2);
+
     manager.createConfig(
         "ldap://9.194.251.136/", "cn=Users,dc=com", "cn=Users,dc=corp",
         "MyLdap12", ldap_base::Create::SearchScope::sub,
@@ -163,8 +161,7 @@
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -176,8 +173,6 @@
                           dbusPersistentFilePath.c_str(),
                           tlsCacertfile.c_str());
 
-    EXPECT_CALL(manager, stopService("nslcd.service")).Times(2);
-
     manager.createDefaultObjects();
 
     EXPECT_NE(nullptr, manager.getADConfigPtr());
@@ -187,13 +182,12 @@
     EXPECT_EQ(manager.getOpenLdapConfigPtr()->lDAPType(),
               ldap_base::Config::Type::OpenLdap);
 }
-/*
+
 TEST_F(TestLDAPConfig, testRestores)
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -203,35 +197,34 @@
     MockConfigMgr* managerPtr = new MockConfigMgr(
         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
-    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
-    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1);
     managerPtr->createConfig(
         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
         "MyLdap12", ldap_base::Create::SearchScope::sub,
         ldap_base::Create::Type::ActiveDirectory, "uid", "gid");
-    managerPtr->getConfigPtr()->enabled(false);
+    managerPtr->getADConfigPtr()->enabled(false);
+    EXPECT_FALSE(fs::exists(configFilePath));
+    EXPECT_FALSE(managerPtr->getADConfigPtr()->enabled());
+    managerPtr->getADConfigPtr()->enabled(true);
 
     EXPECT_TRUE(fs::exists(configFilePath));
-    EXPECT_FALSE(managerPtr->getConfigPtr()->enabled());
-    managerPtr->getConfigPtr()->enabled(true);
-    // Delete LDAP configuration
-    managerPtr->deleteObject();
-    EXPECT_TRUE(fs::exists(configFilePath));
     // Restore from configFilePath
-    managerPtr->restore(configFilePath.c_str());
+    managerPtr->restore();
     // validate restored properties
-    EXPECT_TRUE(managerPtr->getConfigPtr()->enabled());
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
+    EXPECT_TRUE(managerPtr->getADConfigPtr()->enabled());
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(),
               "ldap://9.194.251.138/");
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDN(), "cn=Users,dc=com");
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBaseDN(), "cn=Users,dc=corp");
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPSearchScope(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDN(), "cn=Users,dc=com");
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBaseDN(), "cn=Users,dc=corp");
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPSearchScope(),
               ldap_base::Config::SearchScope::sub);
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPType(),
               ldap_base::Config::Type::ActiveDirectory);
-    EXPECT_EQ(managerPtr->getConfigPtr()->userNameAttribute(), "uid");
-    EXPECT_EQ(managerPtr->getConfigPtr()->groupNameAttribute(), "gid");
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDNPassword(), "");
+    EXPECT_EQ(managerPtr->getADConfigPtr()->userNameAttribute(), "uid");
+    EXPECT_EQ(managerPtr->getADConfigPtr()->groupNameAttribute(), "gid");
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDNPassword(), "");
     EXPECT_EQ(managerPtr->configBindPassword(), "MyLdap12");
     delete managerPtr;
 }
@@ -240,8 +233,7 @@
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -251,31 +243,34 @@
     MockConfigMgr* managerPtr = new MockConfigMgr(
         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
-    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
-    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
+
+    EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1);
 
     managerPtr->createConfig(
         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
         "MyLdap12", ldap_base::Create::SearchScope::sub,
         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
-    managerPtr->getConfigPtr()->enabled(true);
+    managerPtr->getADConfigPtr()->enabled(true);
 
     // Change LDAP Server URI
-    managerPtr->getConfigPtr()->lDAPServerURI("ldap://9.194.251.139/");
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
+    managerPtr->getADConfigPtr()->lDAPServerURI("ldap://9.194.251.139/");
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(),
               "ldap://9.194.251.139/");
-    // Change LDAP Server URI
+
+    // Change LDAP Server URI to make it secure
     EXPECT_THROW(
-        managerPtr->getConfigPtr()->lDAPServerURI("ldaps://9.194.251.139/"),
+        managerPtr->getADConfigPtr()->lDAPServerURI("ldaps://9.194.251.139/"),
         NoCACertificate);
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
-              "ldap://9.194.251.139/");
-    // Delete LDAP configuration
-    managerPtr->deleteObject();
 
-    managerPtr->restore(configFilePath.c_str());
+    // check once again
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(),
+              "ldap://9.194.251.139/");
+
+    managerPtr->restore();
     // Check LDAP Server URI
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(),
               "ldap://9.194.251.139/");
     delete managerPtr;
 }
@@ -284,8 +279,7 @@
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -295,26 +289,28 @@
     MockConfigMgr* managerPtr = new MockConfigMgr(
         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
-    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
-    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
+
+    EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1);
 
     managerPtr->createConfig(
         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
         "MyLdap12", ldap_base::Create::SearchScope::sub,
         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
-    managerPtr->getConfigPtr()->enabled(true);
+    managerPtr->getADConfigPtr()->enabled(true);
 
     // Change LDAP BindDN
-    managerPtr->getConfigPtr()->lDAPBindDN(
+    managerPtr->getADConfigPtr()->lDAPBindDN(
         "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDN(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDN(),
               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
     // Change LDAP BindDN
     EXPECT_THROW(
         {
             try
             {
-                managerPtr->getConfigPtr()->lDAPBindDN("");
+                managerPtr->getADConfigPtr()->lDAPBindDN("");
             }
             catch (const InvalidArgument& e)
             {
@@ -322,12 +318,10 @@
             }
         },
         InvalidArgument);
-    // Delete LDAP configuration
-    managerPtr->deleteObject();
 
-    managerPtr->restore(configFilePath.c_str());
+    managerPtr->restore();
     // Check LDAP BindDN after restoring
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDN(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDN(),
               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
     delete managerPtr;
 }
@@ -336,8 +330,7 @@
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -347,24 +340,25 @@
     MockConfigMgr* managerPtr = new MockConfigMgr(
         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
-    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
-    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1);
     managerPtr->createConfig(
         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
         "MyLdap12", ldap_base::Create::SearchScope::sub,
         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
-    managerPtr->getConfigPtr()->enabled(true);
+    managerPtr->getADConfigPtr()->enabled(true);
     // Change LDAP BaseDN
-    managerPtr->getConfigPtr()->lDAPBaseDN(
+    managerPtr->getADConfigPtr()->lDAPBaseDN(
         "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBaseDN(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBaseDN(),
               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
     // Change LDAP BaseDN
     EXPECT_THROW(
         {
             try
             {
-                managerPtr->getConfigPtr()->lDAPBaseDN("");
+                managerPtr->getADConfigPtr()->lDAPBaseDN("");
             }
             catch (const InvalidArgument& e)
             {
@@ -372,12 +366,10 @@
             }
         },
         InvalidArgument);
-    // Delete LDAP configuration
-    managerPtr->deleteObject();
 
-    managerPtr->restore(configFilePath.c_str());
+    managerPtr->restore();
     // Check LDAP BaseDN after restoring
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBaseDN(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBaseDN(),
               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
     delete managerPtr;
 }
@@ -386,8 +378,7 @@
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -397,25 +388,24 @@
     MockConfigMgr* managerPtr = new MockConfigMgr(
         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
-    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
-    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1);
     managerPtr->createConfig(
         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
         "MyLdap12", ldap_base::Create::SearchScope::sub,
         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
-    managerPtr->getConfigPtr()->enabled(true);
+    managerPtr->getADConfigPtr()->enabled(true);
 
     // Change LDAP SearchScope
-    managerPtr->getConfigPtr()->lDAPSearchScope(
+    managerPtr->getADConfigPtr()->lDAPSearchScope(
         ldap_base::Config::SearchScope::one);
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPSearchScope(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPSearchScope(),
               ldap_base::Config::SearchScope::one);
-    // Delete LDAP configuration
-    managerPtr->deleteObject();
 
-    managerPtr->restore(configFilePath.c_str());
+    managerPtr->restore();
     // Check LDAP SearchScope after restoring
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPSearchScope(),
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPSearchScope(),
               ldap_base::Config::SearchScope::one);
     delete managerPtr;
 }
@@ -424,8 +414,7 @@
 {
     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
-    auto dbusPersistentFilePath =
-        std::string(dir.c_str()) + "/" + dbusPersistFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
 
     if (fs::exists(configFilePath))
     {
@@ -435,27 +424,64 @@
     MockConfigMgr* managerPtr = new MockConfigMgr(
         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
-    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
-    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
+    EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1);
     managerPtr->createConfig(
         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
         "MyLdap12", ldap_base::Create::SearchScope::sub,
         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
-    managerPtr->getConfigPtr()->enabled(true);
+    managerPtr->getADConfigPtr()->enabled(true);
 
     // Change LDAP type
-    managerPtr->getConfigPtr()->lDAPType(ldap_base::Config::Type::OpenLdap);
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
-              ldap_base::Config::Type::OpenLdap);
-    // Delete LDAP configuration
-    managerPtr->deleteObject();
+    // will not be changed
+    EXPECT_THROW(managerPtr->getADConfigPtr()->lDAPType(
+                     ldap_base::Config::Type::OpenLdap),
+                 NotAllowed);
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPType(),
+              ldap_base::Config::Type::ActiveDirectory);
 
-    managerPtr->restore(configFilePath.c_str());
+    managerPtr->restore();
     // Check LDAP type after restoring
-    EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
-              ldap_base::Config::Type::OpenLdap);
+    EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPType(),
+              ldap_base::Config::Type::ActiveDirectory);
     delete managerPtr;
 }
-*/
+
+TEST_F(TestLDAPConfig, filePermission)
+{
+    auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
+    auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
+    auto dbusPersistentFilePath = std::string(dir.c_str());
+
+    if (fs::exists(configFilePath))
+    {
+        fs::remove(configFilePath);
+    }
+    EXPECT_FALSE(fs::exists(configFilePath));
+    MockConfigMgr* managerPtr = new MockConfigMgr(
+        bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
+        dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
+    EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(1);
+    EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1);
+    managerPtr->createConfig(
+        "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
+        "MyLdap12", ldap_base::Create::SearchScope::sub,
+        ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
+    managerPtr->getADConfigPtr()->enabled(true);
+
+    // Permission of the persistent file should be 640
+    // Others should not be allowed to read.
+    auto permission =
+        fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
+    auto persistFilepath = std::string(dir.c_str());
+    persistFilepath += ADDbusObjectPath;
+    persistFilepath += "/config";
+
+    EXPECT_EQ(fs::status(persistFilepath).permissions(), permission);
+    delete managerPtr;
+}
+
 } // namespace ldap
 } // namespace phosphor