From 24c8542dce451ba02df51e83174dbcdabc6bf09f Mon Sep 17 00:00:00 2001 From: Ratan Gupta Date: Wed, 30 Jan 2019 19:41:24 +0530 Subject: Redfish: Add the PATCH support for user locked property. With this commit PATCH operation on the Locked property of ManagerAccount schema would allow the user/admin to unlock an account,however admin would not be allowed to lock an account as account can be locked automatically by configured consecutive authentication failures. TestedBy: Run the following patch request to test the locked property. GET https://${BMC_IP}/redfish/v1/AccountService/Accounts/esalinux0 { "@odata.context": "/redfish/v1/$metadata#ManagerAccount.ManagerAccount", "@odata.id": "/redfish/v1/AccountService/Accounts/esalinux0", "@odata.type": "#ManagerAccount.v1_0_3.ManagerAccount", "Description": "User Account", "Enabled": true, "Id": "esalinux0", "Links": { "Role": { "@odata.id": "/redfish/v1/AccountService/Roles/Administrator" } }, "Locked": true, "Locked@Redfish.AllowableValues": [ false ], "Name": "User Account", "Password": null, "RoleId": "Administrator", "UserName": "esalinux0" } PATCH https://${BMC_IP}/redfish/v1/AccountService/Accounts/esalinux0 -d '{"Locked" : false}' { "@Message.ExtendedInfo": [ { "@odata.type": "/redfish/v1/$metadata#Message.v1_0_0.Message", "Message": "Successfully Completed Request", "MessageArgs": [], "MessageId": "Base.1.4.0.Success", "Resolution": "None", "Severity": "OK" } ] } Change-Id: I5d7a3d8f6330bbf01292ed4079542a1c65c9cc35 Signed-off-by: Ratan Gupta --- redfish-core/lib/account_service.hpp | 145 ++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 45 deletions(-) diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp index d9388cf..f698901 100644 --- a/redfish-core/lib/account_service.hpp +++ b/redfish-core/lib/account_service.hpp @@ -16,6 +16,7 @@ #pragma once #include "node.hpp" +#include #include #include #include @@ -455,6 +456,9 @@ class ManagerAccount : public Node } asyncResp->res.jsonValue["Locked"] = *userLocked; + asyncResp->res.jsonValue + ["Locked@Redfish.AllowableValues"] = { + false}; } else if (property.first == "UserPrivilege") { @@ -510,9 +514,10 @@ class ManagerAccount : public Node std::optional password; std::optional enabled; std::optional roleId; + std::optional locked; if (!json_util::readJson(req, res, "UserName", newUserName, "Password", - password, "RoleId", roleId, "Enabled", - enabled)) + password, "RoleId", roleId, "Enabled", enabled, + "Locked", locked)) { return; } @@ -523,8 +528,8 @@ class ManagerAccount : public Node { // If the username isn't being updated, we can update the properties // directly - updateUserProperties(asyncResp, username, password, enabled, - roleId); + updateUserProperties(asyncResp, username, password, enabled, roleId, + locked); return; } else @@ -532,7 +537,7 @@ class ManagerAccount : public Node crow::connections::systemBus->async_method_call( [this, asyncResp, username, password(std::move(password)), roleId(std::move(roleId)), enabled(std::move(enabled)), - newUser{std::string(*newUserName)}]( + newUser{std::string(*newUserName)}, locked(std::move(locked))]( const boost::system::error_code ec) { if (ec) { @@ -544,7 +549,7 @@ class ManagerAccount : public Node } updateUserProperties(asyncResp, newUser, password, enabled, - roleId); + roleId, locked); }, "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", "xyz.openbmc_project.User.Manager", "RenameUser", username, @@ -556,7 +561,8 @@ class ManagerAccount : public Node const std::string& username, std::optional password, std::optional enabled, - std::optional roleId) + std::optional roleId, + std::optional locked) { if (password) { @@ -568,52 +574,101 @@ class ManagerAccount : public Node } } - if (enabled) - { - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) + std::string dbusObjectPath = "/xyz/openbmc_project/user/" + username; + dbus::utility::escapePathForDbus(dbusObjectPath); + + checkDbusPathExists( + dbusObjectPath, + [dbusObjectPath(std::move(dbusObjectPath)), username, + password(std::move(password)), roleId(std::move(roleId)), + enabled(std::move(enabled)), locked(std::move(locked)), + asyncResp{std::move(asyncResp)}](int rc) { + if (!rc) + { + messages::invalidObject(asyncResp->res, username.c_str()); + return; + } + if (enabled) + { + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " + << ec; + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); + return; + }, + "xyz.openbmc_project.User.Manager", + dbusObjectPath.c_str(), + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.User.Attributes", "UserEnabled", + std::variant{*enabled}); + } + + if (roleId) + { + std::string priv = getRoleIdFromPrivilege(*roleId); + if (priv.empty()) { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); + messages::propertyValueNotInList(asyncResp->res, + *roleId, "RoleId"); return; } - messages::success(asyncResp->res); - return; - }, - "xyz.openbmc_project.User.Manager", - "/xyz/openbmc_project/user/" + username, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.User.Attributes", "UserEnabled", - std::variant{*enabled}); - } - if (roleId) - { - std::string priv = getRoleIdFromPrivilege(*roleId); - if (priv.empty()) - { - messages::propertyValueNotInList(asyncResp->res, *roleId, - "RoleId"); - return; - } + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " + << ec; + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); + }, + "xyz.openbmc_project.User.Manager", + dbusObjectPath.c_str(), + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.User.Attributes", "UserPrivilege", + std::variant{priv}); + } - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) + if (locked) + { + // admin can unlock the account which is locked by + // successive authentication failures but admin should not + // be allowed to lock an account. + if (*locked) { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); + messages::propertyValueNotInList(asyncResp->res, "true", + "Locked"); return; } - messages::success(asyncResp->res); - }, - "xyz.openbmc_project.User.Manager", - "/xyz/openbmc_project/user/" + username, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.User.Attributes", "UserPrivilege", - std::variant{priv}); - } + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " + << ec; + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); + return; + }, + "xyz.openbmc_project.User.Manager", + dbusObjectPath.c_str(), + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.User.Attributes", + "UserLockedForFailedAttempt", + sdbusplus::message::variant{*locked}); + } + }); } void doDelete(crow::Response& res, const crow::Request& req, -- cgit v1.2.3