blob: d802d00b1ffaa0fb1c9d8312150f3571649cb55d [file] [log] [blame]
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -07001#pragma once
2
3#include <app.hpp>
4#include <async_resp.hpp>
Jiaqing Zhaob6a55182022-05-20 11:47:46 +08005#include <dbus_utility.hpp>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -07006#include <error_messages.hpp>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -07007#include <nlohmann/json.hpp>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -07008#include <utils/collection.hpp>
9#include <utils/hex_utils.hpp>
10#include <utils/json_utils.hpp>
11
12#include <vector>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070013
14namespace crow
15{
16namespace google_api
17{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070018
Nan Zhou30aacdd2022-07-03 05:02:36 +000019inline void
20 handleGoogleV1Get(const crow::Request& /*req*/,
21 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070022{
23 asyncResp->res.jsonValue["@odata.type"] =
24 "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
25 asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
26 asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
27 asyncResp->res.jsonValue["Name"] = "Google Service Root";
28 asyncResp->res.jsonValue["Version"] = "1.0.0";
29 asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
Nan Zhoucd027592022-07-03 05:18:29 +000030 "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070031}
32
Nan Zhou30aacdd2022-07-03 05:02:36 +000033inline void handleRootOfTrustCollectionGet(
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070034 const crow::Request& /*req*/,
35 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
36{
Nan Zhoucd027592022-07-03 05:18:29 +000037 asyncResp->res.jsonValue["@odata.id"] = "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070038 asyncResp->res.jsonValue["@odata.type"] =
39 "#RootOfTrustCollection.RootOfTrustCollection";
40 redfish::collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +000041 asyncResp, boost::urls::url("/google/v1/RootOfTrustCollection"),
Nan Zhoucd027592022-07-03 05:18:29 +000042 {"xyz.openbmc_project.Control.Hoth"}, "/xyz/openbmc_project");
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070043}
44
45// Helper struct to identify a resolved D-Bus object interface
46struct ResolvedEntity
47{
48 std::string id;
49 std::string service;
50 std::string object;
Nan Zhou16a55352022-07-03 05:06:08 +000051 std::string interface;
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070052};
53
54using ResolvedEntityHandler = std::function<void(
55 const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
56 const ResolvedEntity&)>;
57
Nan Zhou30aacdd2022-07-03 05:02:36 +000058inline void hothGetSubtreeCallback(
59 const std::string& command,
60 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
61 const std::string& rotId, const ResolvedEntityHandler& entityHandler,
62 const boost::system::error_code ec,
63 const dbus::utility::MapperGetSubTreeResponse& subtree)
64{
65 if (ec)
66 {
67 redfish::messages::internalError(asyncResp->res);
68 return;
69 }
Nan Zhou5600f022022-07-03 16:22:38 +000070 for (const auto& [path, services] : subtree)
Nan Zhou30aacdd2022-07-03 05:02:36 +000071 {
Nan Zhou5600f022022-07-03 16:22:38 +000072 sdbusplus::message::object_path objPath(path);
73 if (objPath.filename() != rotId || services.empty())
Nan Zhou30aacdd2022-07-03 05:02:36 +000074 {
75 continue;
76 }
77
Nan Zhoucd027592022-07-03 05:18:29 +000078 ResolvedEntity resolvedEntity = {
79 .id = rotId,
Nan Zhou5600f022022-07-03 16:22:38 +000080 .service = services[0].first,
81 .object = path,
Nan Zhoucd027592022-07-03 05:18:29 +000082 .interface = "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +000083 entityHandler(command, asyncResp, resolvedEntity);
84 return;
85 }
86
87 // Couldn't find an object with that name. return an error
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +080088 redfish::messages::resourceNotFound(asyncResp->res, "RootOfTrust", rotId);
Nan Zhou30aacdd2022-07-03 05:02:36 +000089}
90
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070091inline void resolveRoT(const std::string& command,
92 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
93 const std::string& rotId,
94 ResolvedEntityHandler&& entityHandler)
95{
Nan Zhou30aacdd2022-07-03 05:02:36 +000096
Nan Zhoucd027592022-07-03 05:18:29 +000097 std::array<std::string, 1> hothIfaces = {
98 "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +000099 crow::connections::systemBus->async_method_call(
Ed Tanous002d39b2022-05-31 08:59:27 -0700100 [command, asyncResp, rotId,
101 entityHandler{std::forward<ResolvedEntityHandler>(entityHandler)}](
102 const boost::system::error_code ec,
103 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Nan Zhou30aacdd2022-07-03 05:02:36 +0000104 hothGetSubtreeCallback(command, asyncResp, rotId, entityHandler, ec,
105 subtree);
106 },
107 "xyz.openbmc_project.ObjectMapper",
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700108 "/xyz/openbmc_project/object_mapper",
Nan Zhoucd027592022-07-03 05:18:29 +0000109 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
110 "/xyz/openbmc_project",
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700111 /*depth=*/0, hothIfaces);
112}
113
114inline void populateRootOfTrustEntity(
115 const std::string& /*unused*/,
116 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
117 const ResolvedEntity& resolvedEntity)
118{
119 asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
120 asyncResp->res.jsonValue["@odata.id"] =
121 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id;
122
123 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
124 asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
125 // Need to fix this later to a stabler property.
126 asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
127 asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
128 asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
129 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
130 "/Actions/RootOfTrust.SendCommand";
131
132 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
133 resolvedEntity.id;
134 asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
135 "Embedded";
136}
137
Nan Zhou30aacdd2022-07-03 05:02:36 +0000138inline void
139 handleRootOfTrustGet(const crow::Request& /*req*/,
140 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
141 const std::string& param)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700142{
Nan Zhou30aacdd2022-07-03 05:02:36 +0000143 std::string emptyCommand;
144 resolveRoT(emptyCommand, asyncResp, param, populateRootOfTrustEntity);
145}
146
147inline void
148 invocationCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
149 const boost::system::error_code ec,
150 const std::vector<uint8_t>& responseBytes)
151{
152 if (ec)
153 {
154 BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
155 << ec.message();
156 redfish::messages::internalError(asyncResp->res);
157 return;
158 }
159
160 asyncResp->res.jsonValue["CommandResponse"] =
161 bytesToHexString(responseBytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700162}
163
164inline void
165 invokeRoTCommand(const std::string& command,
166 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
167 const ResolvedEntity& resolvedEntity)
168{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700169 std::vector<uint8_t> bytes = hexStringToBytes(command);
170 if (bytes.empty())
171 {
172 BMCWEB_LOG_DEBUG << "Invalid command: " << command;
173 redfish::messages::actionParameterValueTypeError(command, "Command",
174 "SendCommand");
175 return;
176 }
177
178 crow::connections::systemBus->async_method_call(
Nan Zhou30aacdd2022-07-03 05:02:36 +0000179 [asyncResp{asyncResp}](const boost::system::error_code ec,
180 const std::vector<uint8_t>& responseBytes) {
181 invocationCallback(asyncResp, ec, responseBytes);
182 },
183 resolvedEntity.service, resolvedEntity.object, resolvedEntity.interface,
184 "SendHostCommand", bytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700185}
186
Nan Zhou30aacdd2022-07-03 05:02:36 +0000187inline void handleRoTSendCommandPost(
188 const crow::Request& request,
189 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
190 const std::string& rotId)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700191{
192 std::string command;
193 if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
194 command))
195 {
196 BMCWEB_LOG_DEBUG << "Missing property Command.";
197 redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
198 "Command");
199 return;
200 }
201
202 resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
203}
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700204
205inline void requestRoutes(App& app)
206{
207 BMCWEB_ROUTE(app, "/google/v1/")
Nan Zhou30aacdd2022-07-03 05:02:36 +0000208 .methods(boost::beast::http::verb::get)(handleGoogleV1Get);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700209
210 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
211 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000212 .methods(boost::beast::http::verb::get)(handleRootOfTrustCollectionGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700213
214 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
215 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000216 .methods(boost::beast::http::verb::get)(handleRootOfTrustGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700217
218 BMCWEB_ROUTE(
219 app,
220 "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
221 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000222 .methods(boost::beast::http::verb::post)(handleRoTSendCommandPost);
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700223}
224
225} // namespace google_api
226} // namespace crow