diff options
author | Ed Tanous <edtanous@google.com> | 2021-05-10 07:51:31 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2023-07-28 19:26:28 +0300 |
commit | 8ed41c35a314580bb794fa0fff2e01b0bf7efcf7 (patch) | |
tree | 414c891a4b384b8b008059c0f501ec90c4382484 /include/dbus_privileges.hpp | |
parent | 3a34b742207414e20eb928e982b7c217789e89d5 (diff) | |
download | bmcweb-8ed41c35a314580bb794fa0fff2e01b0bf7efcf7.tar.xz |
Cache user role in session object
There is an async call within the router that leads to a small, but
pervasive performance issue for all queries. Removing that call from the
router has the potential to increase the performance of every
authenticated query, and significantly reduce our dbus traffic for
"simple" operations.
This commit re-implements the role cache in session object that existed
previously many years ago. Each users role is fetched during
authentication and persisted in session object. Each successive request
can then be matched against the privilege which is there in the
in-memory session object.
This was discussed on below commit
https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/39756
Tested by:
```
POST /redfish/v1/SessionService/Sessions {"UserName":"root", "Password": “0penBmc”}
```
Followed by redfish queries
Get /redfish/v1/AccountService
Tested user role persistency
Redfish service validator passes.
Signed-off-by: Ravi Teja <raviteja28031990@gmail.com>
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I575599c29358e32849446ce6ee7f62c8eb3885f6
Diffstat (limited to 'include/dbus_privileges.hpp')
-rw-r--r-- | include/dbus_privileges.hpp | 134 |
1 files changed, 20 insertions, 114 deletions
diff --git a/include/dbus_privileges.hpp b/include/dbus_privileges.hpp index fca4a137d3..07a1216cdc 100644 --- a/include/dbus_privileges.hpp +++ b/include/dbus_privileges.hpp @@ -6,9 +6,11 @@ #include "http_response.hpp" #include "logging.hpp" #include "routing/baserule.hpp" +#include "user_role_map.hpp" #include "utils/dbus_utils.hpp" #include <boost/url/format.hpp> +#include <sdbusplus/bus/match.hpp> #include <sdbusplus/unpack_properties.hpp> #include <memory> @@ -16,82 +18,6 @@ namespace crow { -// Populate session with user information. -inline bool - populateUserInfo(Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const dbus::utility::DBusPropertiesMap& userInfoMap) -{ - const std::string* userRolePtr = nullptr; - const bool* remoteUser = nullptr; - const bool* passwordExpired = nullptr; - const std::vector<std::string>* userGroups = nullptr; - - const bool success = sdbusplus::unpackPropertiesNoThrow( - redfish::dbus_utils::UnpackErrorPrinter(), userInfoMap, "UserPrivilege", - userRolePtr, "RemoteUser", remoteUser, "UserPasswordExpired", - passwordExpired, "UserGroups", userGroups); - - if (!success) - { - BMCWEB_LOG_ERROR("Failed to unpack user properties."); - asyncResp->res.result( - boost::beast::http::status::internal_server_error); - return false; - } - - if (req.session == nullptr) - { - return false; - } - - if (userRolePtr != nullptr) - { - req.session->userRole = *userRolePtr; - BMCWEB_LOG_DEBUG("userName = {} userRole = {}", req.session->username, - *userRolePtr); - } - - if (remoteUser == nullptr) - { - BMCWEB_LOG_ERROR("RemoteUser property missing or wrong type"); - asyncResp->res.result( - boost::beast::http::status::internal_server_error); - return false; - } - bool expired = false; - if (passwordExpired == nullptr) - { - if (!*remoteUser) - { - BMCWEB_LOG_ERROR("UserPasswordExpired property is expected for" - " local user but is missing or wrong type"); - asyncResp->res.result( - boost::beast::http::status::internal_server_error); - return false; - } - } - else - { - expired = *passwordExpired; - } - - // Set isConfigureSelfOnly based on D-Bus results. This - // ignores the results from both pamAuthenticateUser and the - // value from any previous use of this session. - req.session->isConfigureSelfOnly = expired; - - if (userGroups != nullptr) - { - // Populate session with user groups. - for (const auto& userGroup : *userGroups) - { - req.session->userGroups.emplace_back(userGroup); - } - } - - return true; -} inline bool isUserPrivileged(Request& req, @@ -128,62 +54,42 @@ inline bool return false; } - req.userRole = req.session->userRole; return true; } template <typename CallbackFn> -void afterGetUserInfo(Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - BaseRule& rule, CallbackFn&& callback, - const boost::system::error_code& ec, - const dbus::utility::DBusPropertiesMap& userInfoMap) +void validatePrivilege(Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + BaseRule& rule, CallbackFn&& callback) { - if (ec) + if (req.session == nullptr) { - BMCWEB_LOG_ERROR("GetUserInfo failed..."); - asyncResp->res.result( - boost::beast::http::status::internal_server_error); return; } - - if (!populateUserInfo(req, asyncResp, userInfoMap)) + std::string username = req.session->username; + UserFields props = + UserRoleMap::getInstance().getUserRole(req.session->username); + if (props.userRole) { - BMCWEB_LOG_ERROR("Failed to populate user information"); - asyncResp->res.result( - boost::beast::http::status::internal_server_error); - return; + req.session->userRole = props.userRole.value_or(""); + } + if (props.passwordExpired) + { + req.session->isConfigureSelfOnly = *props.passwordExpired; + } + if (props.userGroups) + { + req.session->userGroups = std::move(*props.userGroups); } if (!isUserPrivileged(req, asyncResp, rule)) { // User is not privileged - BMCWEB_LOG_ERROR("Insufficient Privilege"); + BMCWEB_LOG_WARNING("Insufficient Privilege"); asyncResp->res.result(boost::beast::http::status::forbidden); return; } callback(req); } -template <typename CallbackFn> -void validatePrivilege(Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - BaseRule& rule, CallbackFn&& callback) -{ - if (req.session == nullptr) - { - return; - } - std::string username = req.session->username; - crow::connections::systemBus->async_method_call( - [&req, asyncResp, &rule, callback(std::forward<CallbackFn>(callback))]( - const boost::system::error_code& ec, - const dbus::utility::DBusPropertiesMap& userInfoMap) mutable { - afterGetUserInfo(req, asyncResp, rule, - std::forward<CallbackFn>(callback), ec, userInfoMap); - }, - "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", - "xyz.openbmc_project.User.Manager", "GetUserInfo", username); -} - } // namespace crow |