diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | configure.ac | 22 | ||||
-rw-r--r-- | phosphor-ldap-config/Makefile.am | 17 | ||||
-rw-r--r-- | phosphor-ldap-config/ldap_configuration.cpp | 234 | ||||
-rw-r--r-- | phosphor-ldap-config/ldap_configuration.hpp | 184 | ||||
-rw-r--r-- | phosphor-ldap-config/main.cpp | 40 |
6 files changed, 498 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index 915eedc..4413b84 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,4 +23,5 @@ phosphor_user_manager_CXXFLAGS = $(SYSTEMD_CFLAGS) \ -DBOOST_SYSTEM_NO_DEPRECATED \ -DBOOST_ERROR_CODE_HEADER_ONLY -SUBDIRS = . test phosphor-ldap-mapper +SUBDIRS = . test phosphor-ldap-mapper phosphor-ldap-config + diff --git a/configure.ac b/configure.ac index c190307..5d15fe8 100644 --- a/configure.ac +++ b/configure.ac @@ -63,6 +63,26 @@ AS_IF([test "x$enable_oe_sdk" == "xyes"], AC_SUBST([OESDK_TESTCASE_FLAGS], [$testcase_flags]) ) +AC_ARG_VAR(LDAP_CONFIG_FILE, [Path of LDAP configuration file]) +AS_IF([test "x$LDAP_CONFIG_FILE" == "x"], [LDAP_CONFIG_FILE="/etc/nslcd.conf"]) +AC_DEFINE_UNQUOTED([LDAP_CONFIG_FILE], ["$LDAP_CONFIG_FILE"], [Path of LDAP configuration file]) + +AC_ARG_VAR(LDAP_CONFIG_ROOT, [LDAP configuration root]) +AS_IF([test "x$LDAP_CONFIG_ROOT" == "x"], [LDAP_CONFIG_ROOT="/xyz/openbmc_project/user/ldap"]) +AC_DEFINE_UNQUOTED([LDAP_CONFIG_ROOT], ["$LDAP_CONFIG_ROOT"], [LDAP configuration root]) + +AC_ARG_VAR(LDAP_CONFIG_DBUS_OBJ_PATH, [D-Bus path of LDAP config object]) +AS_IF([test "x$LDAP_CONFIG_DBUS_OBJ_PATH" == "x"], [LDAP_CONFIG_DBUS_OBJ_PATH="/xyz/openbmc_project/user/ldap/config"]) +AC_DEFINE_UNQUOTED([LDAP_CONFIG_DBUS_OBJ_PATH], ["$LDAP_CONFIG_DBUS_OBJ_PATH"], [D-Bus path of LDAP config object]) + +AC_ARG_VAR(LDAP_CONFIG_BUSNAME, [D-Bus busname of LDAP config service]) +AS_IF([test "x$LDAP_CONFIG_BUSNAME" == "x"], [LDAP_CONFIG_BUSNAME="xyz.openbmc_project.Ldap.Config"]) +AC_DEFINE_UNQUOTED([LDAP_CONFIG_BUSNAME], ["$LDAP_CONFIG_BUSNAME"], [D-Bus busname of LDAP config service]) + +AC_DEFINE(SYSTEMD_BUSNAME, "org.freedesktop.systemd1", [systemd busname.]) +AC_DEFINE(SYSTEMD_PATH, "/org/freedesktop/systemd1", [systemd path.]) +AC_DEFINE(SYSTEMD_INTERFACE, "org.freedesktop.systemd1.Manager", [systemd interface.]) + # Checks for typedefs, structures, and compiler characteristics. AX_CXX_COMPILE_STDCXX_17([noext]) AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS]) @@ -71,5 +91,5 @@ AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS]) LT_INIT # Create configured output -AC_CONFIG_FILES([Makefile test/Makefile phosphor-ldap-mapper/Makefile]) +AC_CONFIG_FILES([Makefile test/Makefile phosphor-ldap-mapper/Makefile phosphor-ldap-config/Makefile]) AC_OUTPUT diff --git a/phosphor-ldap-config/Makefile.am b/phosphor-ldap-config/Makefile.am new file mode 100644 index 0000000..ed0853c --- /dev/null +++ b/phosphor-ldap-config/Makefile.am @@ -0,0 +1,17 @@ +sbin_PROGRAMS = phosphor-ldap-conf + +noinst_HEADERS = ldap_configuration.hpp + +phosphor_ldap_conf_SOURCES = \ + main.cpp \ + ldap_configuration.cpp + +phosphor_ldap_conf_LDFLAGS = $(SDBUSPLUS_LIBS) \ + $(PHOSPHOR_DBUS_INTERFACES_LIBS) \ + $(PHOSPHOR_LOGGING_LIBS)\ + -lstdc++fs + +phosphor_ldap_conf_CXXFLAGS = $(SYSTEMD_CFLAGS) \ + $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \ + $(PHOSPHOR_LOGGING_CFLAGS) \ + -flto diff --git a/phosphor-ldap-config/ldap_configuration.cpp b/phosphor-ldap-config/ldap_configuration.cpp new file mode 100644 index 0000000..06a4d5d --- /dev/null +++ b/phosphor-ldap-config/ldap_configuration.cpp @@ -0,0 +1,234 @@ +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include "ldap_configuration.hpp" +#include "config.h" +#include <fstream> +#include <sstream> + +namespace phosphor +{ +namespace ldap +{ +constexpr auto nslcdService = "nslcd.service"; + +Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath, + bool secureLDAP, std::string lDAPServerURI, + std::string lDAPBindDN, std::string lDAPBaseDN, + std::string lDAPBindDNpassword, + ldap_base::Config::SearchScope lDAPSearchScope, + ldap_base::Config::Type lDAPType, ConfigMgr& parent) : + ConfigIface(bus, path, true), + configFilePath(filePath), bus(bus), parent(parent) +{ + ConfigIface::secureLDAP(secureLDAP); + ConfigIface::lDAPServerURI(lDAPServerURI); + ConfigIface::lDAPBindDN(lDAPBindDN); + ConfigIface::lDAPBaseDN(lDAPBaseDN); + ConfigIface::lDAPBINDDNpassword(lDAPBindDNpassword); + ConfigIface::lDAPSearchScope(lDAPSearchScope); + ConfigIface::lDAPType(lDAPType); + writeConfig(); + parent.restartService(nslcdService); + // Emit deferred signal. + this->emit_object_added(); +} + +void Config::writeConfig() +{ + std::fstream stream(configFilePath.c_str(), std::fstream::out); + std::stringstream confData; + confData << "uid root\n"; + confData << "gid root\n\n"; + confData << "ldap_version 3\n\n"; + confData << "timelimit 30\n"; + confData << "bind_timelimit 30\n"; + confData << "pagesize 1000\n"; + confData << "referrals off\n\n"; + confData << "uri " << lDAPServerURI() << "\n\n"; + confData << "base " << lDAPBaseDN() << "\n\n"; + confData << "binddn " << lDAPBindDN() << "\n"; + confData << "bindpw " << lDAPBINDDNpassword() << "\n\n"; + switch (lDAPSearchScope()) + { + case ldap_base::Config::SearchScope::sub: + confData << "scope sub\n\n"; + break; + case ldap_base::Config::SearchScope::one: + confData << "scope one\n\n"; + break; + case ldap_base::Config::SearchScope::base: + confData << "scope base\n\n"; + break; + } + confData << "base passwd " << lDAPBaseDN() << "\n"; + confData << "base shadow " << lDAPBaseDN() << "\n\n"; + if (secureLDAP() == true) + { + confData << "ssl on\n"; + confData << "tls_reqcert allow\n"; + confData << "tls_cert /etc/nslcd/certs/cert.pem\n"; + } + else + { + confData << "ssl off\n\n"; + } + if (lDAPType() == ldap_base::Config::Type::ActiveDirectory) + { + confData << "filter passwd (&(objectClass=user)(objectClass=person)" + "(!(objectClass=computer)))\n"; + confData + << "filter group (|(objectclass=group)(objectclass=groupofnames) " + "(objectclass=groupofuniquenames))\n"; + confData << "map passwd uid sAMAccountName\n"; + confData << "map passwd uidNumber " + "objectSid:S-1-5-21-3623811015-3361044348-30300820\n"; + confData << "map passwd gidNumber primaryGroupID\n"; + confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n"; + confData << "map passwd gecos displayName\n"; + confData << "map passwd loginShell \"/bin/bash\"\n"; + confData << "map group gidNumber primaryGroupID\n"; + confData << "map group gidNumber " + "objectSid:S-1-5-21-3623811015-3361044348-30300820\n"; + confData << "map group cn sAMAccountName\n"; + } + else if (lDAPType() == ldap_base::Config::Type::OpenLdap) + { + confData << "filter passwd (objectclass=*)\n"; + confData << "map passwd uid cn\n"; + confData << "map passwd gecos displayName\n"; + } + stream << confData.str(); + stream.flush(); + stream.close(); + return; +} + +bool Config::secureLDAP(bool value) +{ + if (value == secureLDAP()) + { + return value; + } + + auto val = ConfigIface::secureLDAP(value); + writeConfig(); + parent.restartService(nslcdService); + + return val; +} + +std::string Config::lDAPServerURI(std::string value) +{ + if (value == lDAPServerURI()) + { + return value; + } + + auto val = ConfigIface::lDAPServerURI(value); + writeConfig(); + parent.restartService(nslcdService); + + return val; +} + +std::string Config::lDAPBindDN(std::string value) +{ + if (value == lDAPBindDN()) + { + return value; + } + + auto val = ConfigIface::lDAPBindDN(value); + writeConfig(); + parent.restartService(nslcdService); + + return val; +} + +std::string Config::lDAPBaseDN(std::string value) +{ + if (value == lDAPBaseDN()) + { + return value; + } + + auto val = ConfigIface::lDAPBaseDN(value); + writeConfig(); + parent.restartService(nslcdService); + + return val; +} + +std::string Config::lDAPBINDDNpassword(std::string value) +{ + if (value == lDAPBINDDNpassword()) + { + return value; + } + + auto val = ConfigIface::lDAPBINDDNpassword(value); + writeConfig(); + parent.restartService(nslcdService); + + return val; +} + +ldap_base::Config::SearchScope + Config::lDAPSearchScope(ldap_base::Config::SearchScope value) +{ + if (value == lDAPSearchScope()) + { + return value; + } + + auto val = ConfigIface::lDAPSearchScope(value); + writeConfig(); + parent.restartService(nslcdService); + + return val; +} + +ldap_base::Config::Type Config::lDAPType(ldap_base::Config::Type value) +{ + if (value == lDAPType()) + { + return value; + } + + auto val = ConfigIface::lDAPType(value); + writeConfig(); + parent.restartService(nslcdService); + + return val; +} + +void ConfigMgr::restartService(const std::string& service) +{ + auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, + SYSTEMD_INTERFACE, "RestartUnit"); + method.append(service.c_str(), "replace"); + bus.call_noreply(method); +} + +std::string + ConfigMgr::createConfig(bool secureLDAP, std::string lDAPServerURI, + std::string lDAPBindDN, std::string lDAPBaseDN, + std::string lDAPBINDDNpassword, + ldap_base::Create::SearchScope lDAPSearchScope, + ldap_base::Create::Type lDAPType) +{ + // With current implementation we support only one LDAP server. + configPtr.reset(nullptr); + + auto objPath = std::string(LDAP_CONFIG_DBUS_OBJ_PATH); + configPtr = std::make_unique<Config>( + bus, objPath.c_str(), LDAP_CONFIG_FILE, secureLDAP, lDAPServerURI, + lDAPBindDN, lDAPBaseDN, lDAPBINDDNpassword, + static_cast<ldap_base::Config::SearchScope>(lDAPSearchScope), + static_cast<ldap_base::Config::Type>(lDAPType), *this); + + return objPath; +} + +} // namespace ldap +} // namespace phosphor diff --git a/phosphor-ldap-config/ldap_configuration.hpp b/phosphor-ldap-config/ldap_configuration.hpp new file mode 100644 index 0000000..f2bf02a --- /dev/null +++ b/phosphor-ldap-config/ldap_configuration.hpp @@ -0,0 +1,184 @@ +#pragma once + +#include <sdbusplus/bus.hpp> +#include <sdbusplus/server/object.hpp> +#include <xyz/openbmc_project/User/Ldap/Config/server.hpp> +#include <xyz/openbmc_project/User/Ldap/Create/server.hpp> +#include <string> + +namespace phosphor +{ +namespace ldap +{ +static constexpr auto defaultNslcdFile = "/etc/nslcd.conf.default"; +static constexpr auto nsSwitchFile = "/etc/nsswitch.conf"; +static constexpr auto LDAPNsSwitchFile = "/etc/nsswitch_ldap.conf"; +static constexpr auto linuxNsSwitchFile = "/etc/nsswitch_linux.conf"; + +namespace ldap_base = sdbusplus::xyz::openbmc_project::User::Ldap::server; +using ConfigIface = sdbusplus::server::object::object<ldap_base::Config>; +using CreateIface = sdbusplus::server::object::object<ldap_base::Create>; + +class ConfigMgr; + +/** @class Config + * @brief Configuration for LDAP. + * @details concrete implementation of xyz.openbmc_project.User.Ldap.Config + * API, in order to provide LDAP configuration. + */ +class Config : public ConfigIface +{ + public: + Config() = delete; + ~Config() = default; + Config(const Config&) = delete; + Config& operator=(const Config&) = delete; + Config(Config&&) = default; + Config& operator=(Config&&) = default; + + /** @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] 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. + * @param[in] lDAPBaseDN - distinguished name to use as search base. + * @param[in] lDAPBindDNpassword - credentials with which to bind. + * @param[in] lDAPSearchScope - the search scope. + * @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, + bool secureLDAP, std::string lDAPServerURI, std::string lDAPBindDN, + std::string lDAPBaseDN, std::string lDAPBindDNpassword, + ldap_base::Config::SearchScope lDAPSearchScope, + ldap_base::Config::Type lDAPType, ConfigMgr& parent); + + using ConfigIface::lDAPBaseDN; + using ConfigIface::lDAPBindDN; + using ConfigIface::lDAPBINDDNpassword; + using ConfigIface::lDAPSearchScope; + using ConfigIface::lDAPServerURI; + using ConfigIface::lDAPType; + using ConfigIface::secureLDAP; + using ConfigIface::setPropertyByName; + + /** @brief Update the secure LDAP property. + * @param[in] value - secureLDAP value to be updated. + * @returns value of changed secureLDAP. + */ + bool secureLDAP(bool value) override; + + /** @brief Update the Server URI property. + * @param[in] value - lDAPServerURI value to be updated. + * @returns value of changed lDAPServerURI. + */ + std::string lDAPServerURI(std::string value) override; + + /** @brief Update the BindDN property. + * @param[in] value - lDAPBindDN value to be updated. + * @returns value of changed lDAPBindDN. + */ + std::string lDAPBindDN(std::string value) override; + + /** @brief Update the BaseDN property. + * @param[in] value - lDAPBaseDN value to be updated. + * @returns value of changed lDAPBaseDN. + */ + std::string lDAPBaseDN(std::string value) override; + + /** @brief Update the BindDN password property. + * @param[in] value - lDAPBINDDNpassword value to be updated. + * @returns value of changed lDAPBINDDNpassword. + */ + std::string lDAPBINDDNpassword(std::string value) override; + + /** @brief Update the Search scope property. + * @param[in] value - lDAPSearchScope value to be updated. + * @returns value of changed lDAPSearchScope. + */ + ldap_base::Config::SearchScope + lDAPSearchScope(ldap_base::Config::SearchScope value) override; + + /** @brief Update the LDAP Type property. + * @param[in] value - lDAPType value to be updated. + * @returns value of changed lDAPType. + */ + ldap_base::Config::Type lDAPType(ldap_base::Config::Type value) override; + + private: + std::string configFilePath{}; + + /** @brief Persistent sdbusplus D-Bus bus connection. */ + sdbusplus::bus::bus& bus; + + /** @brief Create a new LDAP config file. + */ + virtual void writeConfig(); + + /** @brief reference to config manager object */ + ConfigMgr& parent; +}; + +/** @class ConfigMgr + * @brief Creates LDAP server configuration. + * @details concrete implementation of xyz.openbmc_project.User.Ldap.Create + * APIs, in order to create LDAP configuration. + */ +class ConfigMgr : public CreateIface +{ + public: + ConfigMgr() = delete; + ~ConfigMgr() = default; + ConfigMgr(const ConfigMgr&) = delete; + ConfigMgr& operator=(const ConfigMgr&) = delete; + ConfigMgr(ConfigMgr&&) = delete; + ConfigMgr& operator=(ConfigMgr&&) = delete; + + /** @brief ConfigMgr to put object onto bus at a dbus path. + * @param[in] bus - Bus to attach to. + * @param[in] path - Path to attach at. + * @param[in] filePath - LDAP configuration file. + */ + ConfigMgr(sdbusplus::bus::bus& bus, const char* path) : + CreateIface(bus, path), bus(bus) + { + // TODO restore config object if config file exists. + } + + /** @brief concrete implementation of the pure virtual funtion + xyz.openbmc_project.User.Ldap.Create.createConfig. + * @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 bind to bind + to the directory server for lookups. + * @param[in] lDAPBaseDN - distinguished name to use as search base. + * @param[in] lDAPBindDNpassword - credentials with which to bind. + * @param[in] lDAPSearchScope - the search scope. + * @param[in] lDAPType - Specifies the LDAP server type which can be AD + or openLDAP. + * @returns the object path of the D-Bus object created. + */ + std::string createConfig(bool secureLDAP, std::string lDAPServerURI, + std::string lDAPBindDN, std::string lDAPBaseDN, + std::string lDAPBindDNpassword, + ldap_base::Create::SearchScope lDAPSearchScope, + ldap_base::Create::Type lDAPType) override; + + /** @brief restarts given service + * @param[in] service - Service to be restarted. + */ + virtual void restartService(const std::string& service); + + private: + /** @brief Persistent sdbusplus D-Bus bus connection. */ + sdbusplus::bus::bus& bus; + + /** @brief Pointer to a Config D-Bus object */ + std::unique_ptr<Config> configPtr = nullptr; +}; +} // namespace ldap +} // namespace phosphor diff --git a/phosphor-ldap-config/main.cpp b/phosphor-ldap-config/main.cpp new file mode 100644 index 0000000..6bba619 --- /dev/null +++ b/phosphor-ldap-config/main.cpp @@ -0,0 +1,40 @@ +#include "config.h" +#include "ldap_configuration.hpp" +#include <experimental/filesystem> +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include <sdbusplus/bus.hpp> +#include <xyz/openbmc_project/Common/error.hpp> + +int main(int argc, char* argv[]) +{ + using namespace phosphor::logging; + using namespace sdbusplus::xyz::openbmc_project::Common::Error; + namespace fs = std::experimental::filesystem; + + if (!fs::exists(phosphor::ldap::defaultNslcdFile) || + !fs::exists(phosphor::ldap::nsSwitchFile) || + (!fs::exists(phosphor::ldap::LDAPNsSwitchFile) && + !fs::exists(phosphor::ldap::linuxNsSwitchFile))) + { + log<level::ERR>("Error starting LDAP Config App, configfile(s) are " + "missing, exiting!!!"); + elog<InternalFailure>(); + } + auto bus = sdbusplus::bus::new_default(); + + // Add sdbusplus ObjectManager for the 'root' path of the LDAP config. + sdbusplus::server::manager::manager objManager(bus, LDAP_CONFIG_ROOT); + + phosphor::ldap::ConfigMgr mgr(bus, LDAP_CONFIG_ROOT); + + bus.request_name(LDAP_CONFIG_BUSNAME); + + while (true) + { + bus.process_discard(); + bus.wait(); + } + + return 0; +} |