phosphor-ldap-conf: handle "InterfaceAdded" signal on the ldap cert object

When LDAP client certificate is uploaded through install method on the
cert object, Object would emit the signal "InterfaceAdded".
Upon receiving the signal, Config file would be updated with
below given info if secure ldap is enabled:
     tls_cert <path client certificate file>
     tls_key  <path to client certificate file>

Tested By: Unit Tested

Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
Change-Id: I54b3e116af1b8a9057d91797d4074d39efc65bb0
diff --git a/phosphor-ldap-config/ldap_config.cpp b/phosphor-ldap-config/ldap_config.cpp
index b22d684..80b8c9c 100644
--- a/phosphor-ldap-config/ldap_config.cpp
+++ b/phosphor-ldap-config/ldap_config.cpp
@@ -27,6 +27,7 @@
 constexpr auto nscdService = "nscd.service";
 constexpr auto LDAPscheme = "ldap";
 constexpr auto LDAPSscheme = "ldaps";
+constexpr auto certObjPath = "/xyz/openbmc_project/certs/client/ldap";
 
 using namespace phosphor::logging;
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
@@ -44,7 +45,7 @@
 using ConfigInfo = std::map<Key, Val>;
 
 Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
-               const char* caCertFile, bool secureLDAP,
+               const char* caCertFile, const char* certFile, bool secureLDAP,
                std::string lDAPServerURI, std::string lDAPBindDN,
                std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
                ConfigIface::SearchScope lDAPSearchScope,
@@ -53,8 +54,12 @@
                ConfigMgr& parent) :
     Ifaces(bus, path, true),
     secureLDAP(secureLDAP), lDAPBindPassword(std::move(lDAPBindDNPassword)),
-    tlsCacertFile(caCertFile), configFilePath(filePath), objectPath(path),
-    bus(bus), parent(parent)
+    tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
+    objectPath(path), bus(bus), parent(parent),
+    certificateInstalledSignal(
+        bus, sdbusplus::bus::match::rules::interfacesAdded(certObjPath),
+        std::bind(std::mem_fn(&Config::certificateInstalled), this,
+                  std::placeholders::_1))
 {
     ConfigIface::lDAPServerURI(lDAPServerURI);
     ConfigIface::lDAPBindDN(lDAPBindDN);
@@ -96,7 +101,11 @@
                ConfigMgr& parent) :
     Ifaces(bus, path, true),
     tlsCacertFile(caCertFile), configFilePath(filePath), objectPath(path),
-    bus(bus), parent(parent)
+    bus(bus), parent(parent),
+    certificateInstalledSignal(
+        bus, sdbusplus::bus::match::rules::interfacesAdded(certObjPath),
+        std::bind(std::mem_fn(&Config::certificateInstalled), this,
+                  std::placeholders::_1))
 {
     ConfigIface::lDAPType(lDAPType);
 
@@ -115,6 +124,27 @@
     fs::permissions(configPersistPath, permission);
 }
 
+void Config::certificateInstalled(sdbusplus::message::message& msg)
+{
+    try
+    {
+        if (enabled())
+        {
+            writeConfig();
+        }
+        parent.startOrStopService(nslcdService, enabled());
+    }
+    catch (const InternalFailure& e)
+    {
+        throw;
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>(e.what());
+        elog<InternalFailure>();
+    }
+}
+
 void Config::writeConfig()
 {
     std::stringstream confData;
@@ -156,6 +186,11 @@
         confData << "ssl on\n";
         confData << "tls_reqcert hard\n";
         confData << "tls_cacertFile " << tlsCacertFile.c_str() << "\n";
+        if (fs::exists(tlsCertFile.c_str()))
+        {
+            confData << "tls_cert " << tlsCertFile.c_str() << "\n";
+            confData << "tls_key " << tlsCertFile.c_str() << "\n";
+        }
     }
     else
     {
diff --git a/phosphor-ldap-config/ldap_config.hpp b/phosphor-ldap-config/ldap_config.hpp
index cbd2e04..d2cc8de 100644
--- a/phosphor-ldap-config/ldap_config.hpp
+++ b/phosphor-ldap-config/ldap_config.hpp
@@ -36,6 +36,8 @@
     sdbusplus::server::object::object<ConfigIface, EnableIface, MapperIface>;
 using ObjectPath = sdbusplus::message::object_path;
 
+namespace sdbusRule = sdbusplus::bus::match::rules;
+
 class ConfigMgr;
 class MockConfigMgr;
 
@@ -59,6 +61,7 @@
      *  @param[in] path - The D-Bus object path to attach at.
      *  @param[in] filePath - LDAP configuration file.
      *  @param[in] caCertFile - LDAP's CA certificate file.
+     *  @param[in] certFile - LDAP's client certificate file.
      *  @param[in] secureLDAP - Specifies whether to use SSL or not.
      *  @param[in] lDAPServerURI - LDAP URI of the server.
      *  @param[in] lDAPBindDN - distinguished name with which to bind.
@@ -78,9 +81,9 @@
      */
 
     Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
-           const char* caCertFile, bool secureLDAP, std::string lDAPServerURI,
-           std::string lDAPBindDN, std::string lDAPBaseDN,
-           std::string&& lDAPBindDNPassword,
+           const char* caCertFile, const char* certFile, bool secureLDAP,
+           std::string lDAPServerURI, std::string lDAPBindDN,
+           std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
            ConfigIface::SearchScope lDAPSearchScope, ConfigIface::Type lDAPType,
            bool lDAPServiceEnabled, std::string groupNameAttribute,
            std::string userNameAttribute, ConfigMgr& parent);
@@ -246,6 +249,7 @@
     bool secureLDAP;
     std::string lDAPBindPassword{};
     std::string tlsCacertFile{};
+    std::string tlsCertFile{};
     std::string configFilePath{};
     std::string objectPath{};
     std::filesystem::path configPersistPath{};
@@ -270,6 +274,12 @@
     std::set<std::string> privMgr = {"priv-admin", "priv-operator", "priv-user",
                                      "priv-callback"};
 
+    /** @brief React to InterfaceAdded signal
+     *  @param[in] msg - sdbusplus message
+     */
+    void certificateInstalled(sdbusplus::message::message& msg);
+    sdbusplus::bus::match_t certificateInstalledSignal;
+
     friend class MockConfigMgr;
 };
 
diff --git a/phosphor-ldap-config/ldap_config_mgr.cpp b/phosphor-ldap-config/ldap_config_mgr.cpp
index 401aacc..1eb3798 100644
--- a/phosphor-ldap-config/ldap_config_mgr.cpp
+++ b/phosphor-ldap-config/ldap_config_mgr.cpp
@@ -134,8 +134,8 @@
         objPath = openLDAPDbusObjectPath;
         openLDAPConfigPtr = std::make_unique<Config>(
             bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
-            secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN,
-            std::move(lDAPBindDNPassword),
+            tlsCertFile.c_str(), secureLDAP, lDAPServerURI, lDAPBindDN,
+            lDAPBaseDN, std::move(lDAPBindDNPassword),
             static_cast<ConfigIface::SearchScope>(lDAPSearchScope),
             static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute,
             userNameAttribute, *this);
@@ -146,8 +146,8 @@
         objPath = ADDbusObjectPath;
         ADConfigPtr = std::make_unique<Config>(
             bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
-            secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN,
-            std::move(lDAPBindDNPassword),
+            tlsCertFile.c_str(), secureLDAP, lDAPServerURI, lDAPBindDN,
+            lDAPBaseDN, std::move(lDAPBindDNPassword),
             static_cast<ConfigIface::SearchScope>(lDAPSearchScope),
             static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute,
             userNameAttribute, *this);
diff --git a/phosphor-ldap-config/ldap_config_mgr.hpp b/phosphor-ldap-config/ldap_config_mgr.hpp
index dc04546..7186503 100644
--- a/phosphor-ldap-config/ldap_config_mgr.hpp
+++ b/phosphor-ldap-config/ldap_config_mgr.hpp
@@ -52,10 +52,11 @@
      *  @param[in] caCertFile - LDAP's CA certificate file.
      */
     ConfigMgr(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
-              const char* dbusPersistentPath, const char* caCertFile) :
+              const char* dbusPersistentPath, const char* caCertFile,
+              const char* certFile) :
         CreateIface(bus, path, true),
         dbusPersistentPath(dbusPersistentPath), configFilePath(filePath),
-        bus(bus)
+        tlsCacertFile(caCertFile), tlsCertFile(certFile), bus(bus)
     {
     }
 
@@ -116,6 +117,7 @@
   protected:
     std::string configFilePath{};
     std::string tlsCacertFile{};
+    std::string tlsCertFile{};
 
     /** @brief Persistent sdbusplus D-Bus bus connection. */
     sdbusplus::bus::bus& bus;
diff --git a/phosphor-ldap-config/main.cpp b/phosphor-ldap-config/main.cpp
index 3a2d5f5..31e0d46 100644
--- a/phosphor-ldap-config/main.cpp
+++ b/phosphor-ldap-config/main.cpp
@@ -26,7 +26,8 @@
     sdbusplus::server::manager::manager objManager(bus, LDAP_CONFIG_ROOT);
 
     phosphor::ldap::ConfigMgr mgr(bus, LDAP_CONFIG_ROOT, LDAP_CONFIG_FILE,
-                                  LDAP_CONF_PERSIST_PATH, TLS_CACERT_FILE);
+                                  LDAP_CONF_PERSIST_PATH, TLS_CACERT_FILE,
+                                  TLS_CERT_FILE);
     mgr.restore();
 
     bus.request_name(LDAP_CONFIG_BUSNAME);