blob: 6d69bc9f3960004907003d1afb895567c8ae5d3d [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";
68constexpr const char* dbusPropIntf = "org.freedesktop.DBus.Properties";
69constexpr const char* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
70constexpr const char* httpsServiceName =
Marri Devender Rao37cce912019-02-20 01:05:22 -060071 "xyz.openbmc_project.Certs.Manager.Server.Https";
Patrick Williams89492a12023-05-10 07:51:34 -050072constexpr const char* ldapServiceName =
Marri Devender Rao37cce912019-02-20 01:05:22 -060073 "xyz.openbmc_project.Certs.Manager.Client.Ldap";
Patrick Williams89492a12023-05-10 07:51:34 -050074constexpr const char* authorityServiceName =
Michal Orzelb2254cc2023-07-27 14:08:32 +020075 "xyz.openbmc_project.Certs.Manager.Authority.Truststore";
Patrick Williams89492a12023-05-10 07:51:34 -050076constexpr const char* baseObjectPath = "/xyz/openbmc_project/certs";
77constexpr const char* httpsObjectPath =
Jiaqing Zhaoc6a8dfb2022-06-03 10:44:23 +080078 "/xyz/openbmc_project/certs/server/https";
Patrick Williams89492a12023-05-10 07:51:34 -050079constexpr const char* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
80constexpr const char* authorityObjectPath =
Michal Orzelb2254cc2023-07-27 14:08:32 +020081 "/xyz/openbmc_project/certs/authority/truststore";
Marri Devender Rao5968cae2019-01-21 10:27:12 -060082} // namespace certs
83
84/**
85 * The Certificate schema defines a Certificate Service which represents the
86 * actions available to manage certificates and links to where certificates
87 * are installed.
88 */
Marri Devender Rao5968cae2019-01-21 10:27:12 -060089
zhanghch058d1b46d2021-04-01 11:18:24 +080090inline std::string getCertificateFromReqBody(
91 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
92 const crow::Request& req)
Kowalski, Kamil58eb2382019-08-12 11:54:31 +020093{
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010094 nlohmann::json reqJson;
95 JsonParseResult ret = parseRequestAsJson(req, reqJson);
96 if (ret != JsonParseResult::Success)
Kowalski, Kamil58eb2382019-08-12 11:54:31 +020097 {
98 // We did not receive JSON request, proceed as it is RAW data
Ed Tanous33c6b582023-02-14 15:05:48 -080099 return req.body();
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200100 }
101
102 std::string certificate;
103 std::optional<std::string> certificateType = "PEM";
104
Patrick Williams504af5a2025-02-03 14:29:03 -0500105 if (!json_util::readJsonPatch( //
106 req, asyncResp->res, //
107 "CertificateString", certificate, //
Myung Baeafc474a2024-10-09 00:53:29 -0700108 "CertificateType", certificateType //
109 ))
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200110 {
Ed Tanous62598e32023-07-17 17:06:25 -0700111 BMCWEB_LOG_ERROR("Required parameters are missing");
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200112 messages::internalError(asyncResp->res);
Ed Tanousabb93cd2021-09-02 14:34:57 -0700113 return {};
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200114 }
115
116 if (*certificateType != "PEM")
117 {
118 messages::propertyValueNotInList(asyncResp->res, *certificateType,
119 "CertificateType");
Ed Tanousabb93cd2021-09-02 14:34:57 -0700120 return {};
Kowalski, Kamil58eb2382019-08-12 11:54:31 +0200121 }
122
123 return certificate;
124}
125
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600126/**
127 * Class to create a temporary certificate file for uploading to system
128 */
129class CertificateFile
130{
131 public:
132 CertificateFile() = delete;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500133 CertificateFile(const CertificateFile&) = delete;
134 CertificateFile& operator=(const CertificateFile&) = delete;
135 CertificateFile(CertificateFile&&) = delete;
136 CertificateFile& operator=(CertificateFile&&) = delete;
Ed Tanous4e23a442022-06-06 09:57:26 -0700137 explicit CertificateFile(const std::string& certString)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600138 {
Ed Tanous72d52d22020-10-12 07:46:27 -0700139 std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
Ed Tanous52074382020-09-28 19:16:18 -0700140 'e', 'r', 't', 's', '.', 'X',
141 'X', 'X', 'X', 'X', 'X', '\0'};
Myung Bae92e11bf2025-01-31 09:22:23 -0500142 // NOLINTNEXTLINE(misc-include-cleaner)
Ed Tanous52074382020-09-28 19:16:18 -0700143 char* tempDirectory = mkdtemp(dirTemplate.data());
Ed Tanouse662eae2022-01-25 10:39:19 -0800144 if (tempDirectory != nullptr)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600145 {
146 certDirectory = tempDirectory;
147 certificateFile = certDirectory / "cert.pem";
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400148 std::ofstream out(certificateFile,
149 std::ofstream::out | std::ofstream::binary |
150 std::ofstream::trunc);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600151 out << certString;
152 out.close();
Ed Tanous62598e32023-07-17 17:06:25 -0700153 BMCWEB_LOG_DEBUG("Creating certificate file{}",
154 certificateFile.string());
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600155 }
156 }
157 ~CertificateFile()
158 {
159 if (std::filesystem::exists(certDirectory))
160 {
Ed Tanous62598e32023-07-17 17:06:25 -0700161 BMCWEB_LOG_DEBUG("Removing certificate file{}",
162 certificateFile.string());
Ed Tanous23a21a12020-07-25 04:45:05 +0000163 std::error_code ec;
164 std::filesystem::remove_all(certDirectory, ec);
165 if (ec)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600166 {
Ed Tanous62598e32023-07-17 17:06:25 -0700167 BMCWEB_LOG_ERROR("Failed to remove temp directory{}",
168 certDirectory.string());
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600169 }
170 }
171 }
172 std::string getCertFilePath()
173 {
174 return certificateFile;
175 }
176
177 private:
178 std::filesystem::path certificateFile;
179 std::filesystem::path certDirectory;
180};
181
182/**
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500183 * @brief Parse and update Certificate Issue/Subject property
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600184 *
185 * @param[in] asyncResp Shared pointer to the response message
186 * @param[in] str Issuer/Subject value in key=value pairs
187 * @param[in] type Issuer/Subject
188 * @return None
189 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700190inline void updateCertIssuerOrSubject(nlohmann::json& out,
Ed Tanous26ccae32023-02-16 10:28:44 -0800191 std::string_view value)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600192{
193 // example: O=openbmc-project.xyz,CN=localhost
194 std::string_view::iterator i = value.begin();
195 while (i != value.end())
196 {
197 std::string_view::iterator tokenBegin = i;
198 while (i != value.end() && *i != '=')
199 {
Patrick Williams6da47ba2023-05-11 11:53:56 -0500200 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600201 }
202 if (i == value.end())
203 {
204 break;
205 }
Ed Tanous26ccae32023-02-16 10:28:44 -0800206 std::string_view key(tokenBegin, static_cast<size_t>(i - tokenBegin));
Patrick Williams6da47ba2023-05-11 11:53:56 -0500207 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600208 tokenBegin = i;
209 while (i != value.end() && *i != ',')
210 {
Patrick Williams6da47ba2023-05-11 11:53:56 -0500211 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600212 }
Ed Tanous26ccae32023-02-16 10:28:44 -0800213 std::string_view val(tokenBegin, static_cast<size_t>(i - tokenBegin));
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600214 if (key == "L")
215 {
216 out["City"] = val;
217 }
218 else if (key == "CN")
219 {
220 out["CommonName"] = val;
221 }
222 else if (key == "C")
223 {
224 out["Country"] = val;
225 }
226 else if (key == "O")
227 {
228 out["Organization"] = val;
229 }
230 else if (key == "OU")
231 {
232 out["OrganizationalUnit"] = val;
233 }
234 else if (key == "ST")
235 {
236 out["State"] = val;
237 }
238 // skip comma character
239 if (i != value.end())
240 {
Patrick Williams6da47ba2023-05-11 11:53:56 -0500241 std::advance(i, 1);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600242 }
243 }
244}
245
246/**
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800247 * @brief Retrieve the installed certificate list
248 *
249 * @param[in] asyncResp Shared pointer to the response message
250 * @param[in] basePath DBus object path to search
251 * @param[in] listPtr Json pointer to the list in asyncResp
252 * @param[in] countPtr Json pointer to the count in asyncResp
253 * @return None
254 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700255inline void getCertificateList(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400256 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
257 const std::string& basePath, const nlohmann::json::json_pointer& listPtr,
258 const nlohmann::json::json_pointer& countPtr)
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800259{
George Liu7a1dbc42022-12-07 16:03:22 +0800260 constexpr std::array<std::string_view, 1> interfaces = {
261 certs::certPropIntf};
262 dbus::utility::getSubTreePaths(
263 basePath, 0, interfaces,
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800264 [asyncResp, listPtr, countPtr](
George Liu7a1dbc42022-12-07 16:03:22 +0800265 const boost::system::error_code& ec,
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800266 const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400267 if (ec)
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800268 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400269 BMCWEB_LOG_ERROR("Certificate collection query failed: {}", ec);
270 messages::internalError(asyncResp->res);
271 return;
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800272 }
273
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400274 nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
275 links = nlohmann::json::array();
276 for (const auto& certPath : certPaths)
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800277 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400278 sdbusplus::message::object_path objPath(certPath);
279 std::string certId = objPath.filename();
280 if (certId.empty())
281 {
282 BMCWEB_LOG_ERROR("Invalid certificate objPath {}",
283 certPath);
284 continue;
285 }
286
287 boost::urls::url certURL;
288 if (objPath.parent_path() == certs::httpsObjectPath)
289 {
290 certURL = boost::urls::format(
291 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
292 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
293 }
294 else if (objPath.parent_path() == certs::ldapObjectPath)
295 {
296 certURL = boost::urls::format(
297 "/redfish/v1/AccountService/LDAP/Certificates/{}",
298 certId);
299 }
300 else if (objPath.parent_path() == certs::authorityObjectPath)
301 {
302 certURL = boost::urls::format(
303 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
304 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
305 }
306 else
307 {
308 continue;
309 }
310
311 nlohmann::json::object_t link;
312 link["@odata.id"] = certURL;
313 links.emplace_back(std::move(link));
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800314 }
315
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400316 asyncResp->res.jsonValue[countPtr] = links.size();
317 });
Jiaqing Zhaod3f92ce2022-06-03 11:46:12 +0800318}
319
320/**
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600321 * @brief Retrieve the certificates properties and append to the response
322 * message
323 *
324 * @param[in] asyncResp Shared pointer to the response message
325 * @param[in] objectPath Path of the D-Bus service object
326 * @param[in] certId Id of the certificate
327 * @param[in] certURL URL of the certificate object
328 * @param[in] name name of the certificate
329 * @return None
330 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700331inline void getCertificateProperties(
zhanghch058d1b46d2021-04-01 11:18:24 +0800332 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhaoe19e97e2022-06-06 19:43:39 +0800333 const std::string& objectPath, const std::string& service,
Jiaqing Zhao1e312592022-06-14 12:58:09 +0800334 const std::string& certId, const boost::urls::url& certURL,
Jiaqing Zhaoe19e97e2022-06-06 19:43:39 +0800335 const std::string& name)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600336{
Ed Tanous62598e32023-07-17 17:06:25 -0700337 BMCWEB_LOG_DEBUG("getCertificateProperties Path={} certId={} certURl={}",
338 objectPath, certId, certURL);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800339 dbus::utility::getAllProperties(
340 service, objectPath, certs::certPropIntf,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800341 [asyncResp, certURL, certId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800342 name](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800343 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400344 if (ec)
345 {
346 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
347 messages::resourceNotFound(asyncResp->res, "Certificate",
348 certId);
349 return;
350 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200351
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400352 const std::string* certificateString = nullptr;
353 const std::vector<std::string>* keyUsage = nullptr;
354 const std::string* issuer = nullptr;
355 const std::string* subject = nullptr;
356 const uint64_t* validNotAfter = nullptr;
357 const uint64_t* validNotBefore = nullptr;
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200358
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400359 const bool success = sdbusplus::unpackPropertiesNoThrow(
360 dbus_utils::UnpackErrorPrinter(), properties,
361 "CertificateString", certificateString, "KeyUsage", keyUsage,
362 "Issuer", issuer, "Subject", subject, "ValidNotAfter",
363 validNotAfter, "ValidNotBefore", validNotBefore);
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200364
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400365 if (!success)
366 {
367 messages::internalError(asyncResp->res);
368 return;
369 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200370
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400371 asyncResp->res.jsonValue["@odata.id"] = certURL;
372 asyncResp->res.jsonValue["@odata.type"] =
373 "#Certificate.v1_0_0.Certificate";
374 asyncResp->res.jsonValue["Id"] = certId;
375 asyncResp->res.jsonValue["Name"] = name;
376 asyncResp->res.jsonValue["Description"] = name;
377 asyncResp->res.jsonValue["CertificateString"] = "";
378 asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array();
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200379
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400380 if (certificateString != nullptr)
381 {
382 asyncResp->res.jsonValue["CertificateString"] =
383 *certificateString;
384 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200385
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400386 if (keyUsage != nullptr)
387 {
388 asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
389 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200390
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400391 if (issuer != nullptr)
392 {
393 updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
394 *issuer);
395 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200396
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400397 if (subject != nullptr)
398 {
399 updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
400 *subject);
401 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200402
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400403 if (validNotAfter != nullptr)
404 {
405 asyncResp->res.jsonValue["ValidNotAfter"] =
406 redfish::time_utils::getDateTimeUint(*validNotAfter);
407 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200408
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400409 if (validNotBefore != nullptr)
410 {
411 asyncResp->res.jsonValue["ValidNotBefore"] =
412 redfish::time_utils::getDateTimeUint(*validNotBefore);
413 }
Krzysztof Grobelny9b12d1f2022-08-11 09:52:56 +0200414
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400415 asyncResp->res.addHeader(
416 boost::beast::http::field::location,
417 std::string_view(certURL.data(), certURL.size()));
418 });
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600419}
420
Patrick Williams504af5a2025-02-03 14:29:03 -0500421inline void deleteCertificate(
422 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
423 const std::string& service,
424 const sdbusplus::message::object_path& objectPath)
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +0800425{
Ed Tanous177612a2025-02-14 15:16:09 -0800426 dbus::utility::async_method_call(
427 asyncResp,
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +0800428 [asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800429 id{objectPath.filename()}](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400430 if (ec)
431 {
432 messages::resourceNotFound(asyncResp->res, "Certificate", id);
433 return;
434 }
435 BMCWEB_LOG_INFO("Certificate deleted");
436 asyncResp->res.result(boost::beast::http::status::no_content);
437 },
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +0800438 service, objectPath, certs::objDeleteIntf, "Delete");
439}
440
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800441inline void handleCertificateServiceGet(
442 App& app, const crow::Request& req,
443 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600444{
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800445 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
446 {
447 return;
448 }
449
Ninad Palsule3e72c202023-03-27 17:19:55 -0500450 if (req.session == nullptr)
451 {
452 messages::internalError(asyncResp->res);
453 return;
454 }
455
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800456 asyncResp->res.jsonValue["@odata.type"] =
457 "#CertificateService.v1_0_0.CertificateService";
458 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService";
459 asyncResp->res.jsonValue["Id"] = "CertificateService";
460 asyncResp->res.jsonValue["Name"] = "Certificate Service";
461 asyncResp->res.jsonValue["Description"] =
462 "Actions available to manage certificates";
463 // /redfish/v1/CertificateService/CertificateLocations is something
464 // only ConfigureManager can access then only display when the user
465 // has permissions ConfigureManager
466 Privileges effectiveUserPrivileges =
Ninad Palsule3e72c202023-03-27 17:19:55 -0500467 redfish::getUserPrivileges(*req.session);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800468 if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
469 effectiveUserPrivileges))
470 {
471 asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
472 "/redfish/v1/CertificateService/CertificateLocations";
473 }
474 nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
475 nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"];
476 replace["target"] =
477 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate";
478 nlohmann::json::array_t allowed;
Patrick Williamsad539542023-05-12 10:10:08 -0500479 allowed.emplace_back("PEM");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800480 replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
481 actions["#CertificateService.GenerateCSR"]["target"] =
482 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
483}
484
485inline void handleCertificateLocationsGet(
486 App& app, const crow::Request& req,
487 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
488{
489 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
490 {
491 return;
492 }
493 asyncResp->res.jsonValue["@odata.id"] =
494 "/redfish/v1/CertificateService/CertificateLocations";
495 asyncResp->res.jsonValue["@odata.type"] =
496 "#CertificateLocations.v1_0_0.CertificateLocations";
497 asyncResp->res.jsonValue["Name"] = "Certificate Locations";
498 asyncResp->res.jsonValue["Id"] = "CertificateLocations";
499 asyncResp->res.jsonValue["Description"] =
500 "Defines a resource that an administrator can use in order to "
501 "locate all certificates installed on a given service";
502
503 getCertificateList(asyncResp, certs::baseObjectPath,
504 "/Links/Certificates"_json_pointer,
505 "/Links/Certificates@odata.count"_json_pointer);
506}
507
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530508inline void handleError(const std::string_view dbusErrorName,
509 const std::string& id, const std::string& certificate,
510 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
511{
512 if (dbusErrorName == "org.freedesktop.DBus.Error.UnknownObject")
513 {
514 messages::resourceNotFound(asyncResp->res, "Certificate", id);
515 }
516 else if (dbusErrorName ==
517 "xyz.openbmc_project.Certs.Error.InvalidCertificate")
518 {
519 messages::propertyValueIncorrect(asyncResp->res, "Certificate",
520 certificate);
521 }
522 else
523 {
524 messages::internalError(asyncResp->res);
525 }
526}
527
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800528inline void handleReplaceCertificateAction(
529 App& app, const crow::Request& req,
530 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
531{
532 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
533 {
534 return;
535 }
536 std::string certificate;
Ed Tanous7a31e332024-03-06 12:17:43 -0800537 std::string certURI;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800538 std::optional<std::string> certificateType = "PEM";
539
Patrick Williams504af5a2025-02-03 14:29:03 -0500540 if (!json_util::readJsonAction( //
541 req, asyncResp->res, //
542 "CertificateString", certificate, //
Myung Baeafc474a2024-10-09 00:53:29 -0700543 "CertificateType", certificateType, //
544 "CertificateUri/@odata.id", certURI //
545 ))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800546 {
Ed Tanous62598e32023-07-17 17:06:25 -0700547 BMCWEB_LOG_ERROR("Required parameters are missing");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800548 return;
549 }
550
551 if (!certificateType)
552 {
553 // should never happen, but it never hurts to be paranoid.
554 return;
555 }
556 if (certificateType != "PEM")
557 {
558 messages::actionParameterNotSupported(asyncResp->res, "CertificateType",
559 "ReplaceCertificate");
560 return;
561 }
562
Ed Tanous62598e32023-07-17 17:06:25 -0700563 BMCWEB_LOG_INFO("Certificate URI to replace: {}", certURI);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800564
Ed Tanous6fd29552023-10-04 09:40:14 -0700565 boost::system::result<boost::urls::url> parsedUrl =
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800566 boost::urls::parse_relative_ref(certURI);
567 if (!parsedUrl)
568 {
569 messages::actionParameterValueFormatError(
570 asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate");
571 return;
572 }
573
574 std::string id;
575 sdbusplus::message::object_path objectPath;
576 std::string name;
577 std::string service;
578 if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers",
579 "bmc", "NetworkProtocol", "HTTPS",
580 "Certificates", std::ref(id)))
581 {
Patrick Williams89492a12023-05-10 07:51:34 -0500582 objectPath = sdbusplus::message::object_path(certs::httpsObjectPath) /
583 id;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800584 name = "HTTPS certificate";
585 service = certs::httpsServiceName;
586 }
587 else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
588 "AccountService", "LDAP",
589 "Certificates", std::ref(id)))
590 {
Patrick Williams89492a12023-05-10 07:51:34 -0500591 objectPath = sdbusplus::message::object_path(certs::ldapObjectPath) /
592 id;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800593 name = "LDAP certificate";
594 service = certs::ldapServiceName;
595 }
596 else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
597 "Managers", "bmc", "Truststore",
598 "Certificates", std::ref(id)))
599 {
600 objectPath =
601 sdbusplus::message::object_path(certs::authorityObjectPath) / id;
602 name = "TrustStore certificate";
603 service = certs::authorityServiceName;
604 }
605 else
606 {
607 messages::actionParameterNotSupported(asyncResp->res, "CertificateUri",
608 "ReplaceCertificate");
609 return;
610 }
611
612 std::shared_ptr<CertificateFile> certFile =
613 std::make_shared<CertificateFile>(certificate);
Ed Tanous177612a2025-02-14 15:16:09 -0800614 dbus::utility::async_method_call(
615 asyncResp,
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530616 [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id, name,
617 certificate](const boost::system::error_code& ec,
Patrick Williamsd3e08592024-09-27 02:39:55 -0400618 sdbusplus::message_t& m) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400619 if (ec)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800620 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400621 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530622 const sd_bus_error* dbusError = m.get_error();
623 if ((dbusError != nullptr) && (dbusError->name != nullptr))
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400624 {
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530625 handleError(dbusError->name, id, certificate, asyncResp);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400626 }
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530627 else
628 {
629 messages::internalError(asyncResp->res);
630 }
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800631 return;
632 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400633 getCertificateProperties(asyncResp, objectPath, service, id, url,
634 name);
635 BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
636 certFile->getCertFilePath());
637 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800638 service, objectPath, certs::certReplaceIntf, "Replace",
639 certFile->getCertFilePath());
640}
641
Ed Tanouscf9e4172022-12-21 09:30:16 -0800642// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800643static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
644/**
645 * @brief Read data from CSR D-bus object and set to response
646 *
647 * @param[in] asyncResp Shared pointer to the response message
Ed Tanous8ece0e42024-01-02 13:16:50 -0800648 * @param[in] certURI Link to certificate collection URI
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800649 * @param[in] service D-Bus service name
650 * @param[in] certObjPath certificate D-Bus object path
651 * @param[in] csrObjPath CSR D-Bus object path
652 * @return None
653 */
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700654inline void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800655 const std::string& certURI, const std::string& service,
656 const std::string& certObjPath,
657 const std::string& csrObjPath)
658{
Ed Tanous62598e32023-07-17 17:06:25 -0700659 BMCWEB_LOG_DEBUG("getCSR CertObjectPath{} CSRObjectPath={} service={}",
660 certObjPath, csrObjPath, service);
Ed Tanous177612a2025-02-14 15:16:09 -0800661 dbus::utility::async_method_call(
662 asyncResp,
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400663 [asyncResp,
664 certURI](const boost::system::error_code& ec, const std::string& csr) {
665 if (ec)
666 {
667 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
668 messages::internalError(asyncResp->res);
669 return;
670 }
671 if (csr.empty())
672 {
673 BMCWEB_LOG_ERROR("CSR read is empty");
674 messages::internalError(asyncResp->res);
675 return;
676 }
677 asyncResp->res.jsonValue["CSRString"] = csr;
678 asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
679 certURI;
680 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800681 service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
682}
683
Patrick Williams504af5a2025-02-03 14:29:03 -0500684inline void handleGenerateCSRAction(
685 App& app, const crow::Request& req,
686 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800687{
688 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
689 {
690 return;
691 }
692 static const int rsaKeyBitLength = 2048;
693
694 // Required parameters
695 std::string city;
696 std::string commonName;
697 std::string country;
698 std::string organization;
699 std::string organizationalUnit;
700 std::string state;
Ed Tanous7a31e332024-03-06 12:17:43 -0800701 std::string certURI;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800702
703 // Optional parameters
704 std::optional<std::vector<std::string>> optAlternativeNames =
705 std::vector<std::string>();
706 std::optional<std::string> optContactPerson = "";
707 std::optional<std::string> optChallengePassword = "";
708 std::optional<std::string> optEmail = "";
709 std::optional<std::string> optGivenName = "";
710 std::optional<std::string> optInitials = "";
711 std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
712 std::optional<std::string> optKeyCurveId = "secp384r1";
713 std::optional<std::string> optKeyPairAlgorithm = "EC";
714 std::optional<std::vector<std::string>> optKeyUsage =
715 std::vector<std::string>();
716 std::optional<std::string> optSurname = "";
717 std::optional<std::string> optUnstructuredName = "";
Patrick Williams504af5a2025-02-03 14:29:03 -0500718 if (!json_util::readJsonAction( //
719 req, asyncResp->res, //
720 "AlternativeNames", optAlternativeNames, //
Myung Baeafc474a2024-10-09 00:53:29 -0700721 "CertificateCollection/@odata.id", certURI, //
Patrick Williams504af5a2025-02-03 14:29:03 -0500722 "ChallengePassword", optChallengePassword, //
723 "City", city, //
724 "CommonName", commonName, //
725 "ContactPerson", optContactPerson, //
726 "Country", country, //
727 "Email", optEmail, //
728 "GivenName", optGivenName, //
729 "Initials", optInitials, //
730 "KeyBitLength", optKeyBitLength, //
731 "KeyCurveId", optKeyCurveId, //
732 "KeyPairAlgorithm", optKeyPairAlgorithm, //
733 "KeyUsage", optKeyUsage, //
734 "Organization", organization, //
735 "OrganizationalUnit", organizationalUnit, //
736 "State", state, //
737 "Surname", optSurname, //
738 "UnstructuredName", optUnstructuredName //
Myung Baeafc474a2024-10-09 00:53:29 -0700739 ))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800740 {
741 return;
742 }
743
744 // bmcweb has no way to store or decode a private key challenge
745 // password, which will likely cause bmcweb to crash on startup
746 // if this is not set on a post so not allowing the user to set
747 // value
748 if (!optChallengePassword->empty())
749 {
750 messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
751 "ChallengePassword");
752 return;
753 }
754
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800755 std::string objectPath;
756 std::string service;
Ed Tanous253f11b2024-05-16 09:38:31 -0700757 if (certURI.starts_with(std::format(
758 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
759 BMCWEB_REDFISH_MANAGER_URI_NAME)))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800760 {
761 objectPath = certs::httpsObjectPath;
762 service = certs::httpsServiceName;
763 }
764 else if (certURI.starts_with(
765 "/redfish/v1/AccountService/LDAP/Certificates"))
766 {
767 objectPath = certs::ldapObjectPath;
768 service = certs::ldapServiceName;
769 }
770 else
771 {
772 messages::actionParameterNotSupported(
773 asyncResp->res, "CertificateCollection", "GenerateCSR");
774 return;
775 }
776
777 // supporting only EC and RSA algorithm
778 if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
779 {
780 messages::actionParameterNotSupported(
781 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
782 return;
783 }
784
785 // supporting only 2048 key bit length for RSA algorithm due to
786 // time consumed in generating private key
787 if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength)
788 {
Ed Tanouse2616cc2022-06-27 12:45:55 -0700789 messages::propertyValueNotInList(asyncResp->res, *optKeyBitLength,
790 "KeyBitLength");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800791 return;
792 }
793
794 // validate KeyUsage supporting only 1 type based on URL
Ed Tanous253f11b2024-05-16 09:38:31 -0700795 if (certURI.starts_with(std::format(
796 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
797 BMCWEB_REDFISH_MANAGER_URI_NAME)))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800798 {
799 if (optKeyUsage->empty())
800 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500801 optKeyUsage->emplace_back("ServerAuthentication");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800802 }
803 else if (optKeyUsage->size() == 1)
804 {
805 if ((*optKeyUsage)[0] != "ServerAuthentication")
806 {
807 messages::propertyValueNotInList(asyncResp->res,
808 (*optKeyUsage)[0], "KeyUsage");
809 return;
810 }
811 }
812 else
813 {
814 messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
815 "GenerateCSR");
816 return;
817 }
818 }
819 else if (certURI.starts_with(
820 "/redfish/v1/AccountService/LDAP/Certificates"))
821 {
822 if (optKeyUsage->empty())
823 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500824 optKeyUsage->emplace_back("ClientAuthentication");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800825 }
826 else if (optKeyUsage->size() == 1)
827 {
828 if ((*optKeyUsage)[0] != "ClientAuthentication")
829 {
830 messages::propertyValueNotInList(asyncResp->res,
831 (*optKeyUsage)[0], "KeyUsage");
832 return;
833 }
834 }
835 else
836 {
837 messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
838 "GenerateCSR");
839 return;
840 }
841 }
842
843 // Only allow one CSR matcher at a time so setting retry
844 // time-out and timer expiry to 10 seconds for now.
845 static const int timeOut = 10;
846 if (csrMatcher)
847 {
848 messages::serviceTemporarilyUnavailable(asyncResp->res,
849 std::to_string(timeOut));
850 return;
851 }
852
853 // Make this static so it survives outside this method
Ed Tanousd98a2f92025-02-06 17:36:31 -0800854 static boost::asio::steady_timer timeout(getIoContext());
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800855 timeout.expires_after(std::chrono::seconds(timeOut));
856 timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
857 csrMatcher = nullptr;
858 if (ec)
859 {
860 // operation_aborted is expected if timer is canceled
861 // before completion.
862 if (ec != boost::asio::error::operation_aborted)
863 {
Ed Tanous62598e32023-07-17 17:06:25 -0700864 BMCWEB_LOG_ERROR("Async_wait failed {}", ec);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800865 }
866 return;
867 }
Ed Tanous62598e32023-07-17 17:06:25 -0700868 BMCWEB_LOG_ERROR("Timed out waiting for Generating CSR");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800869 messages::internalError(asyncResp->res);
870 });
871
872 // create a matcher to wait on CSR object
Ed Tanous62598e32023-07-17 17:06:25 -0700873 BMCWEB_LOG_DEBUG("create matcher with path {}", objectPath);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800874 std::string match("type='signal',"
875 "interface='org.freedesktop.DBus.ObjectManager',"
876 "path='" +
877 objectPath +
878 "',"
879 "member='InterfacesAdded'");
880 csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
881 *crow::connections::systemBus, match,
882 [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400883 timeout.cancel();
884 if (m.is_method_error())
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800885 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400886 BMCWEB_LOG_ERROR("Dbus method error!!!");
887 messages::internalError(asyncResp->res);
888 return;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800889 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400890
891 dbus::utility::DBusInterfacesMap interfacesProperties;
892
893 sdbusplus::message::object_path csrObjectPath;
894 m.read(csrObjectPath, interfacesProperties);
895 BMCWEB_LOG_DEBUG("CSR object added{}", csrObjectPath.str);
896 for (const auto& interface : interfacesProperties)
897 {
898 if (interface.first == "xyz.openbmc_project.Certs.CSR")
899 {
900 getCSR(asyncResp, certURI, service, objectPath,
901 csrObjectPath.str);
902 break;
903 }
904 }
905 });
Ed Tanous177612a2025-02-14 15:16:09 -0800906 dbus::utility::async_method_call(
907 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800908 [asyncResp](const boost::system::error_code& ec, const std::string&) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400909 if (ec)
910 {
911 BMCWEB_LOG_ERROR("DBUS response error: {}", ec.message());
912 messages::internalError(asyncResp->res);
913 return;
914 }
915 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800916 service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
917 "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
918 commonName, *optContactPerson, country, *optEmail, *optGivenName,
919 *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm,
920 *optKeyUsage, organization, organizationalUnit, state, *optSurname,
921 *optUnstructuredName);
922}
923
924inline void requestRoutesCertificateService(App& app)
925{
926 BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
927 .privileges(redfish::privileges::getCertificateService)
928 .methods(boost::beast::http::verb::get)(
929 std::bind_front(handleCertificateServiceGet, std::ref(app)));
930
931 BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
932 .privileges(redfish::privileges::getCertificateLocations)
933 .methods(boost::beast::http::verb::get)(
934 std::bind_front(handleCertificateLocationsGet, std::ref(app)));
935
George Liu0fda0f12021-11-16 10:06:17 +0800936 BMCWEB_ROUTE(
937 app,
938 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
Ed Tanoused398212021-06-09 17:05:54 -0700939 .privileges(redfish::privileges::postCertificateService)
Ed Tanous002d39b2022-05-31 08:59:27 -0700940 .methods(boost::beast::http::verb::post)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800941 std::bind_front(handleReplaceCertificateAction, std::ref(app)));
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600942
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800943 BMCWEB_ROUTE(
944 app,
945 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
946 .privileges(redfish::privileges::postCertificateService)
947 .methods(boost::beast::http::verb::post)(
948 std::bind_front(handleGenerateCSRAction, std::ref(app)));
949} // requestRoutesCertificateService
950
951inline void handleHTTPSCertificateCollectionGet(
952 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -0700953 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
954 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800955{
956 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
957 {
958 return;
959 }
960
Ed Tanous253f11b2024-05-16 09:38:31 -0700961 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
962 {
963 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
964 return;
965 }
966
967 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
968 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
969 BMCWEB_REDFISH_MANAGER_URI_NAME);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800970 asyncResp->res.jsonValue["@odata.type"] =
971 "#CertificateCollection.CertificateCollection";
972 asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
973 asyncResp->res.jsonValue["Description"] =
974 "A Collection of HTTPS certificate instances";
975
976 getCertificateList(asyncResp, certs::httpsObjectPath,
977 "/Members"_json_pointer,
978 "/Members@odata.count"_json_pointer);
979}
980
981inline void handleHTTPSCertificateCollectionPost(
982 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -0700983 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
984 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800985{
986 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
987 {
988 return;
989 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700990
991 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
992 {
993 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
994 return;
995 }
996
Ed Tanous62598e32023-07-17 17:06:25 -0700997 BMCWEB_LOG_DEBUG("HTTPSCertificateCollection::doPost");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800998
999 asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
1000 asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
1001
Ed Tanousb2896142024-01-31 15:25:47 -08001002 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001003
Ed Tanousb2896142024-01-31 15:25:47 -08001004 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001005 {
Ed Tanous62598e32023-07-17 17:06:25 -07001006 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001007 messages::unrecognizedRequestBody(asyncResp->res);
1008 return;
1009 }
1010
1011 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001012 std::make_shared<CertificateFile>(certHttpBody);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001013
Ed Tanous177612a2025-02-14 15:16:09 -08001014 dbus::utility::async_method_call(
1015 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001016 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001017 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001018 if (ec)
1019 {
1020 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1021 messages::internalError(asyncResp->res);
1022 return;
1023 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001024
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001025 sdbusplus::message::object_path path(objectPath);
1026 std::string certId = path.filename();
1027 const boost::urls::url certURL = boost::urls::format(
1028 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
1029 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1030 getCertificateProperties(asyncResp, objectPath,
1031 certs::httpsServiceName, certId, certURL,
1032 "HTTPS Certificate");
1033 BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
1034 certFile->getCertFilePath());
1035 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001036 certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
1037 "Install", certFile->getCertFilePath());
1038}
Ed Tanous002d39b2022-05-31 08:59:27 -07001039
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001040inline void handleHTTPSCertificateGet(
1041 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001042 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1043 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001044{
1045 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1046 {
1047 return;
1048 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001049
Ed Tanous253f11b2024-05-16 09:38:31 -07001050 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1051 {
1052 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1053 return;
1054 }
1055
1056 BMCWEB_LOG_DEBUG("HTTPS Certificate ID={}", certId);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001057 const boost::urls::url certURL = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001058 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
1059 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001060 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001061 sdbusplus::message::object_path(certs::httpsObjectPath) / certId;
1062 getCertificateProperties(asyncResp, objPath, certs::httpsServiceName,
1063 certId, certURL, "HTTPS Certificate");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001064}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001065
1066inline void requestRoutesHTTPSCertificate(App& app)
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001067{
Ed Tanous253f11b2024-05-16 09:38:31 -07001068 BMCWEB_ROUTE(
1069 app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001070 .privileges(redfish::privileges::getCertificateCollection)
1071 .methods(boost::beast::http::verb::get)(std::bind_front(
1072 handleHTTPSCertificateCollectionGet, std::ref(app)));
1073
Ed Tanous253f11b2024-05-16 09:38:31 -07001074 BMCWEB_ROUTE(
1075 app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001076 .privileges(redfish::privileges::postCertificateCollection)
1077 .methods(boost::beast::http::verb::post)(std::bind_front(
1078 handleHTTPSCertificateCollectionPost, std::ref(app)));
1079
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001080 BMCWEB_ROUTE(
1081 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001082 "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001083 .privileges(redfish::privileges::getCertificate)
Jiaqing Zhao1e312592022-06-14 12:58:09 +08001084 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001085 std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001086}
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001087
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001088inline void handleLDAPCertificateCollectionGet(
1089 App& app, const crow::Request& req,
1090 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001091{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001092 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1093 {
1094 return;
1095 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001096
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001097 asyncResp->res.jsonValue["@odata.id"] =
1098 "/redfish/v1/AccountService/LDAP/Certificates";
1099 asyncResp->res.jsonValue["@odata.type"] =
1100 "#CertificateCollection.CertificateCollection";
1101 asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
1102 asyncResp->res.jsonValue["Description"] =
1103 "A Collection of LDAP certificate instances";
Ed Tanous002d39b2022-05-31 08:59:27 -07001104
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001105 getCertificateList(asyncResp, certs::ldapObjectPath,
1106 "/Members"_json_pointer,
1107 "/Members@odata.count"_json_pointer);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001108}
Marri Devender Rao37cce912019-02-20 01:05:22 -06001109
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001110inline void handleLDAPCertificateCollectionPost(
1111 App& app, const crow::Request& req,
1112 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao37cce912019-02-20 01:05:22 -06001113{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001114 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1115 {
1116 return;
1117 }
Ed Tanousb2896142024-01-31 15:25:47 -08001118 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001119
Ed Tanousb2896142024-01-31 15:25:47 -08001120 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001121 {
Ed Tanous62598e32023-07-17 17:06:25 -07001122 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001123 messages::unrecognizedRequestBody(asyncResp->res);
1124 return;
1125 }
1126
1127 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001128 std::make_shared<CertificateFile>(certHttpBody);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001129
Ed Tanous177612a2025-02-14 15:16:09 -08001130 dbus::utility::async_method_call(
1131 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001132 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001133 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001134 if (ec)
1135 {
1136 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1137 messages::internalError(asyncResp->res);
1138 return;
1139 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001140
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001141 sdbusplus::message::object_path path(objectPath);
1142 std::string certId = path.filename();
1143 const boost::urls::url certURL = boost::urls::format(
1144 "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
1145 getCertificateProperties(asyncResp, objectPath,
1146 certs::ldapServiceName, certId, certURL,
1147 "LDAP Certificate");
1148 BMCWEB_LOG_DEBUG("LDAP certificate install file={}",
1149 certFile->getCertFilePath());
1150 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001151 certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
1152 "Install", certFile->getCertFilePath());
1153}
Ed Tanous002d39b2022-05-31 08:59:27 -07001154
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001155inline void handleLDAPCertificateGet(
1156 App& app, const crow::Request& req,
1157 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1158{
1159 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1160 {
1161 return;
1162 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001163
Ed Tanous62598e32023-07-17 17:06:25 -07001164 BMCWEB_LOG_DEBUG("LDAP Certificate ID={}", id);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001165 const boost::urls::url certURL = boost::urls::format(
1166 "/redfish/v1/AccountService/LDAP/Certificates/{}", id);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001167 std::string objPath =
1168 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1169 getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1170 certURL, "LDAP Certificate");
1171}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001172
Jiaqing Zhao99612242022-09-29 15:31:09 +08001173inline void handleLDAPCertificateDelete(
1174 App& app, const crow::Request& req,
1175 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1176{
1177 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1178 {
1179 return;
1180 }
1181
Ed Tanous62598e32023-07-17 17:06:25 -07001182 BMCWEB_LOG_DEBUG("Delete LDAP Certificate ID={}", id);
Jiaqing Zhao99612242022-09-29 15:31:09 +08001183 std::string objPath =
1184 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1185
1186 deleteCertificate(asyncResp, certs::ldapServiceName, objPath);
1187}
1188
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001189inline void requestRoutesLDAPCertificate(App& app)
Marri Devender Rao37cce912019-02-20 01:05:22 -06001190{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001191 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1192 .privileges(redfish::privileges::getCertificateCollection)
1193 .methods(boost::beast::http::verb::get)(
1194 std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app)));
1195
1196 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1197 .privileges(redfish::privileges::postCertificateCollection)
1198 .methods(boost::beast::http::verb::post)(std::bind_front(
1199 handleLDAPCertificateCollectionPost, std::ref(app)));
1200
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001201 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001202 .privileges(redfish::privileges::getCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001203 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001204 std::bind_front(handleLDAPCertificateGet, std::ref(app)));
Jiaqing Zhao99612242022-09-29 15:31:09 +08001205
1206 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1207 .privileges(redfish::privileges::deleteCertificate)
1208 .methods(boost::beast::http::verb::delete_)(
1209 std::bind_front(handleLDAPCertificateDelete, std::ref(app)));
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001210} // requestRoutesLDAPCertificate
1211
1212inline void handleTrustStoreCertificateCollectionGet(
1213 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001214 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1215 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001216{
1217 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1218 {
1219 return;
1220 }
1221
Ed Tanous253f11b2024-05-16 09:38:31 -07001222 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1223 {
1224 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1225 return;
1226 }
1227
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001228 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07001229 boost::urls::format("/redfish/v1/Managers/{}/Truststore/Certificates/",
1230 BMCWEB_REDFISH_MANAGER_URI_NAME);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001231 asyncResp->res.jsonValue["@odata.type"] =
1232 "#CertificateCollection.CertificateCollection";
1233 asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
1234 asyncResp->res.jsonValue["Description"] =
1235 "A Collection of TrustStore certificate instances";
1236
1237 getCertificateList(asyncResp, certs::authorityObjectPath,
1238 "/Members"_json_pointer,
1239 "/Members@odata.count"_json_pointer);
1240}
1241
1242inline void handleTrustStoreCertificateCollectionPost(
1243 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001244 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1245 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001246{
1247 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1248 {
1249 return;
1250 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001251
1252 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1253 {
1254 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1255 return;
1256 }
1257
Ed Tanousb2896142024-01-31 15:25:47 -08001258 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001259
Ed Tanousb2896142024-01-31 15:25:47 -08001260 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001261 {
Ed Tanous62598e32023-07-17 17:06:25 -07001262 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001263 messages::unrecognizedRequestBody(asyncResp->res);
1264 return;
1265 }
1266
1267 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001268 std::make_shared<CertificateFile>(certHttpBody);
Ed Tanous177612a2025-02-14 15:16:09 -08001269 dbus::utility::async_method_call(
1270 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001271 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001272 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001273 if (ec)
1274 {
1275 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1276 messages::internalError(asyncResp->res);
1277 return;
1278 }
Jiaqing Zhao717b9802022-06-06 20:24:04 +08001279
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001280 sdbusplus::message::object_path path(objectPath);
1281 std::string certId = path.filename();
1282 const boost::urls::url certURL = boost::urls::format(
1283 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1284 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1285 getCertificateProperties(asyncResp, objectPath,
1286 certs::authorityServiceName, certId,
1287 certURL, "TrustStore Certificate");
1288 BMCWEB_LOG_DEBUG("TrustStore certificate install file={}",
1289 certFile->getCertFilePath());
1290 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001291 certs::authorityServiceName, certs::authorityObjectPath,
1292 certs::certInstallIntf, "Install", certFile->getCertFilePath());
1293}
1294
1295inline void handleTrustStoreCertificateGet(
1296 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001297 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1298 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001299{
1300 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1301 {
1302 return;
1303 }
1304
Ed Tanous253f11b2024-05-16 09:38:31 -07001305 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1306 {
1307 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1308 return;
1309 }
1310
1311 BMCWEB_LOG_DEBUG("Truststore Certificate ID={}", certId);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001312 const boost::urls::url certURL = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001313 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1314 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001315 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001316 sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001317 getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
Ed Tanous253f11b2024-05-16 09:38:31 -07001318 certId, certURL, "TrustStore Certificate");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001319}
1320
1321inline void handleTrustStoreCertificateDelete(
1322 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001323 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1324 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001325{
1326 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1327 {
1328 return;
1329 }
1330
Ed Tanous253f11b2024-05-16 09:38:31 -07001331 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1332 {
1333 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1334 return;
1335 }
1336
1337 BMCWEB_LOG_DEBUG("Delete TrustStore Certificate ID={}", certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001338 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001339 sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001340
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +08001341 deleteCertificate(asyncResp, certs::authorityServiceName, objPath);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001342}
1343
1344inline void requestRoutesTrustStoreCertificate(App& app)
Marri Devender Raocfcd5f62019-05-17 08:34:37 -05001345{
Ed Tanous253f11b2024-05-16 09:38:31 -07001346 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
Ed Tanoused398212021-06-09 17:05:54 -07001347 .privileges(redfish::privileges::getCertificate)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001348 .methods(boost::beast::http::verb::get)(std::bind_front(
1349 handleTrustStoreCertificateCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001350
Ed Tanous253f11b2024-05-16 09:38:31 -07001351 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
Ed Tanoused398212021-06-09 17:05:54 -07001352 .privileges(redfish::privileges::postCertificateCollection)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001353 .methods(boost::beast::http::verb::post)(std::bind_front(
1354 handleTrustStoreCertificateCollectionPost, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001355
Ed Tanous253f11b2024-05-16 09:38:31 -07001356 BMCWEB_ROUTE(app,
1357 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001358 .privileges(redfish::privileges::getCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001359 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001360 std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001361
Ed Tanous253f11b2024-05-16 09:38:31 -07001362 BMCWEB_ROUTE(app,
1363 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001364 .privileges(redfish::privileges::deleteCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001365 .methods(boost::beast::http::verb::delete_)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001366 std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001367} // requestRoutesTrustStoreCertificate
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001368} // namespace redfish