blob: 5c7b431d8ff8a9dcdae9c9f9ad12106b34ce49c1 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Marri Devender Rao5968cae2019-01-21 10:27:12 -06003#pragma once
4
Ed Tanousd7857202025-01-28 15:32:26 -08005#include "bmcweb_config.h"
6
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08007#include "app.hpp"
8#include "async_resp.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080010#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080011#include "error_messages.hpp"
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010012#include "http/parsing.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080013#include "http_request.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080014#include "http_response.hpp"
Ed Tanousd98a2f92025-02-06 17:36:31 -080015#include "io_context_singleton.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080016#include "logging.hpp"
17#include "privileges.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "query.hpp"
19#include "registries/privilege_registry.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080020#include "utility.hpp"
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +020021#include "utils/dbus_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080022#include "utils/json_utils.hpp"
23#include "utils/time_utils.hpp"
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +020024
Ed Tanousd7857202025-01-28 15:32:26 -080025#include <systemd/sd-bus.h>
26
27#include <boost/asio/error.hpp>
28#include <boost/asio/steady_timer.hpp>
29#include <boost/beast/http/field.hpp>
30#include <boost/beast/http/status.hpp>
31#include <boost/beast/http/verb.hpp>
32#include <boost/system/result.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070033#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080034#include <boost/url/parse.hpp>
35#include <boost/url/url.hpp>
36#include <nlohmann/json.hpp>
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080037#include <sdbusplus/bus/match.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080038#include <sdbusplus/message.hpp>
39#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +020040#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050041
George Liu7a1dbc42022-12-07 16:03:22 +080042#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080043#include <chrono>
44#include <cstddef>
45#include <cstdint>
46#include <cstdlib>
47#include <filesystem>
48#include <format>
49#include <fstream>
50#include <functional>
51#include <iterator>
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080052#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080053#include <optional>
54#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080055#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080056#include <system_error>
57#include <utility>
58#include <vector>
George Liu7a1dbc42022-12-07 16:03:22 +080059
Marri Devender Rao5968cae2019-01-21 10:27:12 -060060namespace redfish
61{
62namespace certs
63{
Patrick Williams89492a12023-05-10 07:51:34 -050064constexpr const char* certInstallIntf = "xyz.openbmc_project.Certs.Install";
65constexpr const char* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
66constexpr const char* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
67constexpr const char* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
Patrick Williams89492a12023-05-10 07:51:34 -050068constexpr const char* httpsServiceName =
Marri Devender Rao37cce912019-02-20 01:05:22 -060069 "xyz.openbmc_project.Certs.Manager.Server.Https";
Patrick Williams89492a12023-05-10 07:51:34 -050070constexpr const char* ldapServiceName =
Marri Devender Rao37cce912019-02-20 01:05:22 -060071 "xyz.openbmc_project.Certs.Manager.Client.Ldap";
Patrick Williams89492a12023-05-10 07:51:34 -050072constexpr const char* authorityServiceName =
Michal Orzelb2254cc2023-07-27 14:08:32 +020073 "xyz.openbmc_project.Certs.Manager.Authority.Truststore";
Patrick Williams89492a12023-05-10 07:51:34 -050074constexpr const char* baseObjectPath = "/xyz/openbmc_project/certs";
75constexpr const char* httpsObjectPath =
Jiaqing Zhaoc6a8dfb2022-06-03 10:44:23 +080076 "/xyz/openbmc_project/certs/server/https";
Patrick Williams89492a12023-05-10 07:51:34 -050077constexpr const char* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
78constexpr const char* authorityObjectPath =
Michal Orzelb2254cc2023-07-27 14:08:32 +020079 "/xyz/openbmc_project/certs/authority/truststore";
Marri Devender Rao5968cae2019-01-21 10:27:12 -060080} // namespace certs
81
82/**
83 * The Certificate schema defines a Certificate Service which represents the
84 * actions available to manage certificates and links to where certificates
85 * are installed.
86 */
Marri Devender Rao5968cae2019-01-21 10:27:12 -060087
zhanghch058d1b46d2021-04-01 11:18:24 +080088inline std::string getCertificateFromReqBody(
89 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
90 const crow::Request& req)
Kowalski, Kamil58eb2382019-08-12 11:54:31 +020091{
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010092 nlohmann::json reqJson;
93 JsonParseResult ret = parseRequestAsJson(req, reqJson);
94 if (ret != JsonParseResult::Success)
Kowalski, Kamil58eb2382019-08-12 11:54:31 +020095 {
96 // We did not receive JSON request, proceed as it is RAW data
Ed Tanous33c6b582023-02-14 15:05:48 -080097 return req.body();
Kowalski, Kamil58eb2382019-08-12 11:54:31 +020098 }
99
100 std::string certificate;
101 std::optional<std::string> certificateType = "PEM";
102
Patrick Williams504af5a2025-02-03 14:29:03 -0500103 if (!json_util::readJsonPatch( //
104 req, asyncResp->res, //
105 "CertificateString", certificate, //
Myung Baeafc474a2024-10-09 00:53:29 -0700106 "CertificateType", certificateType //
107 ))
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200108 {
Ed Tanous62598e32023-07-17 17:06:25 -0700109 BMCWEB_LOG_ERROR("Required parameters are missing");
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200110 messages::internalError(asyncResp->res);
Ed Tanousabb93cd2021-09-02 14:34:57 -0700111 return {};
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200112 }
113
114 if (*certificateType != "PEM")
115 {
116 messages::propertyValueNotInList(asyncResp->res, *certificateType,
117 "CertificateType");
Ed Tanousabb93cd2021-09-02 14:34:57 -0700118 return {};
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200119 }
120
121 return certificate;
122}
123
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600124/**
125 * Class to create a temporary certificate file for uploading to system
126 */
127class CertificateFile
128{
129 public:
130 CertificateFile() = delete;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500131 CertificateFile(const CertificateFile&) = delete;
132 CertificateFile& operator=(const CertificateFile&) = delete;
133 CertificateFile(CertificateFile&&) = delete;
134 CertificateFile& operator=(CertificateFile&&) = delete;
Ed Tanous4e23a442022-06-06 09:57:26 -0700135 explicit CertificateFile(const std::string& certString)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600136 {
Ed Tanous72d52d22020-10-12 07:46:27 -0700137 std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
Ed Tanous52074382020-09-28 19:16:18 -0700138 'e', 'r', 't', 's', '.', 'X',
139 'X', 'X', 'X', 'X', 'X', '\0'};
Myung Bae92e11bf2025-01-31 09:22:23 -0500140 // NOLINTNEXTLINE(misc-include-cleaner)
Ed Tanous52074382020-09-28 19:16:18 -0700141 char* tempDirectory = mkdtemp(dirTemplate.data());
Ed Tanouse662eae2022-01-25 10:39:19 -0800142 if (tempDirectory != nullptr)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600143 {
144 certDirectory = tempDirectory;
145 certificateFile = certDirectory / "cert.pem";
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400146 std::ofstream out(certificateFile,
147 std::ofstream::out | std::ofstream::binary |
148 std::ofstream::trunc);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600149 out << certString;
150 out.close();
Ed Tanous62598e32023-07-17 17:06:25 -0700151 BMCWEB_LOG_DEBUG("Creating certificate file{}",
152 certificateFile.string());
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600153 }
154 }
155 ~CertificateFile()
156 {
157 if (std::filesystem::exists(certDirectory))
158 {
Ed Tanous62598e32023-07-17 17:06:25 -0700159 BMCWEB_LOG_DEBUG("Removing certificate file{}",
160 certificateFile.string());
Ed Tanous23a21a12020-07-25 04:45:05 +0000161 std::error_code ec;
162 std::filesystem::remove_all(certDirectory, ec);
163 if (ec)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600164 {
Ed Tanous62598e32023-07-17 17:06:25 -0700165 BMCWEB_LOG_ERROR("Failed to remove temp directory{}",
166 certDirectory.string());
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600167 }
168 }
169 }
170 std::string getCertFilePath()
171 {
172 return certificateFile;
173 }
174
175 private:
176 std::filesystem::path certificateFile;
177 std::filesystem::path certDirectory;
178};
179
180/**
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500181 * @brief Parse and update Certificate Issue/Subject property
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600182 *
183 * @param[in] asyncResp Shared pointer to the response message
184 * @param[in] str Issuer/Subject value in key=value pairs
185 * @param[in] type Issuer/Subject
186 * @return None
187 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700188inline void updateCertIssuerOrSubject(nlohmann::json& out,
Ed Tanous26ccae32023-02-16 10:28:44 -0800189 std::string_view value)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600190{
191 // example: O=openbmc-project.xyz,CN=localhost
192 std::string_view::iterator i = value.begin();
193 while (i != value.end())
194 {
195 std::string_view::iterator tokenBegin = i;
196 while (i != value.end() && *i != '=')
197 {
Patrick Williams6da47ba2023-05-11 11:53:56 -0500198 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600199 }
200 if (i == value.end())
201 {
202 break;
203 }
Ed Tanous26ccae32023-02-16 10:28:44 -0800204 std::string_view key(tokenBegin, static_cast<size_t>(i - tokenBegin));
Patrick Williams6da47ba2023-05-11 11:53:56 -0500205 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600206 tokenBegin = i;
207 while (i != value.end() && *i != ',')
208 {
Patrick Williams6da47ba2023-05-11 11:53:56 -0500209 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600210 }
Ed Tanous26ccae32023-02-16 10:28:44 -0800211 std::string_view val(tokenBegin, static_cast<size_t>(i - tokenBegin));
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600212 if (key == "L")
213 {
214 out["City"] = val;
215 }
216 else if (key == "CN")
217 {
218 out["CommonName"] = val;
219 }
220 else if (key == "C")
221 {
222 out["Country"] = val;
223 }
224 else if (key == "O")
225 {
226 out["Organization"] = val;
227 }
228 else if (key == "OU")
229 {
230 out["OrganizationalUnit"] = val;
231 }
232 else if (key == "ST")
233 {
234 out["State"] = val;
235 }
236 // skip comma character
237 if (i != value.end())
238 {
Patrick Williams6da47ba2023-05-11 11:53:56 -0500239 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600240 }
241 }
242}
243
244/**
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800245 * @brief Retrieve the installed certificate list
246 *
247 * @param[in] asyncResp Shared pointer to the response message
248 * @param[in] basePath DBus object path to search
249 * @param[in] listPtr Json pointer to the list in asyncResp
250 * @param[in] countPtr Json pointer to the count in asyncResp
251 * @return None
252 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700253inline void getCertificateList(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400254 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
255 const std::string& basePath, const nlohmann::json::json_pointer& listPtr,
256 const nlohmann::json::json_pointer& countPtr)
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800257{
George Liu7a1dbc42022-12-07 16:03:22 +0800258 constexpr std::array<std::string_view, 1> interfaces = {
259 certs::certPropIntf};
260 dbus::utility::getSubTreePaths(
261 basePath, 0, interfaces,
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800262 [asyncResp, listPtr, countPtr](
George Liu7a1dbc42022-12-07 16:03:22 +0800263 const boost::system::error_code& ec,
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800264 const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400265 if (ec)
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800266 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400267 BMCWEB_LOG_ERROR("Certificate collection query failed: {}", ec);
268 messages::internalError(asyncResp->res);
269 return;
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800270 }
271
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400272 nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
273 links = nlohmann::json::array();
274 for (const auto& certPath : certPaths)
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800275 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400276 sdbusplus::message::object_path objPath(certPath);
277 std::string certId = objPath.filename();
278 if (certId.empty())
279 {
280 BMCWEB_LOG_ERROR("Invalid certificate objPath {}",
281 certPath);
282 continue;
283 }
284
285 boost::urls::url certURL;
286 if (objPath.parent_path() == certs::httpsObjectPath)
287 {
288 certURL = boost::urls::format(
289 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
290 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
291 }
292 else if (objPath.parent_path() == certs::ldapObjectPath)
293 {
294 certURL = boost::urls::format(
295 "/redfish/v1/AccountService/LDAP/Certificates/{}",
296 certId);
297 }
298 else if (objPath.parent_path() == certs::authorityObjectPath)
299 {
300 certURL = boost::urls::format(
301 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
302 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
303 }
304 else
305 {
306 continue;
307 }
308
309 nlohmann::json::object_t link;
310 link["@odata.id"] = certURL;
311 links.emplace_back(std::move(link));
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800312 }
313
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400314 asyncResp->res.jsonValue[countPtr] = links.size();
315 });
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800316}
317
318/**
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600319 * @brief Retrieve the certificates properties and append to the response
320 * message
321 *
322 * @param[in] asyncResp Shared pointer to the response message
323 * @param[in] objectPath Path of the D-Bus service object
324 * @param[in] certId Id of the certificate
325 * @param[in] certURL URL of the certificate object
326 * @param[in] name name of the certificate
327 * @return None
328 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700329inline void getCertificateProperties(
zhanghch058d1b46d2021-04-01 11:18:24 +0800330 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhaoe19e97e2022-06-06 19:43:39 +0800331 const std::string& objectPath, const std::string& service,
Jiaqing Zhao1e312592022-06-14 12:58:09 +0800332 const std::string& certId, const boost::urls::url& certURL,
Jiaqing Zhaoe19e97e2022-06-06 19:43:39 +0800333 const std::string& name)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600334{
Ed Tanous62598e32023-07-17 17:06:25 -0700335 BMCWEB_LOG_DEBUG("getCertificateProperties Path={} certId={} certURl={}",
336 objectPath, certId, certURL);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800337 dbus::utility::getAllProperties(
338 service, objectPath, certs::certPropIntf,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800339 [asyncResp, certURL, certId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800340 name](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800341 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400342 if (ec)
343 {
344 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
345 messages::resourceNotFound(asyncResp->res, "Certificate",
346 certId);
347 return;
348 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200349
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400350 const std::string* certificateString = nullptr;
351 const std::vector<std::string>* keyUsage = nullptr;
352 const std::string* issuer = nullptr;
353 const std::string* subject = nullptr;
354 const uint64_t* validNotAfter = nullptr;
355 const uint64_t* validNotBefore = nullptr;
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200356
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400357 const bool success = sdbusplus::unpackPropertiesNoThrow(
358 dbus_utils::UnpackErrorPrinter(), properties,
359 "CertificateString", certificateString, "KeyUsage", keyUsage,
360 "Issuer", issuer, "Subject", subject, "ValidNotAfter",
361 validNotAfter, "ValidNotBefore", validNotBefore);
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200362
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400363 if (!success)
364 {
365 messages::internalError(asyncResp->res);
366 return;
367 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200368
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400369 asyncResp->res.jsonValue["@odata.id"] = certURL;
370 asyncResp->res.jsonValue["@odata.type"] =
371 "#Certificate.v1_0_0.Certificate";
372 asyncResp->res.jsonValue["Id"] = certId;
373 asyncResp->res.jsonValue["Name"] = name;
374 asyncResp->res.jsonValue["Description"] = name;
375 asyncResp->res.jsonValue["CertificateString"] = "";
376 asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array();
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200377
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400378 if (certificateString != nullptr)
379 {
380 asyncResp->res.jsonValue["CertificateString"] =
381 *certificateString;
382 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200383
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400384 if (keyUsage != nullptr)
385 {
386 asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
387 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200388
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400389 if (issuer != nullptr)
390 {
391 updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
392 *issuer);
393 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200394
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400395 if (subject != nullptr)
396 {
397 updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
398 *subject);
399 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200400
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400401 if (validNotAfter != nullptr)
402 {
403 asyncResp->res.jsonValue["ValidNotAfter"] =
404 redfish::time_utils::getDateTimeUint(*validNotAfter);
405 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200406
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400407 if (validNotBefore != nullptr)
408 {
409 asyncResp->res.jsonValue["ValidNotBefore"] =
410 redfish::time_utils::getDateTimeUint(*validNotBefore);
411 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200412
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400413 asyncResp->res.addHeader(
414 boost::beast::http::field::location,
415 std::string_view(certURL.data(), certURL.size()));
416 });
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600417}
418
Patrick Williams504af5a2025-02-03 14:29:03 -0500419inline void deleteCertificate(
420 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
421 const std::string& service,
422 const sdbusplus::message::object_path& objectPath)
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +0800423{
Ed Tanous177612a2025-02-14 15:16:09 -0800424 dbus::utility::async_method_call(
425 asyncResp,
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +0800426 [asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800427 id{objectPath.filename()}](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400428 if (ec)
429 {
430 messages::resourceNotFound(asyncResp->res, "Certificate", id);
431 return;
432 }
433 BMCWEB_LOG_INFO("Certificate deleted");
434 asyncResp->res.result(boost::beast::http::status::no_content);
435 },
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +0800436 service, objectPath, certs::objDeleteIntf, "Delete");
437}
438
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800439inline void handleCertificateServiceGet(
440 App& app, const crow::Request& req,
441 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600442{
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800443 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
444 {
445 return;
446 }
447
Ninad Palsule3e72c202023-03-27 17:19:55 -0500448 if (req.session == nullptr)
449 {
450 messages::internalError(asyncResp->res);
451 return;
452 }
453
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800454 asyncResp->res.jsonValue["@odata.type"] =
455 "#CertificateService.v1_0_0.CertificateService";
456 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService";
457 asyncResp->res.jsonValue["Id"] = "CertificateService";
458 asyncResp->res.jsonValue["Name"] = "Certificate Service";
459 asyncResp->res.jsonValue["Description"] =
460 "Actions available to manage certificates";
461 // /redfish/v1/CertificateService/CertificateLocations is something
462 // only ConfigureManager can access then only display when the user
463 // has permissions ConfigureManager
464 Privileges effectiveUserPrivileges =
Ninad Palsule3e72c202023-03-27 17:19:55 -0500465 redfish::getUserPrivileges(*req.session);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800466 if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
467 effectiveUserPrivileges))
468 {
469 asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
470 "/redfish/v1/CertificateService/CertificateLocations";
471 }
472 nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
473 nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"];
474 replace["target"] =
475 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate";
476 nlohmann::json::array_t allowed;
Patrick Williamsad539542023-05-12 10:10:08 -0500477 allowed.emplace_back("PEM");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800478 replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
479 actions["#CertificateService.GenerateCSR"]["target"] =
480 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
481}
482
483inline void handleCertificateLocationsGet(
484 App& app, const crow::Request& req,
485 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
486{
487 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
488 {
489 return;
490 }
491 asyncResp->res.jsonValue["@odata.id"] =
492 "/redfish/v1/CertificateService/CertificateLocations";
493 asyncResp->res.jsonValue["@odata.type"] =
494 "#CertificateLocations.v1_0_0.CertificateLocations";
495 asyncResp->res.jsonValue["Name"] = "Certificate Locations";
496 asyncResp->res.jsonValue["Id"] = "CertificateLocations";
497 asyncResp->res.jsonValue["Description"] =
498 "Defines a resource that an administrator can use in order to "
499 "locate all certificates installed on a given service";
500
501 getCertificateList(asyncResp, certs::baseObjectPath,
502 "/Links/Certificates"_json_pointer,
503 "/Links/Certificates@odata.count"_json_pointer);
504}
505
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530506inline void handleError(const std::string_view dbusErrorName,
507 const std::string& id, const std::string& certificate,
508 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
509{
510 if (dbusErrorName == "org.freedesktop.DBus.Error.UnknownObject")
511 {
512 messages::resourceNotFound(asyncResp->res, "Certificate", id);
513 }
514 else if (dbusErrorName ==
515 "xyz.openbmc_project.Certs.Error.InvalidCertificate")
516 {
517 messages::propertyValueIncorrect(asyncResp->res, "Certificate",
518 certificate);
519 }
520 else
521 {
522 messages::internalError(asyncResp->res);
523 }
524}
525
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800526inline void handleReplaceCertificateAction(
527 App& app, const crow::Request& req,
528 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
529{
530 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
531 {
532 return;
533 }
534 std::string certificate;
Ed Tanous7a31e332024-03-06 12:17:43 -0800535 std::string certURI;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800536 std::optional<std::string> certificateType = "PEM";
537
Patrick Williams504af5a2025-02-03 14:29:03 -0500538 if (!json_util::readJsonAction( //
539 req, asyncResp->res, //
540 "CertificateString", certificate, //
Myung Baeafc474a2024-10-09 00:53:29 -0700541 "CertificateType", certificateType, //
542 "CertificateUri/@odata.id", certURI //
543 ))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800544 {
Ed Tanous62598e32023-07-17 17:06:25 -0700545 BMCWEB_LOG_ERROR("Required parameters are missing");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800546 return;
547 }
548
549 if (!certificateType)
550 {
551 // should never happen, but it never hurts to be paranoid.
552 return;
553 }
554 if (certificateType != "PEM")
555 {
556 messages::actionParameterNotSupported(asyncResp->res, "CertificateType",
557 "ReplaceCertificate");
558 return;
559 }
560
Ed Tanous62598e32023-07-17 17:06:25 -0700561 BMCWEB_LOG_INFO("Certificate URI to replace: {}", certURI);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800562
Ed Tanous6fd29552023-10-04 09:40:14 -0700563 boost::system::result<boost::urls::url> parsedUrl =
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800564 boost::urls::parse_relative_ref(certURI);
565 if (!parsedUrl)
566 {
567 messages::actionParameterValueFormatError(
568 asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate");
569 return;
570 }
571
572 std::string id;
573 sdbusplus::message::object_path objectPath;
574 std::string name;
575 std::string service;
576 if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers",
577 "bmc", "NetworkProtocol", "HTTPS",
578 "Certificates", std::ref(id)))
579 {
Patrick Williams89492a12023-05-10 07:51:34 -0500580 objectPath = sdbusplus::message::object_path(certs::httpsObjectPath) /
581 id;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800582 name = "HTTPS certificate";
583 service = certs::httpsServiceName;
584 }
585 else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
586 "AccountService", "LDAP",
587 "Certificates", std::ref(id)))
588 {
Patrick Williams89492a12023-05-10 07:51:34 -0500589 objectPath = sdbusplus::message::object_path(certs::ldapObjectPath) /
590 id;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800591 name = "LDAP certificate";
592 service = certs::ldapServiceName;
593 }
594 else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
595 "Managers", "bmc", "Truststore",
596 "Certificates", std::ref(id)))
597 {
598 objectPath =
599 sdbusplus::message::object_path(certs::authorityObjectPath) / id;
600 name = "TrustStore certificate";
601 service = certs::authorityServiceName;
602 }
603 else
604 {
605 messages::actionParameterNotSupported(asyncResp->res, "CertificateUri",
606 "ReplaceCertificate");
607 return;
608 }
609
610 std::shared_ptr<CertificateFile> certFile =
611 std::make_shared<CertificateFile>(certificate);
Ed Tanous177612a2025-02-14 15:16:09 -0800612 dbus::utility::async_method_call(
613 asyncResp,
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530614 [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id, name,
615 certificate](const boost::system::error_code& ec,
Patrick Williamsd3e08592024-09-27 02:39:55 -0400616 sdbusplus::message_t& m) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400617 if (ec)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800618 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400619 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530620 const sd_bus_error* dbusError = m.get_error();
621 if ((dbusError != nullptr) && (dbusError->name != nullptr))
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400622 {
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530623 handleError(dbusError->name, id, certificate, asyncResp);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400624 }
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530625 else
626 {
627 messages::internalError(asyncResp->res);
628 }
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800629 return;
630 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400631 getCertificateProperties(asyncResp, objectPath, service, id, url,
632 name);
633 BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
634 certFile->getCertFilePath());
635 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800636 service, objectPath, certs::certReplaceIntf, "Replace",
637 certFile->getCertFilePath());
638}
639
Ed Tanouscf9e4172022-12-21 09:30:16 -0800640// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800641static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
642/**
643 * @brief Read data from CSR D-bus object and set to response
644 *
645 * @param[in] asyncResp Shared pointer to the response message
Ed Tanous8ece0e42024-01-02 13:16:50 -0800646 * @param[in] certURI Link to certificate collection URI
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800647 * @param[in] service D-Bus service name
648 * @param[in] certObjPath certificate D-Bus object path
649 * @param[in] csrObjPath CSR D-Bus object path
650 * @return None
651 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700652inline void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800653 const std::string& certURI, const std::string& service,
654 const std::string& certObjPath,
655 const std::string& csrObjPath)
656{
Ed Tanous62598e32023-07-17 17:06:25 -0700657 BMCWEB_LOG_DEBUG("getCSR CertObjectPath{} CSRObjectPath={} service={}",
658 certObjPath, csrObjPath, service);
Ed Tanous177612a2025-02-14 15:16:09 -0800659 dbus::utility::async_method_call(
660 asyncResp,
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400661 [asyncResp,
662 certURI](const boost::system::error_code& ec, const std::string& csr) {
663 if (ec)
664 {
665 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
666 messages::internalError(asyncResp->res);
667 return;
668 }
669 if (csr.empty())
670 {
671 BMCWEB_LOG_ERROR("CSR read is empty");
672 messages::internalError(asyncResp->res);
673 return;
674 }
675 asyncResp->res.jsonValue["CSRString"] = csr;
676 asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
677 certURI;
678 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800679 service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
680}
681
Patrick Williams504af5a2025-02-03 14:29:03 -0500682inline void handleGenerateCSRAction(
683 App& app, const crow::Request& req,
684 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800685{
686 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
687 {
688 return;
689 }
690 static const int rsaKeyBitLength = 2048;
691
692 // Required parameters
693 std::string city;
694 std::string commonName;
695 std::string country;
696 std::string organization;
697 std::string organizationalUnit;
698 std::string state;
Ed Tanous7a31e332024-03-06 12:17:43 -0800699 std::string certURI;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800700
701 // Optional parameters
702 std::optional<std::vector<std::string>> optAlternativeNames =
703 std::vector<std::string>();
704 std::optional<std::string> optContactPerson = "";
705 std::optional<std::string> optChallengePassword = "";
706 std::optional<std::string> optEmail = "";
707 std::optional<std::string> optGivenName = "";
708 std::optional<std::string> optInitials = "";
709 std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
710 std::optional<std::string> optKeyCurveId = "secp384r1";
711 std::optional<std::string> optKeyPairAlgorithm = "EC";
712 std::optional<std::vector<std::string>> optKeyUsage =
713 std::vector<std::string>();
714 std::optional<std::string> optSurname = "";
715 std::optional<std::string> optUnstructuredName = "";
Patrick Williams504af5a2025-02-03 14:29:03 -0500716 if (!json_util::readJsonAction( //
717 req, asyncResp->res, //
718 "AlternativeNames", optAlternativeNames, //
Myung Baeafc474a2024-10-09 00:53:29 -0700719 "CertificateCollection/@odata.id", certURI, //
Patrick Williams504af5a2025-02-03 14:29:03 -0500720 "ChallengePassword", optChallengePassword, //
721 "City", city, //
722 "CommonName", commonName, //
723 "ContactPerson", optContactPerson, //
724 "Country", country, //
725 "Email", optEmail, //
726 "GivenName", optGivenName, //
727 "Initials", optInitials, //
728 "KeyBitLength", optKeyBitLength, //
729 "KeyCurveId", optKeyCurveId, //
730 "KeyPairAlgorithm", optKeyPairAlgorithm, //
731 "KeyUsage", optKeyUsage, //
732 "Organization", organization, //
733 "OrganizationalUnit", organizationalUnit, //
734 "State", state, //
735 "Surname", optSurname, //
736 "UnstructuredName", optUnstructuredName //
Myung Baeafc474a2024-10-09 00:53:29 -0700737 ))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800738 {
739 return;
740 }
741
742 // bmcweb has no way to store or decode a private key challenge
743 // password, which will likely cause bmcweb to crash on startup
744 // if this is not set on a post so not allowing the user to set
745 // value
746 if (!optChallengePassword->empty())
747 {
748 messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
749 "ChallengePassword");
750 return;
751 }
752
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800753 std::string objectPath;
754 std::string service;
Ed Tanous253f11b2024-05-16 09:38:31 -0700755 if (certURI.starts_with(std::format(
756 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
757 BMCWEB_REDFISH_MANAGER_URI_NAME)))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800758 {
759 objectPath = certs::httpsObjectPath;
760 service = certs::httpsServiceName;
761 }
762 else if (certURI.starts_with(
763 "/redfish/v1/AccountService/LDAP/Certificates"))
764 {
765 objectPath = certs::ldapObjectPath;
766 service = certs::ldapServiceName;
767 }
768 else
769 {
770 messages::actionParameterNotSupported(
771 asyncResp->res, "CertificateCollection", "GenerateCSR");
772 return;
773 }
774
775 // supporting only EC and RSA algorithm
776 if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
777 {
778 messages::actionParameterNotSupported(
779 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
780 return;
781 }
782
783 // supporting only 2048 key bit length for RSA algorithm due to
784 // time consumed in generating private key
785 if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength)
786 {
Ed Tanouse2616cc2022-06-27 12:45:55 -0700787 messages::propertyValueNotInList(asyncResp->res, *optKeyBitLength,
788 "KeyBitLength");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800789 return;
790 }
791
792 // validate KeyUsage supporting only 1 type based on URL
Ed Tanous253f11b2024-05-16 09:38:31 -0700793 if (certURI.starts_with(std::format(
794 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
795 BMCWEB_REDFISH_MANAGER_URI_NAME)))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800796 {
797 if (optKeyUsage->empty())
798 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500799 optKeyUsage->emplace_back("ServerAuthentication");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800800 }
801 else if (optKeyUsage->size() == 1)
802 {
803 if ((*optKeyUsage)[0] != "ServerAuthentication")
804 {
805 messages::propertyValueNotInList(asyncResp->res,
806 (*optKeyUsage)[0], "KeyUsage");
807 return;
808 }
809 }
810 else
811 {
812 messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
813 "GenerateCSR");
814 return;
815 }
816 }
817 else if (certURI.starts_with(
818 "/redfish/v1/AccountService/LDAP/Certificates"))
819 {
820 if (optKeyUsage->empty())
821 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500822 optKeyUsage->emplace_back("ClientAuthentication");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800823 }
824 else if (optKeyUsage->size() == 1)
825 {
826 if ((*optKeyUsage)[0] != "ClientAuthentication")
827 {
828 messages::propertyValueNotInList(asyncResp->res,
829 (*optKeyUsage)[0], "KeyUsage");
830 return;
831 }
832 }
833 else
834 {
835 messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
836 "GenerateCSR");
837 return;
838 }
839 }
840
841 // Only allow one CSR matcher at a time so setting retry
842 // time-out and timer expiry to 10 seconds for now.
843 static const int timeOut = 10;
844 if (csrMatcher)
845 {
846 messages::serviceTemporarilyUnavailable(asyncResp->res,
847 std::to_string(timeOut));
848 return;
849 }
850
851 // Make this static so it survives outside this method
Ed Tanousd98a2f92025-02-06 17:36:31 -0800852 static boost::asio::steady_timer timeout(getIoContext());
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800853 timeout.expires_after(std::chrono::seconds(timeOut));
854 timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
855 csrMatcher = nullptr;
856 if (ec)
857 {
858 // operation_aborted is expected if timer is canceled
859 // before completion.
860 if (ec != boost::asio::error::operation_aborted)
861 {
Ed Tanous62598e32023-07-17 17:06:25 -0700862 BMCWEB_LOG_ERROR("Async_wait failed {}", ec);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800863 }
864 return;
865 }
Ed Tanous62598e32023-07-17 17:06:25 -0700866 BMCWEB_LOG_ERROR("Timed out waiting for Generating CSR");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800867 messages::internalError(asyncResp->res);
868 });
869
870 // create a matcher to wait on CSR object
Ed Tanous62598e32023-07-17 17:06:25 -0700871 BMCWEB_LOG_DEBUG("create matcher with path {}", objectPath);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800872 std::string match("type='signal',"
873 "interface='org.freedesktop.DBus.ObjectManager',"
874 "path='" +
875 objectPath +
876 "',"
877 "member='InterfacesAdded'");
878 csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
879 *crow::connections::systemBus, match,
880 [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400881 timeout.cancel();
882 if (m.is_method_error())
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800883 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400884 BMCWEB_LOG_ERROR("Dbus method error!!!");
885 messages::internalError(asyncResp->res);
886 return;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800887 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400888
889 dbus::utility::DBusInterfacesMap interfacesProperties;
890
891 sdbusplus::message::object_path csrObjectPath;
892 m.read(csrObjectPath, interfacesProperties);
893 BMCWEB_LOG_DEBUG("CSR object added{}", csrObjectPath.str);
894 for (const auto& interface : interfacesProperties)
895 {
896 if (interface.first == "xyz.openbmc_project.Certs.CSR")
897 {
898 getCSR(asyncResp, certURI, service, objectPath,
899 csrObjectPath.str);
900 break;
901 }
902 }
903 });
Ed Tanous177612a2025-02-14 15:16:09 -0800904 dbus::utility::async_method_call(
905 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800906 [asyncResp](const boost::system::error_code& ec, const std::string&) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400907 if (ec)
908 {
909 BMCWEB_LOG_ERROR("DBUS response error: {}", ec.message());
910 messages::internalError(asyncResp->res);
911 return;
912 }
913 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800914 service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
915 "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
916 commonName, *optContactPerson, country, *optEmail, *optGivenName,
917 *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm,
918 *optKeyUsage, organization, organizationalUnit, state, *optSurname,
919 *optUnstructuredName);
920}
921
922inline void requestRoutesCertificateService(App& app)
923{
924 BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
925 .privileges(redfish::privileges::getCertificateService)
926 .methods(boost::beast::http::verb::get)(
927 std::bind_front(handleCertificateServiceGet, std::ref(app)));
928
929 BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
930 .privileges(redfish::privileges::getCertificateLocations)
931 .methods(boost::beast::http::verb::get)(
932 std::bind_front(handleCertificateLocationsGet, std::ref(app)));
933
George Liu0fda0f12021-11-16 10:06:17 +0800934 BMCWEB_ROUTE(
935 app,
936 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
Ed Tanoused398212021-06-09 17:05:54 -0700937 .privileges(redfish::privileges::postCertificateService)
Ed Tanous002d39b2022-05-31 08:59:27 -0700938 .methods(boost::beast::http::verb::post)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800939 std::bind_front(handleReplaceCertificateAction, std::ref(app)));
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600940
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800941 BMCWEB_ROUTE(
942 app,
943 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
944 .privileges(redfish::privileges::postCertificateService)
945 .methods(boost::beast::http::verb::post)(
946 std::bind_front(handleGenerateCSRAction, std::ref(app)));
947} // requestRoutesCertificateService
948
949inline void handleHTTPSCertificateCollectionGet(
950 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -0700951 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
952 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800953{
954 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
955 {
956 return;
957 }
958
Ed Tanous253f11b2024-05-16 09:38:31 -0700959 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
960 {
961 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
962 return;
963 }
964
965 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
966 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
967 BMCWEB_REDFISH_MANAGER_URI_NAME);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800968 asyncResp->res.jsonValue["@odata.type"] =
969 "#CertificateCollection.CertificateCollection";
970 asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
971 asyncResp->res.jsonValue["Description"] =
972 "A Collection of HTTPS certificate instances";
973
974 getCertificateList(asyncResp, certs::httpsObjectPath,
975 "/Members"_json_pointer,
976 "/Members@odata.count"_json_pointer);
977}
978
979inline void handleHTTPSCertificateCollectionPost(
980 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -0700981 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
982 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800983{
984 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
985 {
986 return;
987 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700988
989 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
990 {
991 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
992 return;
993 }
994
Ed Tanous62598e32023-07-17 17:06:25 -0700995 BMCWEB_LOG_DEBUG("HTTPSCertificateCollection::doPost");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800996
997 asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
998 asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
999
Ed Tanousb2896142024-01-31 15:25:47 -08001000 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001001
Ed Tanousb2896142024-01-31 15:25:47 -08001002 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001003 {
Ed Tanous62598e32023-07-17 17:06:25 -07001004 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001005 messages::unrecognizedRequestBody(asyncResp->res);
1006 return;
1007 }
1008
1009 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001010 std::make_shared<CertificateFile>(certHttpBody);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001011
Ed Tanous177612a2025-02-14 15:16:09 -08001012 dbus::utility::async_method_call(
1013 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001014 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001015 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001016 if (ec)
1017 {
1018 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1019 messages::internalError(asyncResp->res);
1020 return;
1021 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001022
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001023 sdbusplus::message::object_path path(objectPath);
1024 std::string certId = path.filename();
1025 const boost::urls::url certURL = boost::urls::format(
1026 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
1027 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1028 getCertificateProperties(asyncResp, objectPath,
1029 certs::httpsServiceName, certId, certURL,
1030 "HTTPS Certificate");
1031 BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
1032 certFile->getCertFilePath());
1033 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001034 certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
1035 "Install", certFile->getCertFilePath());
1036}
Ed Tanous002d39b2022-05-31 08:59:27 -07001037
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001038inline void handleHTTPSCertificateGet(
1039 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001040 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1041 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001042{
1043 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1044 {
1045 return;
1046 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001047
Ed Tanous253f11b2024-05-16 09:38:31 -07001048 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1049 {
1050 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1051 return;
1052 }
1053
1054 BMCWEB_LOG_DEBUG("HTTPS Certificate ID={}", certId);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001055 const boost::urls::url certURL = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001056 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
1057 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001058 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001059 sdbusplus::message::object_path(certs::httpsObjectPath) / certId;
1060 getCertificateProperties(asyncResp, objPath, certs::httpsServiceName,
1061 certId, certURL, "HTTPS Certificate");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001062}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001063
1064inline void requestRoutesHTTPSCertificate(App& app)
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001065{
Ed Tanous253f11b2024-05-16 09:38:31 -07001066 BMCWEB_ROUTE(
1067 app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001068 .privileges(redfish::privileges::getCertificateCollection)
1069 .methods(boost::beast::http::verb::get)(std::bind_front(
1070 handleHTTPSCertificateCollectionGet, std::ref(app)));
1071
Ed Tanous253f11b2024-05-16 09:38:31 -07001072 BMCWEB_ROUTE(
1073 app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001074 .privileges(redfish::privileges::postCertificateCollection)
1075 .methods(boost::beast::http::verb::post)(std::bind_front(
1076 handleHTTPSCertificateCollectionPost, std::ref(app)));
1077
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001078 BMCWEB_ROUTE(
1079 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001080 "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001081 .privileges(redfish::privileges::getCertificate)
Jiaqing Zhao1e312592022-06-14 12:58:09 +08001082 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001083 std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001084}
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001085
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001086inline void handleLDAPCertificateCollectionGet(
1087 App& app, const crow::Request& req,
1088 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001089{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001090 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1091 {
1092 return;
1093 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001094
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001095 asyncResp->res.jsonValue["@odata.id"] =
1096 "/redfish/v1/AccountService/LDAP/Certificates";
1097 asyncResp->res.jsonValue["@odata.type"] =
1098 "#CertificateCollection.CertificateCollection";
1099 asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
1100 asyncResp->res.jsonValue["Description"] =
1101 "A Collection of LDAP certificate instances";
Ed Tanous002d39b2022-05-31 08:59:27 -07001102
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001103 getCertificateList(asyncResp, certs::ldapObjectPath,
1104 "/Members"_json_pointer,
1105 "/Members@odata.count"_json_pointer);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001106}
Marri Devender Rao37cce912019-02-20 01:05:22 -06001107
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001108inline void handleLDAPCertificateCollectionPost(
1109 App& app, const crow::Request& req,
1110 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao37cce912019-02-20 01:05:22 -06001111{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001112 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1113 {
1114 return;
1115 }
Ed Tanousb2896142024-01-31 15:25:47 -08001116 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001117
Ed Tanousb2896142024-01-31 15:25:47 -08001118 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001119 {
Ed Tanous62598e32023-07-17 17:06:25 -07001120 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001121 messages::unrecognizedRequestBody(asyncResp->res);
1122 return;
1123 }
1124
1125 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001126 std::make_shared<CertificateFile>(certHttpBody);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001127
Ed Tanous177612a2025-02-14 15:16:09 -08001128 dbus::utility::async_method_call(
1129 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001130 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001131 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001132 if (ec)
1133 {
1134 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1135 messages::internalError(asyncResp->res);
1136 return;
1137 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001138
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001139 sdbusplus::message::object_path path(objectPath);
1140 std::string certId = path.filename();
1141 const boost::urls::url certURL = boost::urls::format(
1142 "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
1143 getCertificateProperties(asyncResp, objectPath,
1144 certs::ldapServiceName, certId, certURL,
1145 "LDAP Certificate");
1146 BMCWEB_LOG_DEBUG("LDAP certificate install file={}",
1147 certFile->getCertFilePath());
1148 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001149 certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
1150 "Install", certFile->getCertFilePath());
1151}
Ed Tanous002d39b2022-05-31 08:59:27 -07001152
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001153inline void handleLDAPCertificateGet(
1154 App& app, const crow::Request& req,
1155 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1156{
1157 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1158 {
1159 return;
1160 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001161
Ed Tanous62598e32023-07-17 17:06:25 -07001162 BMCWEB_LOG_DEBUG("LDAP Certificate ID={}", id);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001163 const boost::urls::url certURL = boost::urls::format(
1164 "/redfish/v1/AccountService/LDAP/Certificates/{}", id);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001165 std::string objPath =
1166 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1167 getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1168 certURL, "LDAP Certificate");
1169}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001170
Jiaqing Zhao99612242022-09-29 15:31:09 +08001171inline void handleLDAPCertificateDelete(
1172 App& app, const crow::Request& req,
1173 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1174{
1175 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1176 {
1177 return;
1178 }
1179
Ed Tanous62598e32023-07-17 17:06:25 -07001180 BMCWEB_LOG_DEBUG("Delete LDAP Certificate ID={}", id);
Jiaqing Zhao99612242022-09-29 15:31:09 +08001181 std::string objPath =
1182 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1183
1184 deleteCertificate(asyncResp, certs::ldapServiceName, objPath);
1185}
1186
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001187inline void requestRoutesLDAPCertificate(App& app)
Marri Devender Rao37cce912019-02-20 01:05:22 -06001188{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001189 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1190 .privileges(redfish::privileges::getCertificateCollection)
1191 .methods(boost::beast::http::verb::get)(
1192 std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app)));
1193
1194 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1195 .privileges(redfish::privileges::postCertificateCollection)
1196 .methods(boost::beast::http::verb::post)(std::bind_front(
1197 handleLDAPCertificateCollectionPost, std::ref(app)));
1198
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001199 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001200 .privileges(redfish::privileges::getCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001201 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001202 std::bind_front(handleLDAPCertificateGet, std::ref(app)));
Jiaqing Zhao99612242022-09-29 15:31:09 +08001203
1204 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1205 .privileges(redfish::privileges::deleteCertificate)
1206 .methods(boost::beast::http::verb::delete_)(
1207 std::bind_front(handleLDAPCertificateDelete, std::ref(app)));
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001208} // requestRoutesLDAPCertificate
1209
1210inline void handleTrustStoreCertificateCollectionGet(
1211 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001212 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1213 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001214{
1215 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1216 {
1217 return;
1218 }
1219
Ed Tanous253f11b2024-05-16 09:38:31 -07001220 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1221 {
1222 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1223 return;
1224 }
1225
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001226 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07001227 boost::urls::format("/redfish/v1/Managers/{}/Truststore/Certificates/",
1228 BMCWEB_REDFISH_MANAGER_URI_NAME);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001229 asyncResp->res.jsonValue["@odata.type"] =
1230 "#CertificateCollection.CertificateCollection";
1231 asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
1232 asyncResp->res.jsonValue["Description"] =
1233 "A Collection of TrustStore certificate instances";
1234
1235 getCertificateList(asyncResp, certs::authorityObjectPath,
1236 "/Members"_json_pointer,
1237 "/Members@odata.count"_json_pointer);
1238}
1239
1240inline void handleTrustStoreCertificateCollectionPost(
1241 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001242 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1243 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001244{
1245 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1246 {
1247 return;
1248 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001249
1250 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1251 {
1252 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1253 return;
1254 }
1255
Ed Tanousb2896142024-01-31 15:25:47 -08001256 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001257
Ed Tanousb2896142024-01-31 15:25:47 -08001258 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001259 {
Ed Tanous62598e32023-07-17 17:06:25 -07001260 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001261 messages::unrecognizedRequestBody(asyncResp->res);
1262 return;
1263 }
1264
1265 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001266 std::make_shared<CertificateFile>(certHttpBody);
Ed Tanous177612a2025-02-14 15:16:09 -08001267 dbus::utility::async_method_call(
1268 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001269 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001270 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001271 if (ec)
1272 {
1273 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1274 messages::internalError(asyncResp->res);
1275 return;
1276 }
Jiaqing Zhao717b9802022-06-06 20:24:04 +08001277
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001278 sdbusplus::message::object_path path(objectPath);
1279 std::string certId = path.filename();
1280 const boost::urls::url certURL = boost::urls::format(
1281 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1282 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1283 getCertificateProperties(asyncResp, objectPath,
1284 certs::authorityServiceName, certId,
1285 certURL, "TrustStore Certificate");
1286 BMCWEB_LOG_DEBUG("TrustStore certificate install file={}",
1287 certFile->getCertFilePath());
1288 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001289 certs::authorityServiceName, certs::authorityObjectPath,
1290 certs::certInstallIntf, "Install", certFile->getCertFilePath());
1291}
1292
1293inline void handleTrustStoreCertificateGet(
1294 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001295 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1296 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001297{
1298 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1299 {
1300 return;
1301 }
1302
Ed Tanous253f11b2024-05-16 09:38:31 -07001303 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1304 {
1305 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1306 return;
1307 }
1308
1309 BMCWEB_LOG_DEBUG("Truststore Certificate ID={}", certId);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001310 const boost::urls::url certURL = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001311 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1312 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001313 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001314 sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001315 getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
Ed Tanous253f11b2024-05-16 09:38:31 -07001316 certId, certURL, "TrustStore Certificate");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001317}
1318
1319inline void handleTrustStoreCertificateDelete(
1320 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001321 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1322 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001323{
1324 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1325 {
1326 return;
1327 }
1328
Ed Tanous253f11b2024-05-16 09:38:31 -07001329 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1330 {
1331 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1332 return;
1333 }
1334
1335 BMCWEB_LOG_DEBUG("Delete TrustStore Certificate ID={}", certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001336 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001337 sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001338
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +08001339 deleteCertificate(asyncResp, certs::authorityServiceName, objPath);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001340}
1341
1342inline void requestRoutesTrustStoreCertificate(App& app)
Marri Devender Raocfcd5f62019-05-17 08:34:37 -05001343{
Ed Tanous253f11b2024-05-16 09:38:31 -07001344 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
Ed Tanoused398212021-06-09 17:05:54 -07001345 .privileges(redfish::privileges::getCertificate)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001346 .methods(boost::beast::http::verb::get)(std::bind_front(
1347 handleTrustStoreCertificateCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001348
Ed Tanous253f11b2024-05-16 09:38:31 -07001349 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
Ed Tanoused398212021-06-09 17:05:54 -07001350 .privileges(redfish::privileges::postCertificateCollection)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001351 .methods(boost::beast::http::verb::post)(std::bind_front(
1352 handleTrustStoreCertificateCollectionPost, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001353
Ed Tanous253f11b2024-05-16 09:38:31 -07001354 BMCWEB_ROUTE(app,
1355 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001356 .privileges(redfish::privileges::getCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001357 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001358 std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001359
Ed Tanous253f11b2024-05-16 09:38:31 -07001360 BMCWEB_ROUTE(app,
1361 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001362 .privileges(redfish::privileges::deleteCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001363 .methods(boost::beast::http::verb::delete_)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001364 std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001365} // requestRoutesTrustStoreCertificate
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001366} // namespace redfish