blob: f39b45f572e70663cf92d23268190bac79919bc0 [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>
Ed Tanousef4c65b2023-04-24 15:28:50 -070012#include <boost/url/format.hpp>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070013#include <nlohmann/json.hpp>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070014
George Liu7a1dbc42022-12-07 16:03:22 +080015#include <array>
16#include <string_view>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070017#include <vector>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070018
19namespace crow
20{
21namespace google_api
22{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070023
Nan Zhou30aacdd2022-07-03 05:02:36 +000024inline void
25 handleGoogleV1Get(const crow::Request& /*req*/,
26 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070027{
28 asyncResp->res.jsonValue["@odata.type"] =
29 "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
30 asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
31 asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
32 asyncResp->res.jsonValue["Name"] = "Google Service Root";
33 asyncResp->res.jsonValue["Version"] = "1.0.0";
34 asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
Nan Zhoucd027592022-07-03 05:18:29 +000035 "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070036}
37
Nan Zhou30aacdd2022-07-03 05:02:36 +000038inline void handleRootOfTrustCollectionGet(
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070039 const crow::Request& /*req*/,
40 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
41{
Nan Zhoucd027592022-07-03 05:18:29 +000042 asyncResp->res.jsonValue["@odata.id"] = "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070043 asyncResp->res.jsonValue["@odata.type"] =
44 "#RootOfTrustCollection.RootOfTrustCollection";
George Liu7a1dbc42022-12-07 16:03:22 +080045 const std::array<std::string_view, 1> interfaces{
46 "xyz.openbmc_project.Control.Hoth"};
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070047 redfish::collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +000048 asyncResp, boost::urls::url("/google/v1/RootOfTrustCollection"),
George Liu7a1dbc42022-12-07 16:03:22 +080049 interfaces, "/xyz/openbmc_project");
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070050}
51
52// Helper struct to identify a resolved D-Bus object interface
53struct ResolvedEntity
54{
55 std::string id;
56 std::string service;
57 std::string object;
Nan Zhou16a55352022-07-03 05:06:08 +000058 std::string interface;
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070059};
60
61using ResolvedEntityHandler = std::function<void(
62 const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
63 const ResolvedEntity&)>;
64
Nan Zhou30aacdd2022-07-03 05:02:36 +000065inline void hothGetSubtreeCallback(
66 const std::string& command,
67 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
68 const std::string& rotId, const ResolvedEntityHandler& entityHandler,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080069 const boost::system::error_code& ec,
Nan Zhou30aacdd2022-07-03 05:02:36 +000070 const dbus::utility::MapperGetSubTreeResponse& subtree)
71{
72 if (ec)
73 {
74 redfish::messages::internalError(asyncResp->res);
75 return;
76 }
Nan Zhou5600f022022-07-03 16:22:38 +000077 for (const auto& [path, services] : subtree)
Nan Zhou30aacdd2022-07-03 05:02:36 +000078 {
Nan Zhou5600f022022-07-03 16:22:38 +000079 sdbusplus::message::object_path objPath(path);
80 if (objPath.filename() != rotId || services.empty())
Nan Zhou30aacdd2022-07-03 05:02:36 +000081 {
82 continue;
83 }
84
Nan Zhoucd027592022-07-03 05:18:29 +000085 ResolvedEntity resolvedEntity = {
86 .id = rotId,
Nan Zhou5600f022022-07-03 16:22:38 +000087 .service = services[0].first,
88 .object = path,
Nan Zhoucd027592022-07-03 05:18:29 +000089 .interface = "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +000090 entityHandler(command, asyncResp, resolvedEntity);
91 return;
92 }
93
94 // Couldn't find an object with that name. return an error
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +080095 redfish::messages::resourceNotFound(asyncResp->res, "RootOfTrust", rotId);
Nan Zhou30aacdd2022-07-03 05:02:36 +000096}
97
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070098inline void resolveRoT(const std::string& command,
99 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
100 const std::string& rotId,
101 ResolvedEntityHandler&& entityHandler)
102{
George Liu7a1dbc42022-12-07 16:03:22 +0800103 constexpr std::array<std::string_view, 1> hothIfaces = {
Nan Zhoucd027592022-07-03 05:18:29 +0000104 "xyz.openbmc_project.Control.Hoth"};
George Liue99073f2022-12-09 11:06:16 +0800105 dbus::utility::getSubTree(
106 "/xyz/openbmc_project", 0, hothIfaces,
Ed Tanous002d39b2022-05-31 08:59:27 -0700107 [command, asyncResp, rotId,
108 entityHandler{std::forward<ResolvedEntityHandler>(entityHandler)}](
George Liue99073f2022-12-09 11:06:16 +0800109 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -0700110 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Nan Zhou30aacdd2022-07-03 05:02:36 +0000111 hothGetSubtreeCallback(command, asyncResp, rotId, entityHandler, ec,
112 subtree);
George Liue99073f2022-12-09 11:06:16 +0800113 });
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700114}
115
116inline void populateRootOfTrustEntity(
117 const std::string& /*unused*/,
118 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
119 const ResolvedEntity& resolvedEntity)
120{
121 asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700122 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
123 "/google/v1/RootOfTrustCollection/{}", resolvedEntity.id);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700124
125 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
126 asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
127 // Need to fix this later to a stabler property.
128 asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
129 asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
130 asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
131 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
132 "/Actions/RootOfTrust.SendCommand";
133
134 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
135 resolvedEntity.id;
136 asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
137 "Embedded";
138}
139
Nan Zhou30aacdd2022-07-03 05:02:36 +0000140inline void
141 handleRootOfTrustGet(const crow::Request& /*req*/,
142 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
143 const std::string& param)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700144{
Nan Zhou30aacdd2022-07-03 05:02:36 +0000145 std::string emptyCommand;
146 resolveRoT(emptyCommand, asyncResp, param, populateRootOfTrustEntity);
147}
148
149inline void
150 invocationCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800151 const boost::system::error_code& ec,
Nan Zhou30aacdd2022-07-03 05:02:36 +0000152 const std::vector<uint8_t>& responseBytes)
153{
154 if (ec)
155 {
156 BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
157 << ec.message();
158 redfish::messages::internalError(asyncResp->res);
159 return;
160 }
161
162 asyncResp->res.jsonValue["CommandResponse"] =
163 bytesToHexString(responseBytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700164}
165
166inline void
167 invokeRoTCommand(const std::string& command,
168 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
169 const ResolvedEntity& resolvedEntity)
170{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700171 std::vector<uint8_t> bytes = hexStringToBytes(command);
172 if (bytes.empty())
173 {
174 BMCWEB_LOG_DEBUG << "Invalid command: " << command;
175 redfish::messages::actionParameterValueTypeError(command, "Command",
176 "SendCommand");
177 return;
178 }
179
180 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800181 [asyncResp{asyncResp}](const boost::system::error_code& ec,
Nan Zhou30aacdd2022-07-03 05:02:36 +0000182 const std::vector<uint8_t>& responseBytes) {
183 invocationCallback(asyncResp, ec, responseBytes);
184 },
185 resolvedEntity.service, resolvedEntity.object, resolvedEntity.interface,
186 "SendHostCommand", bytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700187}
188
Nan Zhou30aacdd2022-07-03 05:02:36 +0000189inline void handleRoTSendCommandPost(
190 const crow::Request& request,
191 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
192 const std::string& rotId)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700193{
194 std::string command;
195 if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
196 command))
197 {
198 BMCWEB_LOG_DEBUG << "Missing property Command.";
199 redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
200 "Command");
201 return;
202 }
203
204 resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
205}
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700206
207inline void requestRoutes(App& app)
208{
209 BMCWEB_ROUTE(app, "/google/v1/")
Nan Zhou30aacdd2022-07-03 05:02:36 +0000210 .methods(boost::beast::http::verb::get)(handleGoogleV1Get);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700211
212 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
213 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000214 .methods(boost::beast::http::verb::get)(handleRootOfTrustCollectionGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700215
216 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
217 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000218 .methods(boost::beast::http::verb::get)(handleRootOfTrustGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700219
220 BMCWEB_ROUTE(
221 app,
222 "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
223 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000224 .methods(boost::beast::http::verb::post)(handleRoTSendCommandPost);
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700225}
226
227} // namespace google_api
228} // namespace crow