summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Feist <james.feist@linux.intel.com>2019-12-10 16:52:14 +0000
committerJames Feist <james.feist@linux.intel.com>2019-12-10 17:22:47 +0000
commit7166bf0fd7453f2b5d6bfb3afbdad5eb00f74990 (patch)
treea75ffbf37684d15df4dd01b8a1cc3a28f1495a55
parent4dcc3f92c8725e2424c7792908c44311e484a429 (diff)
downloadbmcweb-7166bf0fd7453f2b5d6bfb3afbdad5eb00f74990.tar.gz
bmcweb-7166bf0fd7453f2b5d6bfb3afbdad5eb00f74990.zip
Revert "Fix authorization for LDAP users"
This reverts commit 5e931ae994307babe6c3520cbaca6a7139acc81d. Reason for revert: Causing build failures /bmcweb/redfish-core/include/node.hpp: In member function ‘bool redfish::Node::isAllowedWithoutConfigureSelf(const crow::Request&)’: /bmcweb/redfish-core/include/node.hpp:182:36: error: ‘crow::persistent_data::UserRoleMap’ has not been declared crow::persistent_data::UserRoleMap::getInstance().getUserRole( When 900f949773795141266271107219ea019f2839cd was merged first this patch was not successfully rebased. Change-Id: I947d96362c7dadea5572888468a11fac5ee361d4 Signed-off-by: James Feist <james.feist@linux.intel.com>
-rw-r--r--http/routing.h85
-rw-r--r--include/sessions.hpp244
-rw-r--r--src/webserver_main.cpp4
3 files changed, 285 insertions, 48 deletions
diff --git a/http/routing.h b/http/routing.h
index 0929286..7846924 100644
--- a/http/routing.h
+++ b/http/routing.h
@@ -1250,59 +1250,48 @@ class Router
<< static_cast<uint32_t>(req.method()) << " / "
<< rules[ruleIndex]->getMethods();
- if (req.session == nullptr)
+ redfish::Privileges userPrivileges;
+ if (req.session != nullptr)
{
- rules[ruleIndex]->handle(req, res, found.second);
- return;
- }
-
- crow::connections::systemBus->async_method_call(
- [&req, &res, &rules, ruleIndex, found](
- const boost::system::error_code ec,
- std::map<std::string, std::variant<bool, std::string,
- std::vector<std::string>>>
- userInfo) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "GetUserInfo failed...";
- res.result(
- boost::beast::http::status::internal_server_error);
- res.end();
- return;
- }
-
- const std::string* userRolePtr = nullptr;
- auto userInfoIter = userInfo.find("UserPrivilege");
- if (userInfoIter != userInfo.end())
- {
- userRolePtr =
- std::get_if<std::string>(&userInfoIter->second);
- }
+ // Get the user role from the session.
+ const std::string& userRole =
+ persistent_data::UserRoleMap::getInstance().getUserRole(
+ req.session->username);
- std::string userRole{};
- if (userRolePtr != nullptr)
- {
- userRole = *userRolePtr;
- BMCWEB_LOG_DEBUG << "userName = " << req.session->username
- << " userRole = " << *userRolePtr;
- }
+ BMCWEB_LOG_DEBUG << "USER ROLE=" << userRole;
- // Get the user privileges from the role
- redfish::Privileges userPrivileges =
- redfish::getUserPrivileges(userRole);
+ // Get the user privileges from the role
+ userPrivileges = redfish::getUserPrivileges(userRole);
+ }
- if (!rules[ruleIndex]->checkPrivileges(userPrivileges))
- {
- res.result(boost::beast::http::status::forbidden);
- res.end();
- return;
- }
+ if (!rules[ruleIndex]->checkPrivileges(userPrivileges))
+ {
+ res.result(boost::beast::http::status::forbidden);
+ res.end();
+ return;
+ }
- rules[ruleIndex]->handle(req, res, found.second);
- },
- "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
- "xyz.openbmc_project.User.Manager", "GetUserInfo",
- req.session->username);
+ // any uncaught exceptions become 500s
+ try
+ {
+ rules[ruleIndex]->handle(req, res, found.second);
+ }
+ catch (std::exception& e)
+ {
+ BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+ catch (...)
+ {
+ BMCWEB_LOG_ERROR
+ << "An uncaught exception occurred. The type was unknown "
+ "so no information was available.";
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
}
void debugPrint()
diff --git a/include/sessions.hpp b/include/sessions.hpp
index 7c2575d..6e74f25 100644
--- a/include/sessions.hpp
+++ b/include/sessions.hpp
@@ -30,6 +30,250 @@ enum class PersistenceType
SINGLE_REQUEST // User times out once this request is completed.
};
+constexpr char const* userService = "xyz.openbmc_project.User.Manager";
+constexpr char const* userObjPath = "/xyz/openbmc_project/user";
+constexpr char const* userAttrIface = "xyz.openbmc_project.User.Attributes";
+constexpr char const* dbusPropertiesIface = "org.freedesktop.DBus.Properties";
+
+struct UserRoleMap
+{
+ using GetManagedPropertyType =
+ boost::container::flat_map<std::string,
+ std::variant<std::string, bool>>;
+
+ using InterfacesPropertiesType =
+ boost::container::flat_map<std::string, GetManagedPropertyType>;
+
+ using GetManagedObjectsType = std::vector<
+ std::pair<sdbusplus::message::object_path, InterfacesPropertiesType>>;
+
+ static UserRoleMap& getInstance()
+ {
+ static UserRoleMap userRoleMap;
+ return userRoleMap;
+ }
+
+ UserRoleMap(const UserRoleMap&) = delete;
+ UserRoleMap& operator=(const UserRoleMap&) = delete;
+
+ std::string getUserRole(std::string_view name)
+ {
+ auto it = roleMap.find(std::string(name));
+ if (it == roleMap.end())
+ {
+ BMCWEB_LOG_ERROR << "User name " << name
+ << " is not found in the UserRoleMap.";
+ return "";
+ }
+ return it->second;
+ }
+
+ std::string
+ extractUserRole(const InterfacesPropertiesType& interfacesProperties)
+ {
+ auto iface = interfacesProperties.find(userAttrIface);
+ if (iface == interfacesProperties.end())
+ {
+ return {};
+ }
+
+ auto& properties = iface->second;
+ auto property = properties.find("UserPrivilege");
+ if (property == properties.end())
+ {
+ return {};
+ }
+
+ const std::string* role = std::get_if<std::string>(&property->second);
+ if (role == nullptr)
+ {
+ BMCWEB_LOG_ERROR << "UserPrivilege property value is null";
+ return {};
+ }
+
+ return *role;
+ }
+
+ private:
+ void userAdded(sdbusplus::message::message& m)
+ {
+ sdbusplus::message::object_path objPath;
+ InterfacesPropertiesType interfacesProperties;
+
+ try
+ {
+ m.read(objPath, interfacesProperties);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ BMCWEB_LOG_ERROR << "Failed to parse user add signal."
+ << "ERROR=" << e.what()
+ << "REPLY_SIG=" << m.get_signature();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "obj path = " << objPath.str;
+
+ std::size_t lastPos = objPath.str.rfind("/");
+ if (lastPos == std::string::npos)
+ {
+ return;
+ };
+
+ std::string name = objPath.str.substr(lastPos + 1);
+ std::string role = this->extractUserRole(interfacesProperties);
+
+ // Insert the newly added user name and the role
+ auto res = roleMap.emplace(name, role);
+ if (res.second == false)
+ {
+ BMCWEB_LOG_ERROR << "Insertion of the user=\"" << name
+ << "\" in the roleMap failed.";
+ return;
+ }
+ }
+
+ void userRemoved(sdbusplus::message::message& m)
+ {
+ sdbusplus::message::object_path objPath;
+
+ try
+ {
+ m.read(objPath);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ BMCWEB_LOG_ERROR << "Failed to parse user delete signal.";
+ BMCWEB_LOG_ERROR << "ERROR=" << e.what()
+ << "REPLY_SIG=" << m.get_signature();
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "obj path = " << objPath.str;
+
+ std::size_t lastPos = objPath.str.rfind("/");
+ if (lastPos == std::string::npos)
+ {
+ return;
+ };
+
+ // User name must be atleast 1 char in length.
+ if ((lastPos + 1) >= objPath.str.length())
+ {
+ return;
+ }
+
+ std::string name = objPath.str.substr(lastPos + 1);
+
+ roleMap.erase(name);
+ }
+
+ void userPropertiesChanged(sdbusplus::message::message& m)
+ {
+ std::string interface;
+ GetManagedPropertyType changedProperties;
+ m.read(interface, changedProperties);
+ const std::string path = m.get_path();
+
+ BMCWEB_LOG_DEBUG << "Object Path = \"" << path << "\"";
+
+ std::size_t lastPos = path.rfind("/");
+ if (lastPos == std::string::npos)
+ {
+ return;
+ };
+
+ // User name must be at least 1 char in length.
+ if ((lastPos + 1) == path.length())
+ {
+ return;
+ }
+
+ std::string user = path.substr(lastPos + 1);
+
+ BMCWEB_LOG_DEBUG << "User Name = \"" << user << "\"";
+
+ auto index = changedProperties.find("UserPrivilege");
+ if (index == changedProperties.end())
+ {
+ return;
+ }
+
+ const std::string* role = std::get_if<std::string>(&index->second);
+ if (role == nullptr)
+ {
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Role = \"" << *role << "\"";
+
+ auto it = roleMap.find(user);
+ if (it == roleMap.end())
+ {
+ BMCWEB_LOG_ERROR << "User Name = \"" << user
+ << "\" is not found. But, received "
+ "propertiesChanged signal";
+ return;
+ }
+ it->second = *role;
+ }
+
+ UserRoleMap() :
+ userAddedSignal(
+ *crow::connections::systemBus,
+ sdbusplus::bus::match::rules::interfacesAdded(userObjPath),
+ [this](sdbusplus::message::message& m) {
+ BMCWEB_LOG_DEBUG << "User Added";
+ this->userAdded(m);
+ }),
+ userRemovedSignal(
+ *crow::connections::systemBus,
+ sdbusplus::bus::match::rules::interfacesRemoved(userObjPath),
+ [this](sdbusplus::message::message& m) {
+ BMCWEB_LOG_DEBUG << "User Removed";
+ this->userRemoved(m);
+ }),
+ userPropertiesChangedSignal(
+ *crow::connections::systemBus,
+ sdbusplus::bus::match::rules::path_namespace(userObjPath) +
+ sdbusplus::bus::match::rules::type::signal() +
+ sdbusplus::bus::match::rules::member("PropertiesChanged") +
+ sdbusplus::bus::match::rules::interface(dbusPropertiesIface) +
+ sdbusplus::bus::match::rules::argN(0, userAttrIface),
+ [this](sdbusplus::message::message& m) {
+ BMCWEB_LOG_DEBUG << "Properties Changed";
+ this->userPropertiesChanged(m);
+ })
+ {
+ crow::connections::systemBus->async_method_call(
+ [this](boost::system::error_code ec,
+ GetManagedObjectsType& managedObjects) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "User manager call failed, ignoring";
+ return;
+ }
+
+ for (auto& managedObj : managedObjects)
+ {
+ std::size_t lastPos = managedObj.first.str.rfind("/");
+ if (lastPos == std::string::npos)
+ {
+ continue;
+ };
+ std::string name = managedObj.first.str.substr(lastPos + 1);
+ std::string role = extractUserRole(managedObj.second);
+ roleMap.emplace(name, role);
+ }
+ },
+ userService, userObjPath, "org.freedesktop.DBus.ObjectManager",
+ "GetManagedObjects");
+ }
+
+ boost::container::flat_map<std::string, std::string> roleMap;
+ sdbusplus::bus::match_t userAddedSignal;
+ sdbusplus::bus::match_t userRemovedSignal;
+ sdbusplus::bus::match_t userPropertiesChangedSignal;
+};
+
struct UserSession
{
std::string uniqueId;
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index 901c180..a2da120 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -108,6 +108,10 @@ int main(int argc, char** argv)
redfish::RedfishService redfish(app);
+ // Keep the user role map hot in memory and
+ // track the changes using match object
+ crow::persistent_data::UserRoleMap::getInstance();
+
app.run();
io->run();
OpenPOWER on IntegriCloud