summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunitha Harish <sunharis@in.ibm.com>2020-10-30 10:37:30 +0300
committerEd Tanous <ed@tanous.net>2020-11-10 19:30:11 +0300
commitc0ea7ae1c502fa2c67b0a58aee05b75581dafa7a (patch)
tree812b2d37bb153377a5897b434ddef7fc8137d7e9
parenta0744d38e93863ce3fb4bef2d4c70f9e9f640840 (diff)
downloadbmcweb-c0ea7ae1c502fa2c67b0a58aee05b75581dafa7a.tar.xz
Redfish Session : Support ClientOriginIPAddress
This commit implements the ClientOriginIPAddress property on the session resource. The IP address is persisted across the reboot Tested by: 1. Create session POST https://${bmc}/redfish/v1/SessionService/Sessions -d '{"UserName":<>, "Password":<>}' 2. Check the session gets updated with the ClientOriginIPAddress GET https://${bmc}/redfish/v1/SessionService/Sessions/<id> 3. Redfish validator passed 4. Create session and reboot the BMC to ensure the IP address is persisted 5. Tested the basic auth populates the clientIp at req Signed-off-by: Sunitha Harish <sunharis@in.ibm.com> Change-Id: Iaa60d0657c991bde4bcf6c86819055c71c92e421
-rw-r--r--http/http_connection.hpp29
-rw-r--r--http/http_request.hpp2
-rw-r--r--include/authorization.hpp9
-rw-r--r--include/login_routes.hpp2
-rw-r--r--include/persistent_data.hpp1
-rw-r--r--redfish-core/lib/redfish_sessions.hpp9
-rw-r--r--static/redfish/v1/JsonSchemas/OemSession/index.json6
-rw-r--r--static/redfish/v1/schema/OemSession_v1.xml4
8 files changed, 41 insertions, 21 deletions
diff --git a/http/http_connection.hpp b/http/http_connection.hpp
index ec8e9d5233..6610beec9f 100644
--- a/http/http_connection.hpp
+++ b/http/http_connection.hpp
@@ -241,7 +241,8 @@ class Connection :
session =
persistent_data::SessionStore::getInstance()
.generateUserSession(
- sslUser, persistent_data::PersistenceType::TIMEOUT);
+ sslUser, persistent_data::PersistenceType::TIMEOUT,
+ false, req->ipAddress.to_string());
if (auto sp = session.lock())
{
BMCWEB_LOG_DEBUG << this
@@ -278,6 +279,10 @@ class Connection :
{
startDeadline(0);
+
+ // Fetch the client IP address
+ readClientIp();
+
// TODO(ed) Abstract this to a more clever class with the idea of an
// asynchronous "start"
if constexpr (std::is_same_v<Adaptor,
@@ -319,7 +324,7 @@ class Connection :
BMCWEB_LOG_INFO << "Request: "
<< " " << this << " HTTP/" << req->version() / 10 << "."
<< req->version() % 10 << ' ' << req->methodString()
- << " " << req->target();
+ << " " << req->target() << " " << req->ipAddress;
needToCallAfterHandlers = false;
@@ -461,6 +466,26 @@ class Connection :
res.completeRequestHandler = nullptr;
}
+ void readClientIp()
+ {
+ boost::system::error_code ec;
+ BMCWEB_LOG_DEBUG << "Fetch the client IP address";
+ boost::asio::ip::tcp::endpoint endpoint =
+ boost::beast::get_lowest_layer(adaptor).remote_endpoint(ec);
+
+ if (ec)
+ {
+ // If remote endpoint fails keep going. "ClientOriginIPAddress"
+ // will be empty.
+ BMCWEB_LOG_ERROR << "Failed to get the client's IP Address. ec : "
+ << ec;
+ }
+ else
+ {
+ req->ipAddress = endpoint.address();
+ }
+ }
+
private:
void doReadHeaders()
{
diff --git a/http/http_request.hpp b/http/http_request.hpp
index e5c0c9e982..8bcce064db 100644
--- a/http/http_request.hpp
+++ b/http/http_request.hpp
@@ -4,6 +4,7 @@
#include "sessions.hpp"
#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/address.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/string_body.hpp>
#include <boost/beast/websocket.hpp>
@@ -24,6 +25,7 @@ struct Request
const std::string& body;
boost::asio::io_context* ioService{};
+ boost::asio::ip::address ipAddress{};
std::shared_ptr<persistent_data::UserSession> session;
diff --git a/include/authorization.hpp b/include/authorization.hpp
index e965508e08..0f73e967cb 100644
--- a/include/authorization.hpp
+++ b/include/authorization.hpp
@@ -35,7 +35,8 @@ static void cleanupTempSession(Request& req)
}
static std::shared_ptr<persistent_data::UserSession>
- performBasicAuth(std::string_view auth_header)
+ performBasicAuth(const boost::asio::ip::address& clientIp,
+ std::string_view auth_header)
{
BMCWEB_LOG_DEBUG << "[AuthMiddleware] Basic authentication";
@@ -60,6 +61,8 @@ static std::shared_ptr<persistent_data::UserSession>
std::string pass = authData.substr(separator);
BMCWEB_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user;
+ BMCWEB_LOG_DEBUG << "[AuthMiddleware] User IPAddress: "
+ << clientIp.to_string();
int pamrc = pamAuthenticateUser(user, pass);
bool isConfigureSelfOnly = pamrc == PAM_NEW_AUTHTOK_REQD;
@@ -76,7 +79,7 @@ static std::shared_ptr<persistent_data::UserSession>
// calling directly into pam for every request
return persistent_data::SessionStore::getInstance().generateUserSession(
user, persistent_data::PersistenceType::SINGLE_REQUEST,
- isConfigureSelfOnly);
+ isConfigureSelfOnly, clientIp.to_string());
}
static std::shared_ptr<persistent_data::UserSession>
@@ -269,7 +272,7 @@ static void authenticate(
else if (boost::starts_with(authHeader, "Basic ") &&
authMethodsConfig.basic)
{
- req.session = performBasicAuth(authHeader);
+ req.session = performBasicAuth(req.ipAddress, authHeader);
}
}
}
diff --git a/include/login_routes.hpp b/include/login_routes.hpp
index 1f7b35a3b4..6879de0d47 100644
--- a/include/login_routes.hpp
+++ b/include/login_routes.hpp
@@ -141,7 +141,7 @@ inline void requestRoutes(App& app)
.generateUserSession(
username,
persistent_data::PersistenceType::TIMEOUT,
- isConfigureSelfOnly);
+ isConfigureSelfOnly, req.ipAddress.to_string());
if (looksLikePhosphorRest)
{
diff --git a/include/persistent_data.hpp b/include/persistent_data.hpp
index 19c424a202..0ff0c7e1df 100644
--- a/include/persistent_data.hpp
+++ b/include/persistent_data.hpp
@@ -193,6 +193,7 @@ class ConfigFile
{"session_token", p.second->sessionToken},
{"username", p.second->username},
{"csrf_token", p.second->csrfToken},
+ {"client_ip", p.second->clientIp},
#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
{"client_id", p.second->clientId},
#endif
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index e3259895d2..c38f1026d2 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -60,15 +60,15 @@ class Sessions : public Node
res.jsonValue["UserName"] = session->username;
res.jsonValue["@odata.id"] =
"/redfish/v1/SessionService/Sessions/" + session->uniqueId;
- res.jsonValue["@odata.type"] = "#Session.v1_0_2.Session";
+ res.jsonValue["@odata.type"] = "#Session.v1_3_0.Session";
res.jsonValue["Name"] = "User Session";
res.jsonValue["Description"] = "Manager User Session";
+ res.jsonValue["ClientOriginIPAddress"] = session->clientIp;
+#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
res.jsonValue["Oem"]["OpenBMC"]["@odata.type"] =
"#OemSession.v1_0_0.Session";
-#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
res.jsonValue["Oem"]["OpenBMC"]["ClientID"] = session->clientId;
#endif
- res.jsonValue["Oem"]["OpenBMC"]["ClientOriginIP"] = session->clientIp;
res.end();
}
@@ -174,7 +174,6 @@ class SessionCollection : public Node
std::string password;
std::optional<nlohmann::json> oemObject;
std::string clientId;
- std::string clientIp;
if (!json_util::readJson(req, res, "UserName", username, "Password",
password, "Oem", oemObject))
{
@@ -231,7 +230,7 @@ class SessionCollection : public Node
std::shared_ptr<persistent_data::UserSession> session =
persistent_data::SessionStore::getInstance().generateUserSession(
username, persistent_data::PersistenceType::TIMEOUT,
- isConfigureSelfOnly, clientId, clientIp);
+ isConfigureSelfOnly, clientId, req.ipAddress.to_string());
res.addHeader("X-Auth-Token", session->sessionToken);
res.addHeader("Location", "/redfish/v1/SessionService/Sessions/" +
session->uniqueId);
diff --git a/static/redfish/v1/JsonSchemas/OemSession/index.json b/static/redfish/v1/JsonSchemas/OemSession/index.json
index c80e34003c..8eefd952f3 100644
--- a/static/redfish/v1/JsonSchemas/OemSession/index.json
+++ b/static/redfish/v1/JsonSchemas/OemSession/index.json
@@ -28,12 +28,6 @@
"readonly": true,
"type" : "string"
},
- "ClientOriginIP" : {
- "description": "The IP address where the Session was created from.",
- "longDescription": "This property shall contain the IP address where the client created the session from.",
- "readonly": true,
- "type": "string"
- },
"type": "object"
}
}
diff --git a/static/redfish/v1/schema/OemSession_v1.xml b/static/redfish/v1/schema/OemSession_v1.xml
index cc74848b81..f02f8617eb 100644
--- a/static/redfish/v1/schema/OemSession_v1.xml
+++ b/static/redfish/v1/schema/OemSession_v1.xml
@@ -32,10 +32,6 @@
<Annotation Term="OData.Description" String="The Id of the client creating this session."/>
<Annotation Term="OData.LongDescription" String="This will be the unique identifier set by the client."/>
</Property>
- <Property Name="ClientOriginIP" Type="Edm.String">
- <Annotation Term="OData.Description" String="The IP address where the Session was created from."/>
- <Annotation Term="OData.LongDescription" String="This property shall contain the IP address where the client created the session from."/>
- </Property>
</EntityType>
</Schema>