summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorVidya Satyamsetti <satyamsetti@google.com>2022-04-22 00:53:44 +0300
committerEd Tanous <ed@tanous.net>2022-05-20 04:59:46 +0300
commit4cee35e72cc593f7d407c110ed8c19afb78d279c (patch)
tree10134fc833a919e9d674d5396787594feac900c3 /include
parent9a5aceac206a550930204f102f1b84d808579407 (diff)
downloadbmcweb-4cee35e72cc593f7d407c110ed8c19afb78d279c.tar.xz
Add RootOfTrustCollection and RootOfTrust under Google service root.
These are Google only resources powered by Hoth DBus interface. The ComponentsProtected links is hardcoded for now. But it will be queried from DBus and interpreted accordingly in the future. TEST: $curl -u root:0penBmc -X GET http://[::1]:$PORT/google/v1/RootOfTrustCollection { "@odata.id": "/google/v1/RootOfTrustCollection", "@odata.type": "#RootOfTrustCollection.RootOfTrustCollection", "Members": [ { "@odata.id": "/google/v1/RootOfTrustCollection/Hoth" } ], "Members@odata.count": 1 } $ curl -u root:0penBmc -X GET http://[::1]:$PORT/google/v1/RootOfTrustCollection/Hoth { "@odata.id": "/google/v1/RootOfTrustCollection/Hoth", "@odata.type": "#RootOfTrust.v1_0_0.RootOfTrust", "Actions": { "#RootOfTrust.SendCommand": { "target": "/google/v1/RootOfTrustCollection/Hoth/Actions/RootOfTrust.SendCommand" } }, "Id": "Hoth", "Location": { "PartLocation": { "ServiceLabel": "Hoth", "Locationtype": "Embedded" } }, "Name": "RootOfTrust-Hoth", "Status": { "State": "Enabled" } $ curl -u root:0penBmc -X POST -d @req.json -H "Content-Type: application/json" http://[::1]:$PORT/google/v1/RootOfTrustCollection/Hoth/Actions/RootOfTrust.SendCommand { "CommandResponse": "033B0000" } Signed-off-by: Vidya Satyamsetti <satyamsetti@google.com> Change-Id: If64612468bb89e6d9251d848697608b7daf37339
Diffstat (limited to 'include')
-rw-r--r--include/google/google_service_root.hpp202
1 files changed, 192 insertions, 10 deletions
diff --git a/include/google/google_service_root.hpp b/include/google/google_service_root.hpp
index a80a50071b..42d2af9ddd 100644
--- a/include/google/google_service_root.hpp
+++ b/include/google/google_service_root.hpp
@@ -2,26 +2,208 @@
#include <app.hpp>
#include <async_resp.hpp>
+#include <error_messages.hpp>
#include <nlohmann/json.hpp>
+#include <utils/collection.hpp>
+#include <utils/hex_utils.hpp>
+#include <utils/json_utils.hpp>
+
+#include <vector>
namespace crow
{
namespace google_api
{
+constexpr const char* hothSearchPath = "/xyz/openbmc_project";
+constexpr const char* hothInterface = "xyz.openbmc_project.Control.Hoth";
+constexpr const char* rotCollectionPrefix = "/google/v1/RootOfTrustCollection";
+
+inline void getGoogleV1(const crow::Request& /*req*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
+ asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
+ asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
+ asyncResp->res.jsonValue["Name"] = "Google Service Root";
+ asyncResp->res.jsonValue["Version"] = "1.0.0";
+ asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
+ rotCollectionPrefix;
+}
+
+inline void getRootOfTrustCollection(
+ const crow::Request& /*req*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ asyncResp->res.jsonValue["@odata.id"] = rotCollectionPrefix;
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#RootOfTrustCollection.RootOfTrustCollection";
+ redfish::collection_util::getCollectionMembers(
+ asyncResp, rotCollectionPrefix, std::vector<const char*>{hothInterface},
+ hothSearchPath);
+}
+
+// Helper struct to identify a resolved D-Bus object interface
+struct ResolvedEntity
+{
+ std::string id;
+ std::string service;
+ std::string object;
+ const char* interface;
+};
+
+using ResolvedEntityHandler = std::function<void(
+ const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
+ const ResolvedEntity&)>;
+
+inline void resolveRoT(const std::string& command,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& rotId,
+ ResolvedEntityHandler&& entityHandler)
+{
+ auto validateFunc = [command, asyncResp, rotId,
+ entityHandler{std::forward<ResolvedEntityHandler>(
+ entityHandler)}](
+ const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType&
+ subtree) {
+ if (ec)
+ {
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::pair<
+ std::string,
+ std::vector<std::pair<std::string, std::vector<std::string>>>>&
+ object : subtree)
+ {
+ sdbusplus::message::object_path objPath(object.first);
+ if (objPath.filename() != rotId || object.second.empty())
+ {
+ continue;
+ }
+
+ ResolvedEntity resolvedEntity = {.id = rotId,
+ .service = object.second[0].first,
+ .object = object.first,
+ .interface = hothInterface};
+ entityHandler(command, asyncResp, resolvedEntity);
+ return;
+ }
+
+ // Couldn't find an object with that name. return an error
+ redfish::messages::resourceNotFound(
+ asyncResp->res, "#RootOfTrust.v1_0_0.RootOfTrust", rotId);
+ };
+
+ std::array<std::string, 1> hothIfaces = {hothInterface};
+ crow::connections::systemBus->async_method_call(
+ validateFunc, "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree", hothSearchPath,
+ /*depth=*/0, hothIfaces);
+}
+
+inline void populateRootOfTrustEntity(
+ const std::string& /*unused*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const ResolvedEntity& resolvedEntity)
+{
+ asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/google/v1/RootOfTrustCollection/" + resolvedEntity.id;
+
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
+ // Need to fix this later to a stabler property.
+ asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
+ asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
+ asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
+ "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
+ "/Actions/RootOfTrust.SendCommand";
+
+ asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+ resolvedEntity.id;
+ asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
+ "Embedded";
+}
+
+inline void getRootOfTrust(const crow::Request& /*unused*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
+{
+ resolveRoT("" /*Empty command*/, asyncResp, param,
+ populateRootOfTrustEntity);
+}
+
+inline void
+ invokeRoTCommand(const std::string& command,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const ResolvedEntity& resolvedEntity)
+{
+ auto handleFunc = [asyncResp](const boost::system::error_code ec,
+ std::vector<uint8_t>& responseBytes) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
+ << ec.message();
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+
+ asyncResp->res.jsonValue["CommandResponse"] =
+ bytesToHexString(responseBytes);
+ };
+ std::vector<uint8_t> bytes = hexStringToBytes(command);
+ if (bytes.empty())
+ {
+ BMCWEB_LOG_DEBUG << "Invalid command: " << command;
+ redfish::messages::actionParameterValueTypeError(command, "Command",
+ "SendCommand");
+ return;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ handleFunc, resolvedEntity.service, resolvedEntity.object,
+ resolvedEntity.interface, "SendHostCommand", bytes);
+}
+
+inline void sendRoTCommand(const crow::Request& request,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& rotId)
+{
+ std::string command;
+ if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
+ command))
+ {
+ BMCWEB_LOG_DEBUG << "Missing property Command.";
+ redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
+ "Command");
+ return;
+ }
+
+ resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
+}
inline void requestRoutes(App& app)
{
BMCWEB_ROUTE(app, "/google/v1/")
- .methods(boost::beast::http::verb::get)(
- [](const crow::Request&,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- asyncResp->res.jsonValue["@odata.type"] =
- "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
- asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
- asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
- asyncResp->res.jsonValue["Name"] = "Google Service Root";
- asyncResp->res.jsonValue["Version"] = "1.0.0";
- });
+ .methods(boost::beast::http::verb::get)(getGoogleV1);
+
+ BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
+ .privileges({{"ConfigureManager"}})
+ .methods(boost::beast::http::verb::get)(getRootOfTrustCollection);
+
+ BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
+ .privileges({{"ConfigureManager"}})
+ .methods(boost::beast::http::verb::get)(getRootOfTrust);
+
+ BMCWEB_ROUTE(
+ app,
+ "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
+ .privileges({{"ConfigureManager"}})
+ .methods(boost::beast::http::verb::post)(sendRoTCommand);
}
} // namespace google_api