Redfish(Authorization): Map the user role with the Redfish privileges
This commit gets the role of the user from the session object and
map it with the redfish privileges and then allow/reject the asked
operation depending on the userprivileges and the entity privileges.
Change-Id: I40be06c28e80b47fe76891cacf863f8495bace88
Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
diff --git a/crow/include/crow/http_request.h b/crow/include/crow/http_request.h
index 0ba0266..ef0bb28 100644
--- a/crow/include/crow/http_request.h
+++ b/crow/include/crow/http_request.h
@@ -1,5 +1,7 @@
#pragma once
+#include "sessions.hpp"
+
#include <boost/asio/io_context.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/websocket.hpp>
@@ -22,6 +24,8 @@
void* middlewareContext{};
boost::asio::io_context* ioService{};
+ std::shared_ptr<crow::persistent_data::UserSession> session;
+
Request(boost::beast::http::request<boost::beast::http::string_body>& req) :
req(req), body(req.body())
{
diff --git a/crow/include/crow/routing.h b/crow/include/crow/routing.h
index d1c33b5..c97c874 100644
--- a/crow/include/crow/routing.h
+++ b/crow/include/crow/routing.h
@@ -1,6 +1,7 @@
#pragma once
#include "privileges.hpp"
+#include "sessions.hpp"
#include <boost/container/flat_map.hpp>
#include <boost/container/small_vector.hpp>
@@ -1229,11 +1230,17 @@
<< (uint32_t)req.method() << " / "
<< rules[ruleIndex]->getMethods();
- // TODO: load user privileges from configuration as soon as its
- // available now we are granting all privileges to everyone.
- redfish::Privileges userPrivileges{"Login", "ConfigureManager",
- "ConfigureSelf", "ConfigureUsers",
- "ConfigureComponents"};
+ redfish::Privileges userPrivileges;
+ if (req.session != nullptr)
+ {
+ // Get the user role from the session.
+ const std::string& userRole = req.session->userRole;
+
+ BMCWEB_LOG_DEBUG << "USER ROLE=" << userRole;
+
+ // Get the user privileges from the role
+ userPrivileges = redfish::getUserPrivileges(userRole);
+ }
if (!rules[ruleIndex]->checkPrivileges(userPrivileges))
{
diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp
index 697e400..ee34d00 100644
--- a/include/token_authorization_middleware.hpp
+++ b/include/token_authorization_middleware.hpp
@@ -22,7 +22,6 @@
public:
struct Context
{
- std::shared_ptr<crow::persistent_data::UserSession> session;
};
void beforeHandle(crow::Request& req, Response& res, Context& ctx)
@@ -32,12 +31,12 @@
return;
}
- ctx.session = performXtokenAuth(req);
- if (ctx.session == nullptr)
+ req.session = performXtokenAuth(req);
+ if (req.session == nullptr)
{
- ctx.session = performCookieAuth(req);
+ req.session = performCookieAuth(req);
}
- if (ctx.session == nullptr)
+ if (req.session == nullptr)
{
std::string_view authHeader = req.getHeaderValue("Authorization");
if (!authHeader.empty())
@@ -45,16 +44,16 @@
// Reject any kind of auth other than basic or token
if (boost::starts_with(authHeader, "Token "))
{
- ctx.session = performTokenAuth(authHeader);
+ req.session = performTokenAuth(authHeader);
}
else if (boost::starts_with(authHeader, "Basic "))
{
- ctx.session = performBasicAuth(authHeader);
+ req.session = performBasicAuth(authHeader);
}
}
}
- if (ctx.session == nullptr)
+ if (req.session == nullptr)
{
BMCWEB_LOG_WARNING << "[AuthMiddleware] authorization failed";
@@ -93,12 +92,12 @@
// middleware, but because it is upstream, it doesn't have access to the
// session information. Should the data middleware persist the current
// user session?
- if (ctx.session != nullptr &&
- ctx.session->persistence ==
+ if (req.session != nullptr &&
+ req.session->persistence ==
crow::persistent_data::PersistenceType::SINGLE_REQUEST)
{
persistent_data::SessionStore::getInstance().removeSession(
- ctx.session);
+ req.session);
}
}
@@ -431,24 +430,22 @@
});
BMCWEB_ROUTE(app, "/logout")
- .methods(
- "POST"_method)([&](const crow::Request& req, crow::Response& res) {
- auto& session =
- app.template getContext<token_authorization::Middleware>(req)
- .session;
- if (session != nullptr)
- {
- res.jsonValue = {
- {"data", "User '" + session->username + "' logged out"},
- {"message", "200 OK"},
- {"status", "ok"}};
+ .methods("POST"_method)(
+ [&](const crow::Request& req, crow::Response& res) {
+ auto& session = req.session;
+ if (session != nullptr)
+ {
+ res.jsonValue = {
+ {"data", "User '" + session->username + "' logged out"},
+ {"message", "200 OK"},
+ {"status", "ok"}};
- persistent_data::SessionStore::getInstance().removeSession(
- session);
- }
- res.end();
- return;
- });
+ persistent_data::SessionStore::getInstance().removeSession(
+ session);
+ }
+ res.end();
+ return;
+ });
}
} // namespace token_authorization
} // namespace crow
diff --git a/redfish-core/include/privileges.hpp b/redfish-core/include/privileges.hpp
index ca44551..ec6e6a5 100644
--- a/redfish-core/include/privileges.hpp
+++ b/redfish-core/include/privileges.hpp
@@ -177,6 +177,29 @@
std::bitset<maxPrivilegeCount> privilegeBitset = 0;
};
+inline const Privileges& getUserPrivileges(const std::string& userRole)
+{
+ // Redfish privilege : Administrator
+ if (userRole == "priv-admin")
+ {
+ static Privileges admin{"Login", "ConfigureManager", "ConfigureSelf",
+ "ConfigureUsers", "ConfigureComponents"};
+ return admin;
+ }
+ else if (userRole == "priv-operator")
+ {
+ // Redfish privilege : Operator
+ static Privileges op{"Login", "ConfigureSelf", "ConfigureComponents"};
+ return op;
+ }
+ else
+ {
+ // Redfish privilege : Readonly
+ static Privileges readOnly{"Login", "ConfigureSelf"};
+ return readOnly;
+ }
+}
+
using OperationMap = boost::container::flat_map<boost::beast::http::verb,
std::vector<Privileges>>;