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/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);