Create role mapping under ldap config object
Each ldap config object should be have its own
mapping object.
This is to align with the redfish.
https://redfish.dmtf.org/schemas/AccountService.v1_4_0.json
As per redfish, Each config will have it's own
"RemoteRoleMapping".
Mapping object should be persisted and restores
when the phosphor-ldap-conf restarts.
TestedBy:
Unit Tested.
Creation of privilege mapping.
Persist the priv-mapping.
Restores the priv-mapping.
Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
Change-Id: I5ab4aeffae61f9cc57c1338f94784d0fe5607cd3
diff --git a/phosphor-ldap-config/Makefile.am b/phosphor-ldap-config/Makefile.am
index 3052b6d..d6d8454 100644
--- a/phosphor-ldap-config/Makefile.am
+++ b/phosphor-ldap-config/Makefile.am
@@ -1,15 +1,18 @@
bin_PROGRAMS = phosphor-ldap-conf
-noinst_HEADERS = \
- ldap_config.hpp \
+noinst_HEADERS = ldap_config.hpp \
ldap_config_mgr.hpp \
+ ldap_mapper_entry.hpp \
+ ldap_mapper_serialize.hpp \
utils.hpp
phosphor_ldap_conf_SOURCES = \
main.cpp \
utils.cpp \
ldap_config.cpp \
- ldap_config_mgr.cpp
+ ldap_config_mgr.cpp \
+ ldap_mapper_entry.cpp \
+ ldap_mapper_serialize.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 03c6ffc..b22d684 100644
--- a/phosphor-ldap-config/ldap_config.cpp
+++ b/phosphor-ldap-config/ldap_config.cpp
@@ -5,6 +5,10 @@
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/archives/binary.hpp>
+#include "ldap_mapper_serialize.hpp"
+
+#include <xyz/openbmc_project/Common/error.hpp>
+#include <xyz/openbmc_project/User/Common/error.hpp>
#include <filesystem>
#include <fstream>
#include <sstream>
@@ -27,9 +31,12 @@
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
namespace fs = std::filesystem;
+
using Argument = xyz::openbmc_project::Common::InvalidArgument;
using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
+using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
+ Error::PrivilegeMappingExists;
using Line = std::string;
using Key = std::string;
@@ -625,5 +632,114 @@
}
}
+ObjectPath Config::create(std::string groupName, std::string privilege)
+{
+ checkPrivilegeMapper(groupName);
+ checkPrivilegeLevel(privilege);
+
+ entryId++;
+
+ // Object path for the LDAP group privilege mapper entry
+ fs::path mapperObjectPath = objectPath;
+ mapperObjectPath /= "role_map";
+ mapperObjectPath /= std::to_string(entryId);
+
+ fs::path persistPath = parent.dbusPersistentPath;
+ persistPath += mapperObjectPath;
+
+ // Create mapping for LDAP privilege mapper entry
+ auto entry = std::make_unique<LDAPMapperEntry>(
+ bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
+ groupName, privilege, *this);
+
+ phosphor::ldap::serialize(*entry, std::move(persistPath));
+
+ PrivilegeMapperList.emplace(entryId, std::move(entry));
+ return mapperObjectPath.string();
+}
+
+void Config::deletePrivilegeMapper(Id id)
+{
+ fs::path mapperObjectPath = objectPath;
+ mapperObjectPath /= "role_map";
+ mapperObjectPath /= std::to_string(id);
+
+ fs::path persistPath = parent.dbusPersistentPath;
+ persistPath += std::move(mapperObjectPath);
+
+ // Delete the persistent representation of the privilege mapper.
+ fs::remove(std::move(persistPath));
+
+ PrivilegeMapperList.erase(id);
+}
+void Config::checkPrivilegeMapper(const std::string& groupName)
+{
+ if (groupName.empty())
+ {
+ log<level::ERR>("Group name is empty");
+ elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
+ Argument::ARGUMENT_VALUE("Null"));
+ }
+
+ for (const auto& val : PrivilegeMapperList)
+ {
+ if (val.second.get()->groupName() == groupName)
+ {
+ log<level::ERR>("Group name already exists");
+ elog<PrivilegeMappingExists>();
+ }
+ }
+}
+
+void Config::checkPrivilegeLevel(const std::string& privilege)
+{
+ if (privilege.empty())
+ {
+ log<level::ERR>("Privilege level is empty");
+ elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
+ Argument::ARGUMENT_VALUE("Null"));
+ }
+
+ if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
+ {
+ log<level::ERR>("Invalid privilege");
+ elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
+ Argument::ARGUMENT_VALUE(privilege.c_str()));
+ }
+}
+
+void Config::restoreRoleMapping()
+{
+ namespace fs = std::filesystem;
+ fs::path dir = parent.dbusPersistentPath;
+ dir += objectPath;
+ dir /= "role_map";
+
+ if (!fs::exists(dir) || fs::is_empty(dir))
+ {
+ return;
+ }
+
+ for (auto& file : fs::directory_iterator(dir))
+ {
+ std::string id = file.path().filename().c_str();
+ size_t idNum = std::stol(id);
+
+ auto entryPath = objectPath + '/' + "role_map" + '/' + id;
+ auto persistPath = parent.dbusPersistentPath + entryPath;
+ auto entry = std::make_unique<LDAPMapperEntry>(
+ bus, entryPath.c_str(), persistPath.c_str(), *this);
+ if (phosphor::ldap::deserialize(file.path(), *entry))
+ {
+ entry->Interfaces::emit_object_added();
+ PrivilegeMapperList.emplace(idNum, std::move(entry));
+ if (idNum > entryId)
+ {
+ entryId = idNum;
+ }
+ }
+ }
+}
+
} // namespace ldap
} // namespace phosphor
diff --git a/phosphor-ldap-config/ldap_config.hpp b/phosphor-ldap-config/ldap_config.hpp
index 0d2adf1..cbd2e04 100644
--- a/phosphor-ldap-config/ldap_config.hpp
+++ b/phosphor-ldap-config/ldap_config.hpp
@@ -4,14 +4,18 @@
#include <xyz/openbmc_project/Object/Enable/server.hpp>
#include <xyz/openbmc_project/User/Ldap/Create/server.hpp>
#include <xyz/openbmc_project/User/Ldap/Config/server.hpp>
+#include <xyz/openbmc_project/User/PrivilegeMapper/server.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
+#include "ldap_mapper_entry.hpp"
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
-#include <string>
+
#include <filesystem>
+#include <set>
+#include <string>
namespace phosphor
{
@@ -22,10 +26,16 @@
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using ConfigIface = sdbusplus::xyz::openbmc_project::User::Ldap::server::Config;
using EnableIface = sdbusplus::xyz::openbmc_project::Object::server::Enable;
-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;
+using MapperIface =
+ sdbusplus::xyz::openbmc_project::User::server::PrivilegeMapper;
+
+using Ifaces =
+ sdbusplus::server::object::object<ConfigIface, EnableIface, MapperIface>;
+using ObjectPath = sdbusplus::message::object_path;
+
class ConfigMgr;
class MockConfigMgr;
@@ -189,6 +199,49 @@
*/
bool enableService(bool value);
+ /** @brief Creates a mapping for the group to the privilege
+ *
+ * @param[in] groupName - Group Name to which the privilege needs to be
+ * assigned.
+ * @param[in] privilege - The privilege role associated with the group.
+ *
+ * @return On success return the D-Bus object path of the created privilege
+ * mapper entry.
+ */
+ ObjectPath create(std::string groupName, std::string privilege) override;
+
+ /** @brief Delete privilege mapping for LDAP group
+ *
+ * This method deletes the privilege mapping
+ *
+ * @param[in] id - id of the object which needs to be deleted.
+ */
+ void deletePrivilegeMapper(Id id);
+
+ /** @brief Check if LDAP group privilege mapping requested is valid
+ *
+ * Check if the privilege mapping already exists for the LDAP group name
+ * and group name is empty.
+ *
+ * @param[in] groupName - LDAP group name
+ *
+ * @return throw exception if the conditions are not met.
+ */
+ void checkPrivilegeMapper(const std::string& groupName);
+
+ /** @brief Check if the privilege level is a valid one
+ *
+ * @param[in] privilege - Privilege level
+ *
+ * @return throw exception if the conditions are not met.
+ */
+ void checkPrivilegeLevel(const std::string& privilege);
+
+ /** @brief Construct LDAP mapper entry D-Bus objects from their persisted
+ * representations.
+ */
+ void restoreRoleMapping();
+
private:
bool secureLDAP;
std::string lDAPBindPassword{};
@@ -207,6 +260,16 @@
/** @brief reference to config manager object */
ConfigMgr& parent;
+ /** @brief Id of the last privilege mapper entry */
+ Id entryId = 0;
+
+ /** @brief container to hold privilege mapper objects */
+ std::map<Id, std::unique_ptr<LDAPMapperEntry>> PrivilegeMapperList;
+
+ /** @brief available privileges container */
+ std::set<std::string> privMgr = {"priv-admin", "priv-operator", "priv-user",
+ "priv-callback"};
+
friend class MockConfigMgr;
};
diff --git a/phosphor-ldap-config/ldap_config_mgr.cpp b/phosphor-ldap-config/ldap_config_mgr.cpp
index 9142538..401aacc 100644
--- a/phosphor-ldap-config/ldap_config_mgr.cpp
+++ b/phosphor-ldap-config/ldap_config_mgr.cpp
@@ -198,12 +198,14 @@
// Restore the ldap config and their mappings
if (ADConfigPtr->deserialize())
{
- // Restore the role mappings in later commit
+ // Restore the role mappings
+ ADConfigPtr->restoreRoleMapping();
ADConfigPtr->emit_object_added();
}
if (openLDAPConfigPtr->deserialize())
{
- // Restore the role mappings in later commit
+ // Restore the role mappings
+ openLDAPConfigPtr->restoreRoleMapping();
openLDAPConfigPtr->emit_object_added();
}
}
diff --git a/phosphor-ldap-config/ldap_mapper_entry.cpp b/phosphor-ldap-config/ldap_mapper_entry.cpp
index 8410942..09b0e0f 100644
--- a/phosphor-ldap-config/ldap_mapper_entry.cpp
+++ b/phosphor-ldap-config/ldap_mapper_entry.cpp
@@ -1,17 +1,17 @@
-#include <experimental/filesystem>
+#include <filesystem>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/User/Common/error.hpp>
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include "config.h"
+#include "ldap_config.hpp"
#include "ldap_mapper_entry.hpp"
-#include "ldap_mapper_mgr.hpp"
#include "ldap_mapper_serialize.hpp"
namespace phosphor
{
-namespace user
+namespace ldap
{
using namespace phosphor::logging;
@@ -22,22 +22,21 @@
LDAPMapperEntry::LDAPMapperEntry(sdbusplus::bus::bus &bus, const char *path,
const char *filePath,
const std::string &groupName,
- const std::string &privilege,
- LDAPMapperMgr &parent) :
- Ifaces(bus, path, true),
- id(std::stol(std::experimental::filesystem::path(path).filename())),
- manager(parent), persistPath(filePath)
+ const std::string &privilege, Config &parent) :
+ Interfaces(bus, path, true),
+ id(std::stol(std::filesystem::path(path).filename())), manager(parent),
+ persistPath(filePath)
{
- Ifaces::privilege(privilege, true);
- Ifaces::groupName(groupName, true);
- Ifaces::emit_object_added();
+ Interfaces::privilege(privilege, true);
+ Interfaces::groupName(groupName, true);
+ Interfaces::emit_object_added();
}
LDAPMapperEntry::LDAPMapperEntry(sdbusplus::bus::bus &bus, const char *path,
- const char *filePath, LDAPMapperMgr &parent) :
- Ifaces(bus, path, true),
- id(std::stol(std::experimental::filesystem::path(path).filename())),
- manager(parent), persistPath(filePath)
+ const char *filePath, Config &parent) :
+ Interfaces(bus, path, true),
+ id(std::stol(std::filesystem::path(path).filename())), manager(parent),
+ persistPath(filePath)
{
}
@@ -48,29 +47,29 @@
std::string LDAPMapperEntry::groupName(std::string value)
{
- if (value == Ifaces::groupName())
+ if (value == Interfaces::groupName())
{
return value;
}
manager.checkPrivilegeMapper(value);
- auto val = Ifaces::groupName(value);
- serialize(*this, id, persistPath);
+ auto val = Interfaces::groupName(value);
+ serialize(*this, persistPath);
return val;
}
std::string LDAPMapperEntry::privilege(std::string value)
{
- if (value == Ifaces::privilege())
+ if (value == Interfaces::privilege())
{
return value;
}
manager.checkPrivilegeLevel(value);
- auto val = Ifaces::privilege(value);
- serialize(*this, id, persistPath);
+ auto val = Interfaces::privilege(value);
+ serialize(*this, persistPath);
return val;
}
-} // namespace user
+} // namespace ldap
} // namespace phosphor
diff --git a/phosphor-ldap-config/ldap_mapper_entry.hpp b/phosphor-ldap-config/ldap_mapper_entry.hpp
index dea85c2..310f006 100644
--- a/phosphor-ldap-config/ldap_mapper_entry.hpp
+++ b/phosphor-ldap-config/ldap_mapper_entry.hpp
@@ -7,17 +7,17 @@
namespace phosphor
{
-namespace user
+namespace ldap
{
namespace Base = sdbusplus::xyz::openbmc_project;
using Entry =
sdbusplus::xyz::openbmc_project::User::server::PrivilegeMapperEntry;
using Delete = sdbusplus::xyz::openbmc_project::Object::server::Delete;
-using Ifaces = sdbusplus::server::object::object<Entry, Delete>;
+using Interfaces = sdbusplus::server::object::object<Entry, Delete>;
-// Forward declaration for LDAPMapperMgr
-class LDAPMapperMgr;
+// Forward declaration for Config
+class Config;
using Id = size_t;
@@ -25,7 +25,7 @@
*
* @brief This D-Bus object represents the privilege level for the LDAP group.
*/
-class LDAPMapperEntry : public Ifaces
+class LDAPMapperEntry : public Interfaces
{
public:
LDAPMapperEntry() = delete;
@@ -46,7 +46,7 @@
*/
LDAPMapperEntry(sdbusplus::bus::bus &bus, const char *path,
const char *filePath, const std::string &groupName,
- const std::string &privilege, LDAPMapperMgr &parent);
+ const std::string &privilege, Config &parent);
/** @brief Constructs LDAP privilege mapper entry object
*
@@ -56,7 +56,7 @@
* @param[in] parent - LDAP privilege mapper manager
*/
LDAPMapperEntry(sdbusplus::bus::bus &bus, const char *path,
- const char *filePath, LDAPMapperMgr &parent);
+ const char *filePath, Config &parent);
/** @brief Delete privilege mapper entry object
*
@@ -88,11 +88,11 @@
private:
Id id;
- LDAPMapperMgr &manager;
+ Config &manager;
/** @brief serialization directory path */
std::string persistPath;
};
-} // namespace user
+} // namespace ldap
} // namespace phosphor
diff --git a/phosphor-ldap-config/ldap_mapper_serialize.cpp b/phosphor-ldap-config/ldap_mapper_serialize.cpp
index 3ef809e..7fe2398 100644
--- a/phosphor-ldap-config/ldap_mapper_serialize.cpp
+++ b/phosphor-ldap-config/ldap_mapper_serialize.cpp
@@ -8,11 +8,11 @@
// Register class version
// From cereal documentation;
// "This macro should be placed at global scope"
-CEREAL_CLASS_VERSION(phosphor::user::LDAPMapperEntry, CLASS_VERSION);
+CEREAL_CLASS_VERSION(phosphor::ldap::LDAPMapperEntry, CLASS_VERSION);
namespace phosphor
{
-namespace user
+namespace ldap
{
using namespace phosphor::logging;
@@ -54,10 +54,10 @@
privilege(privilege, true);
}
-fs::path serialize(const LDAPMapperEntry& entry, Id id, const fs::path& dir)
+fs::path serialize(const LDAPMapperEntry& entry, const fs::path& path)
{
- auto path = dir / std::to_string(id);
- std::ofstream os(path.c_str(), std::ios::binary);
+ fs::create_directories(path.parent_path());
+ std::ofstream os(path.c_str(), std::ios::binary | std::ios::out);
cereal::BinaryOutputArchive oarchive(os);
oarchive(entry);
return path;
@@ -90,5 +90,5 @@
}
}
-} // namespace user
+} // namespace ldap
} // namespace phosphor
diff --git a/phosphor-ldap-config/ldap_mapper_serialize.hpp b/phosphor-ldap-config/ldap_mapper_serialize.hpp
index 5ab71c0..371a556 100644
--- a/phosphor-ldap-config/ldap_mapper_serialize.hpp
+++ b/phosphor-ldap-config/ldap_mapper_serialize.hpp
@@ -1,26 +1,24 @@
#pragma once
-#include <experimental/filesystem>
+#include <filesystem>
#include "config.h"
#include "ldap_mapper_entry.hpp"
namespace phosphor
{
-namespace user
+namespace ldap
{
-namespace fs = std::experimental::filesystem;
+namespace fs = std::filesystem;
/** @brief Serialize and persist LDAP privilege mapper D-Bus object
*
* @param[in] entry - LDAP privilege mapper entry
- * @param[in] id - filename of the persisted LDAP mapper entry
- * @param[in] dir - pathname of directory where the serialized privilege
- * mappings are stored.
+ * @param[in] path - pathname of persisted LDAP mapper entry
*
* @return fs::path - pathname of persisted error file
*/
-fs::path serialize(const LDAPMapperEntry& entry, Id id, const fs::path& dir);
+fs::path serialize(const LDAPMapperEntry& entry, const fs::path& dir);
/** @brief Deserialize a persisted LDAP privilege mapper into a D-Bus object
*
@@ -32,5 +30,5 @@
*/
bool deserialize(const fs::path& path, LDAPMapperEntry& entry);
-} // namespace user
+} // namespace ldap
} // namespace phosphor
diff --git a/test/Makefile.am b/test/Makefile.am
index 9d11428..4f4f9a1 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -30,7 +30,9 @@
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_mgr.o
+ $(top_builddir)/phosphor-ldap-config/ldap_config_mgr.o \
+ $(top_builddir)/phosphor-ldap-config/ldap_mapper_entry.o \
+ $(top_builddir)/phosphor-ldap-config/ldap_mapper_serialize.o
check_PROGRAMS += ldap_mapper_test
ldap_mapper_test_CPPFLAGS = $(cppflags)