Redfish: Populate the RemoteRoleMapping prop under AccountService schema
Get request on account service gets the RemoteRoleMapping info.
Tested:
1.Ran redifsh validator and there are no errors
2.GET Request on AccountService would add below given info if RoleMapping data
is configured on the system.
GET
"RemoteRoleMapping": [
{
"LocalRole": "<configured role>",
"RemoteUser": "<configured user>"
},
],
Change-Id: Ie22f0bb520de795d31a9aba76a56fe88886ed50b
Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
Signed-off-by: Nagaraju Goruganti <ngorugan@in.ibm.com>
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index 784cbd2..6cbbdce 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -43,6 +43,12 @@
constexpr const char* mapperObjectPath = "/xyz/openbmc_project/object_mapper";
constexpr const char* mapperIntf = "xyz.openbmc_project.ObjectMapper";
+struct LDAPRoleMapData
+{
+ std::string groupName;
+ std::string privilege;
+};
+
struct LDAPConfigData
{
std::string uri{};
@@ -53,6 +59,7 @@
bool serviceEnabled = false;
std::string userNameAttribute{};
std::string groupAttribute{};
+ std::vector<std::pair<std::string, LDAPRoleMapData>> groupRoleList;
};
using ManagedObjectType = std::vector<std::pair<
@@ -63,7 +70,7 @@
using GetObjectType =
std::vector<std::pair<std::string, std::vector<std::string>>>;
-inline std::string getPrivilegeFromRoleId(std::string_view role)
+inline std::string getRoleIdFromPrivilege(std::string_view role)
{
if (role == "priv-admin")
{
@@ -83,7 +90,7 @@
}
return "";
}
-inline std::string getRoleIdFromPrivilege(std::string_view role)
+inline std::string getPrivilegeFromRoleId(std::string_view role)
{
if (role == "Administrator")
{
@@ -125,7 +132,20 @@
{"UsernameAttribute", confData.userNameAttribute},
{"GroupsAttribute", confData.groupAttribute}}}}},
};
+
json_response[ldapType].update(std::move(ldap));
+
+ nlohmann::json& roleMapArray = json_response[ldapType]["RemoteRoleMapping"];
+ roleMapArray = nlohmann::json::array();
+ for (auto& obj : confData.groupRoleList)
+ {
+ BMCWEB_LOG_DEBUG << "Pushing the data groupName="
+ << obj.second.groupName << "\n";
+ roleMapArray.push_back(
+ {nlohmann::json::array({"RemoteGroup", obj.second.groupName}),
+ nlohmann::json::array(
+ {"LocalRole", getRoleIdFromPrivilege(obj.second.privilege)})});
+ }
}
/**
@@ -136,154 +156,176 @@
inline void getLDAPConfigData(const std::string& ldapType,
CallbackFunc&& callback)
{
- auto getConfig = [callback,
- ldapType](const boost::system::error_code error_code,
- const ManagedObjectType& ldapObjects) {
- LDAPConfigData confData{};
- if (error_code)
- {
- callback(false, confData, ldapType);
- BMCWEB_LOG_ERROR << "D-Bus responses error: " << error_code;
- return;
- }
- std::string ldapDbusType;
- if (ldapType == "LDAP")
- {
- ldapDbusType = "xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap";
- }
- else if (ldapType == "ActiveDirectory")
- {
- ldapDbusType = "xyz.openbmc_project.User.Ldap.Config.Type."
- "ActiveDirectory";
- }
- else
- {
- BMCWEB_LOG_ERROR << "Can't get the DbusType for the given type="
- << ldapType;
- callback(false, confData, ldapType);
- return;
- }
-
- std::string ldapEnableInterfaceStr = ldapEnableInterface;
- std::string ldapConfigInterfaceStr = ldapConfigInterface;
-
- for (const auto& object : ldapObjects)
- {
- // let's find the object whose ldap type is equal to the given type
- auto intfit = object.second.find(ldapConfigInterfaceStr);
- if (intfit == object.second.end())
- {
- continue;
- }
- auto propit = intfit->second.find("LDAPType");
- if (propit == intfit->second.end())
- {
- continue;
- }
-
- const std::string* value =
- std::get_if<std::string>(&(propit->second));
- if (value == nullptr || (*value) != ldapDbusType)
- {
-
- // this is not the interested configuration,
- // let's move on to the other configuration.
- continue;
- }
- else
- {
- confData.serverType = *value;
- }
-
- for (const auto& interface : object.second)
- {
- if (interface.first == ldapEnableInterfaceStr)
- {
- // rest of the properties are string.
- for (const auto& property : interface.second)
- {
- if (property.first == "Enabled")
- {
- const bool* value =
- std::get_if<bool>(&property.second);
- if (value == nullptr)
- {
- continue;
- }
- confData.serviceEnabled = *value;
- break;
- }
- }
- }
- else if (interface.first == ldapConfigInterfaceStr)
- {
-
- for (const auto& property : interface.second)
- {
- const std::string* value =
- std::get_if<std::string>(&property.second);
- if (value == nullptr)
- {
- continue;
- }
- if (property.first == "LDAPServerURI")
- {
- confData.uri = *value;
- }
- else if (property.first == "LDAPBindDN")
- {
- confData.bindDN = *value;
- }
- else if (property.first == "LDAPBaseDN")
- {
- confData.baseDN = *value;
- }
- else if (property.first == "LDAPSearchScope")
- {
- confData.searchScope = *value;
- }
- else if (property.first == "GroupNameAttribute")
- {
- confData.groupAttribute = *value;
- }
- else if (property.first == "UserNameAttribute")
- {
- confData.userNameAttribute = *value;
- }
- }
- }
- }
- if (confData.serverType == ldapDbusType)
- {
- callback(true, confData, ldapType);
- break;
- }
- }
- };
- auto getServiceName = [callback, ldapType, getConfig(std::move(getConfig))](
- const boost::system::error_code ec,
- const GetObjectType& resp) {
- LDAPConfigData confData{};
- if (ec || resp.empty())
- {
- BMCWEB_LOG_ERROR
- << "DBUS response error during getting of service name: " << ec;
- callback(false, confData, ldapType);
- return;
- }
- std::string service = resp.begin()->first;
- crow::connections::systemBus->async_method_call(
- std::move(getConfig), service, ldapRootObject, dbusObjManagerIntf,
- "GetManagedObjects");
- };
-
- const std::array<std::string, 2> interfaces = {ldapEnableInterface,
+ const std::array<const char*, 2> interfaces = {ldapEnableInterface,
ldapConfigInterface};
crow::connections::systemBus->async_method_call(
- std::move(getServiceName), mapperBusName, mapperObjectPath, mapperIntf,
- "GetObject", ldapConfigObject, interfaces);
+ [callback, ldapType](const boost::system::error_code ec,
+ const GetObjectType& resp) {
+ LDAPConfigData confData{};
+ if (ec || resp.empty())
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error during getting of "
+ "service name: "
+ << ec;
+ callback(false, confData, ldapType);
+ return;
+ }
+ std::string service = resp.begin()->first;
+ crow::connections::systemBus->async_method_call(
+ [callback, ldapType](const boost::system::error_code error_code,
+ const ManagedObjectType& ldapObjects) {
+ LDAPConfigData confData{};
+ if (error_code)
+ {
+ callback(false, confData, ldapType);
+ BMCWEB_LOG_ERROR << "D-Bus responses error: "
+ << error_code;
+ return;
+ }
+
+ std::string ldapDbusType;
+ std::string searchString;
+
+ if (ldapType == "LDAP")
+ {
+ ldapDbusType = "xyz.openbmc_project.User.Ldap.Config."
+ "Type.OpenLdap";
+ searchString = "openldap";
+ }
+ else if (ldapType == "ActiveDirectory")
+ {
+ ldapDbusType =
+ "xyz.openbmc_project.User.Ldap.Config.Type."
+ "ActiveDirectory";
+ searchString = "active_directory";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR
+ << "Can't get the DbusType for the given type="
+ << ldapType;
+ callback(false, confData, ldapType);
+ return;
+ }
+
+ std::string ldapEnableInterfaceStr = ldapEnableInterface;
+ std::string ldapConfigInterfaceStr = ldapConfigInterface;
+
+ for (const auto& object : ldapObjects)
+ {
+ // let's find the object whose ldap type is equal to the
+ // given type
+ if (object.first.str.find(searchString) ==
+ std::string::npos)
+ {
+ continue;
+ }
+
+ for (const auto& interface : object.second)
+ {
+ if (interface.first == ldapEnableInterfaceStr)
+ {
+ // rest of the properties are string.
+ for (const auto& property : interface.second)
+ {
+ if (property.first == "Enabled")
+ {
+ const bool* value =
+ std::get_if<bool>(&property.second);
+ if (value == nullptr)
+ {
+ continue;
+ }
+ confData.serviceEnabled = *value;
+ break;
+ }
+ }
+ }
+ else if (interface.first == ldapConfigInterfaceStr)
+ {
+
+ for (const auto& property : interface.second)
+ {
+ const std::string* value =
+ std::get_if<std::string>(
+ &property.second);
+ if (value == nullptr)
+ {
+ continue;
+ }
+ if (property.first == "LDAPServerURI")
+ {
+ confData.uri = *value;
+ }
+ else if (property.first == "LDAPBindDN")
+ {
+ confData.bindDN = *value;
+ }
+ else if (property.first == "LDAPBaseDN")
+ {
+ confData.baseDN = *value;
+ }
+ else if (property.first ==
+ "LDAPSearchScope")
+ {
+ confData.searchScope = *value;
+ }
+ else if (property.first ==
+ "GroupNameAttribute")
+ {
+ confData.groupAttribute = *value;
+ }
+ else if (property.first ==
+ "UserNameAttribute")
+ {
+ confData.userNameAttribute = *value;
+ }
+ else if (property.first == "LDAPType")
+ {
+ confData.serverType = *value;
+ }
+ }
+ }
+ else if (interface.first ==
+ "xyz.openbmc_project.User."
+ "PrivilegeMapperEntry")
+ {
+ LDAPRoleMapData roleMapData{};
+ for (const auto& property : interface.second)
+ {
+ const std::string* value =
+ std::get_if<std::string>(
+ &property.second);
+
+ if (value == nullptr)
+ {
+ continue;
+ }
+
+ if (property.first == "GroupName")
+ {
+ roleMapData.groupName = *value;
+ }
+ else if (property.first == "Privilege")
+ {
+ roleMapData.privilege = *value;
+ }
+ }
+
+ confData.groupRoleList.push_back(std::make_pair(
+ object.first.str, roleMapData));
+ }
+ }
+ }
+ callback(true, confData, ldapType);
+ },
+ service, ldapRootObject, dbusObjManagerIntf,
+ "GetManagedObjects");
+ },
+ mapperBusName, mapperObjectPath, mapperIntf, "GetObject",
+ ldapConfigObject, interfaces);
}
class AccountService : public Node
@@ -1029,7 +1071,7 @@
return;
}
- std::string priv = getRoleIdFromPrivilege(*roleId);
+ std::string priv = getPrivilegeFromRoleId(*roleId);
if (priv.empty())
{
messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId");
@@ -1050,9 +1092,9 @@
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
+ // 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)
@@ -1186,9 +1228,9 @@
}
else if (property.first == "UserPrivilege")
{
- const std::string* userRolePtr =
+ const std::string* userPrivPtr =
std::get_if<std::string>(&property.second);
- if (userRolePtr == nullptr)
+ if (userPrivPtr == nullptr)
{
BMCWEB_LOG_ERROR
<< "UserPrivilege wasn't a "
@@ -1196,20 +1238,20 @@
messages::internalError(asyncResp->res);
return;
}
- std::string priv =
- getPrivilegeFromRoleId(*userRolePtr);
- if (priv.empty())
+ std::string role =
+ getRoleIdFromPrivilege(*userPrivPtr);
+ if (role.empty())
{
BMCWEB_LOG_ERROR << "Invalid user role";
messages::internalError(asyncResp->res);
return;
}
- asyncResp->res.jsonValue["RoleId"] = priv;
+ asyncResp->res.jsonValue["RoleId"] = role;
asyncResp->res.jsonValue["Links"]["Role"] = {
{"@odata.id", "/redfish/v1/AccountService/"
"Roles/" +
- priv}};
+ role}};
}
}
}
@@ -1250,8 +1292,8 @@
if (!newUserName)
{
- // If the username isn't being updated, we can update the properties
- // directly
+ // If the username isn't being updated, we can update the
+ // properties directly
updateUserProperties(asyncResp, username, password, enabled, roleId,
locked);
return;
@@ -1335,7 +1377,7 @@
if (roleId)
{
- std::string priv = getRoleIdFromPrivilege(*roleId);
+ std::string priv = getPrivilegeFromRoleId(*roleId);
if (priv.empty())
{
messages::propertyValueNotInList(asyncResp->res,
@@ -1364,8 +1406,8 @@
if (locked)
{
// admin can unlock the account which is locked by
- // successive authentication failures but admin should not
- // be allowed to lock an account.
+ // successive authentication failures but admin should
+ // not be allowed to lock an account.
if (*locked)
{
messages::propertyValueNotInList(asyncResp->res, "true",