diff options
author | James Feist <james.feist@linux.intel.com> | 2019-12-10 16:52:14 +0000 |
---|---|---|
committer | James Feist <james.feist@linux.intel.com> | 2019-12-10 17:22:47 +0000 |
commit | 7166bf0fd7453f2b5d6bfb3afbdad5eb00f74990 (patch) | |
tree | a75ffbf37684d15df4dd01b8a1cc3a28f1495a55 | |
parent | 4dcc3f92c8725e2424c7792908c44311e484a429 (diff) | |
download | bmcweb-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.h | 85 | ||||
-rw-r--r-- | include/sessions.hpp | 244 | ||||
-rw-r--r-- | src/webserver_main.cpp | 4 |
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(); |