diff options
author | Ed Tanous <ed.tanous@intel.com> | 2018-09-20 15:54:36 -0700 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2018-10-08 17:27:18 +0000 |
commit | 04ae99ec1fbfea2e07c0db4174712d0873d2e91c (patch) | |
tree | 3e41a606d52b6b4d09c36e65ecc8026468ea38cf /redfish-core/lib/account_service.hpp | |
parent | 06e086d9c5564346edd082fc69ba23b9365bdcee (diff) | |
download | bmcweb-04ae99ec1fbfea2e07c0db4174712d0873d2e91c.tar.gz bmcweb-04ae99ec1fbfea2e07c0db4174712d0873d2e91c.zip |
Implement AccountService POST
This commit implements POST events for AccountService/Accounts to aid in
the creation of users. It utilizes the DBus User manager API to do its
work, as well as PAM to set the password.
Tested By:
Created users of varying field counts to test all cases.
{"UserName": "foobar", "Password": "superpassword", "RoleId": "Administrator"}
Observed a user get enabled as Administrator
{"UserName": "foobar", "Password": "superpassword"}
Observed user created enabled, with default user level of "User"
{"UserName": "foobar", "Password": "superpassword", "Enabled": false}
observed a user get created as disabled
{"UserName": "foobar", "Password": "password"}
Observed error due to bad password security
Change-Id: I09522c1ddd0f531e6201e7786c6d376d3b0a89e6
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Diffstat (limited to 'redfish-core/lib/account_service.hpp')
-rw-r--r-- | redfish-core/lib/account_service.hpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp index d44d4a3..3d44278 100644 --- a/redfish-core/lib/account_service.hpp +++ b/redfish-core/lib/account_service.hpp @@ -134,6 +134,197 @@ class AccountsCollection : public Node "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); } + void doPost(crow::Response& res, const crow::Request& req, + const std::vector<std::string>& params) override + { + auto asyncResp = std::make_shared<AsyncResp>(res); + + nlohmann::json patchRequest; + if (!json_util::processJsonFromRequest(res, req, patchRequest)) + { + return; + } + + const std::string* username = nullptr; + const std::string* password = nullptr; + // Default to user + std::string privilege = "priv-user"; + // default to enabled + bool enabled = true; + for (const auto& item : patchRequest.items()) + { + if (item.key() == "UserName") + { + username = item.value().get_ptr<const std::string*>(); + if (username == nullptr) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::propertyValueFormatError(item.value().dump(), + item.key())); + asyncResp->res.result( + boost::beast::http::status::bad_request); + return; + } + } + else if (item.key() == "Enabled") + { + const bool* enabledJson = item.value().get_ptr<const bool*>(); + if (enabledJson == nullptr) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::propertyValueFormatError(item.value().dump(), + item.key())); + asyncResp->res.result( + boost::beast::http::status::bad_request); + return; + } + enabled = *enabledJson; + } + else if (item.key() == "Password") + { + password = item.value().get_ptr<const std::string*>(); + if (password == nullptr) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::propertyValueFormatError(item.value().dump(), + item.key())); + asyncResp->res.result( + boost::beast::http::status::bad_request); + return; + } + } + else if (item.key() == "RoleId") + { + const std::string* roleIdJson = + item.value().get_ptr<const std::string*>(); + if (roleIdJson == nullptr) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::propertyValueFormatError(item.value().dump(), + item.key())); + asyncResp->res.result( + boost::beast::http::status::bad_request); + return; + } + const char* priv = getRoleIdFromPrivilege(*roleIdJson); + if (priv == nullptr) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::propertyValueNotInList(*roleIdJson, + item.key())); + asyncResp->res.result( + boost::beast::http::status::bad_request); + return; + } + privilege = priv; + } + else + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::propertyNotWritable(item.key())); + asyncResp->res.result(boost::beast::http::status::bad_request); + return; + } + } + + if (username == nullptr) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::createFailedMissingReqProperties("UserName")); + asyncResp->res.result(boost::beast::http::status::bad_request); + return; + } + + if (password == nullptr) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::createFailedMissingReqProperties("Password")); + asyncResp->res.result(boost::beast::http::status::bad_request); + return; + } + + crow::connections::systemBus->async_method_call( + [asyncResp, username{std::string(*username)}, + password{std::string(*password)}]( + const boost::system::error_code ec) { + if (ec) + { + messages::addMessageToErrorJson( + asyncResp->res.jsonValue, + messages::resourceAlreadyExists( + "#ManagerAccount.v1_0_3.ManagerAccount", "UserName", + username)); + asyncResp->res.result( + boost::beast::http::status::bad_request); + return; + } + + if (!pamUpdatePassword(username, password)) + { + // At this point we have a user that's been created, but the + // password set failed. Something is wrong, so delete the + // user that we've already created + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) + { + asyncResp->res.result( + boost::beast::http::status:: + internal_server_error); + return; + } + + asyncResp->res.result( + boost::beast::http::status::bad_request); + }, + "xyz.openbmc_project.User.Manager", + "/xyz/openbmc_project/user/" + username, + "xyz.openbmc_project.Object.Delete", "Delete"); + + BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; + return; + } + + messages::addMessageToJsonRoot(asyncResp->res.jsonValue, + messages::created()); + asyncResp->res.addHeader( + "Location", + "/redfish/v1/AccountService/Accounts/" + username); + }, + "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", + "xyz.openbmc_project.User.Manager", "CreateUser", *username, + std::array<const char*, 4>{"ipmi", "redfish", "ssh", "web"}, + privilege, enabled); + } + + static const char* getRoleIdFromPrivilege(boost::beast::string_view role) + { + if (role == "Administrator") + { + return "priv-admin"; + } + else if (role == "Callback") + { + return "priv-callback"; + } + else if (role == "User") + { + return "priv-user"; + } + else if (role == "Operator") + { + return "priv-operator"; + } + return nullptr; + } }; template <typename Callback> |