blob: cbcf15d78e6873536adc3d5a948bc71eb8745f4a [file] [log] [blame]
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -07001#pragma once
2
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "app.hpp"
4#include "async_resp.hpp"
5#include "dbus_utility.hpp"
6#include "error_messages.hpp"
7#include "utils/collection.hpp"
8#include "utils/hex_utils.hpp"
9#include "utils/json_utils.hpp"
10
George Liue99073f2022-12-09 11:06:16 +080011#include <boost/system/error_code.hpp>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070012#include <nlohmann/json.hpp>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070013
George Liu7a1dbc42022-12-07 16:03:22 +080014#include <array>
15#include <string_view>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070016#include <vector>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070017
18namespace crow
19{
20namespace google_api
21{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070022
Nan Zhou30aacdd2022-07-03 05:02:36 +000023inline void
24 handleGoogleV1Get(const crow::Request& /*req*/,
25 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070026{
27 asyncResp->res.jsonValue["@odata.type"] =
28 "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
29 asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
30 asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
31 asyncResp->res.jsonValue["Name"] = "Google Service Root";
32 asyncResp->res.jsonValue["Version"] = "1.0.0";
33 asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
Nan Zhoucd027592022-07-03 05:18:29 +000034 "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070035}
36
Nan Zhou30aacdd2022-07-03 05:02:36 +000037inline void handleRootOfTrustCollectionGet(
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070038 const crow::Request& /*req*/,
39 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
40{
Nan Zhoucd027592022-07-03 05:18:29 +000041 asyncResp->res.jsonValue["@odata.id"] = "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070042 asyncResp->res.jsonValue["@odata.type"] =
43 "#RootOfTrustCollection.RootOfTrustCollection";
George Liu7a1dbc42022-12-07 16:03:22 +080044 const std::array<std::string_view, 1> interfaces{
45 "xyz.openbmc_project.Control.Hoth"};
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070046 redfish::collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +000047 asyncResp, boost::urls::url("/google/v1/RootOfTrustCollection"),
George Liu7a1dbc42022-12-07 16:03:22 +080048 interfaces, "/xyz/openbmc_project");
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070049}
50
51// Helper struct to identify a resolved D-Bus object interface
52struct ResolvedEntity
53{
54 std::string id;
55 std::string service;
56 std::string object;
Nan Zhou16a55352022-07-03 05:06:08 +000057 std::string interface;
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070058};
59
60using ResolvedEntityHandler = std::function<void(
61 const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
62 const ResolvedEntity&)>;
63
Nan Zhou30aacdd2022-07-03 05:02:36 +000064inline void hothGetSubtreeCallback(
65 const std::string& command,
66 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
67 const std::string& rotId, const ResolvedEntityHandler& entityHandler,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080068 const boost::system::error_code& ec,
Nan Zhou30aacdd2022-07-03 05:02:36 +000069 const dbus::utility::MapperGetSubTreeResponse& subtree)
70{
71 if (ec)
72 {
73 redfish::messages::internalError(asyncResp->res);
74 return;
75 }
Nan Zhou5600f022022-07-03 16:22:38 +000076 for (const auto& [path, services] : subtree)
Nan Zhou30aacdd2022-07-03 05:02:36 +000077 {
Nan Zhou5600f022022-07-03 16:22:38 +000078 sdbusplus::message::object_path objPath(path);
79 if (objPath.filename() != rotId || services.empty())
Nan Zhou30aacdd2022-07-03 05:02:36 +000080 {
81 continue;
82 }
83
Nan Zhoucd027592022-07-03 05:18:29 +000084 ResolvedEntity resolvedEntity = {
85 .id = rotId,
Nan Zhou5600f022022-07-03 16:22:38 +000086 .service = services[0].first,
87 .object = path,
Nan Zhoucd027592022-07-03 05:18:29 +000088 .interface = "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +000089 entityHandler(command, asyncResp, resolvedEntity);
90 return;
91 }
92
93 // Couldn't find an object with that name. return an error
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +080094 redfish::messages::resourceNotFound(asyncResp->res, "RootOfTrust", rotId);
Nan Zhou30aacdd2022-07-03 05:02:36 +000095}
96
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070097inline void resolveRoT(const std::string& command,
98 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
99 const std::string& rotId,
100 ResolvedEntityHandler&& entityHandler)
101{
George Liu7a1dbc42022-12-07 16:03:22 +0800102 constexpr std::array<std::string_view, 1> hothIfaces = {
Nan Zhoucd027592022-07-03 05:18:29 +0000103 "xyz.openbmc_project.Control.Hoth"};
George Liue99073f2022-12-09 11:06:16 +0800104 dbus::utility::getSubTree(
105 "/xyz/openbmc_project", 0, hothIfaces,
Ed Tanous002d39b2022-05-31 08:59:27 -0700106 [command, asyncResp, rotId,
107 entityHandler{std::forward<ResolvedEntityHandler>(entityHandler)}](
George Liue99073f2022-12-09 11:06:16 +0800108 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -0700109 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Nan Zhou30aacdd2022-07-03 05:02:36 +0000110 hothGetSubtreeCallback(command, asyncResp, rotId, entityHandler, ec,
111 subtree);
George Liue99073f2022-12-09 11:06:16 +0800112 });
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700113}
114
115inline void populateRootOfTrustEntity(
116 const std::string& /*unused*/,
117 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
118 const ResolvedEntity& resolvedEntity)
119{
120 asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
Willy Tueddfc432022-09-26 16:46:38 +0000121 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
122 "google", "v1", "RootOfTrustCollection", resolvedEntity.id);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700123
124 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
125 asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
126 // Need to fix this later to a stabler property.
127 asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
128 asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
129 asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
130 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
131 "/Actions/RootOfTrust.SendCommand";
132
133 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
134 resolvedEntity.id;
135 asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
136 "Embedded";
137}
138
Nan Zhou30aacdd2022-07-03 05:02:36 +0000139inline void
140 handleRootOfTrustGet(const crow::Request& /*req*/,
141 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
142 const std::string& param)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700143{
Nan Zhou30aacdd2022-07-03 05:02:36 +0000144 std::string emptyCommand;
145 resolveRoT(emptyCommand, asyncResp, param, populateRootOfTrustEntity);
146}
147
148inline void
149 invocationCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800150 const boost::system::error_code& ec,
Nan Zhou30aacdd2022-07-03 05:02:36 +0000151 const std::vector<uint8_t>& responseBytes)
152{
153 if (ec)
154 {
155 BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
156 << ec.message();
157 redfish::messages::internalError(asyncResp->res);
158 return;
159 }
160
161 asyncResp->res.jsonValue["CommandResponse"] =
162 bytesToHexString(responseBytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700163}
164
165inline void
166 invokeRoTCommand(const std::string& command,
167 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
168 const ResolvedEntity& resolvedEntity)
169{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700170 std::vector<uint8_t> bytes = hexStringToBytes(command);
171 if (bytes.empty())
172 {
173 BMCWEB_LOG_DEBUG << "Invalid command: " << command;
174 redfish::messages::actionParameterValueTypeError(command, "Command",
175 "SendCommand");
176 return;
177 }
178
179 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800180 [asyncResp{asyncResp}](const boost::system::error_code& ec,
Nan Zhou30aacdd2022-07-03 05:02:36 +0000181 const std::vector<uint8_t>& responseBytes) {
182 invocationCallback(asyncResp, ec, responseBytes);
183 },
184 resolvedEntity.service, resolvedEntity.object, resolvedEntity.interface,
185 "SendHostCommand", bytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700186}
187
Nan Zhou30aacdd2022-07-03 05:02:36 +0000188inline void handleRoTSendCommandPost(
189 const crow::Request& request,
190 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
191 const std::string& rotId)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700192{
193 std::string command;
194 if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
195 command))
196 {
197 BMCWEB_LOG_DEBUG << "Missing property Command.";
198 redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
199 "Command");
200 return;
201 }
202
203 resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
204}
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700205
206inline void requestRoutes(App& app)
207{
208 BMCWEB_ROUTE(app, "/google/v1/")
Nan Zhou30aacdd2022-07-03 05:02:36 +0000209 .methods(boost::beast::http::verb::get)(handleGoogleV1Get);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700210
211 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
212 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000213 .methods(boost::beast::http::verb::get)(handleRootOfTrustCollectionGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700214
215 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
216 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000217 .methods(boost::beast::http::verb::get)(handleRootOfTrustGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700218
219 BMCWEB_ROUTE(
220 app,
221 "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
222 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000223 .methods(boost::beast::http::verb::post)(handleRoTSendCommandPost);
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700224}
225
226} // namespace google_api
227} // namespace crow