blob: 645c24272061a1a1d725cb765190a551d8dc9bfe [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{
426 crow::connections::systemBus->async_method_call(
427 [asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800428 id{objectPath.filename()}](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400429 if (ec)
430 {
431 messages::resourceNotFound(asyncResp->res, "Certificate", id);
432 return;
433 }
434 BMCWEB_LOG_INFO("Certificate deleted");
435 asyncResp->res.result(boost::beast::http::status::no_content);
436 },
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +0800437 service, objectPath, certs::objDeleteIntf, "Delete");
438}
439
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800440inline void handleCertificateServiceGet(
441 App& app, const crow::Request& req,
442 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600443{
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800444 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
445 {
446 return;
447 }
448
Ninad Palsule3e72c202023-03-27 17:19:55 -0500449 if (req.session == nullptr)
450 {
451 messages::internalError(asyncResp->res);
452 return;
453 }
454
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800455 asyncResp->res.jsonValue["@odata.type"] =
456 "#CertificateService.v1_0_0.CertificateService";
457 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService";
458 asyncResp->res.jsonValue["Id"] = "CertificateService";
459 asyncResp->res.jsonValue["Name"] = "Certificate Service";
460 asyncResp->res.jsonValue["Description"] =
461 "Actions available to manage certificates";
462 // /redfish/v1/CertificateService/CertificateLocations is something
463 // only ConfigureManager can access then only display when the user
464 // has permissions ConfigureManager
465 Privileges effectiveUserPrivileges =
Ninad Palsule3e72c202023-03-27 17:19:55 -0500466 redfish::getUserPrivileges(*req.session);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800467 if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
468 effectiveUserPrivileges))
469 {
470 asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
471 "/redfish/v1/CertificateService/CertificateLocations";
472 }
473 nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
474 nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"];
475 replace["target"] =
476 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate";
477 nlohmann::json::array_t allowed;
Patrick Williamsad539542023-05-12 10:10:08 -0500478 allowed.emplace_back("PEM");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800479 replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
480 actions["#CertificateService.GenerateCSR"]["target"] =
481 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
482}
483
484inline void handleCertificateLocationsGet(
485 App& app, const crow::Request& req,
486 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
487{
488 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
489 {
490 return;
491 }
492 asyncResp->res.jsonValue["@odata.id"] =
493 "/redfish/v1/CertificateService/CertificateLocations";
494 asyncResp->res.jsonValue["@odata.type"] =
495 "#CertificateLocations.v1_0_0.CertificateLocations";
496 asyncResp->res.jsonValue["Name"] = "Certificate Locations";
497 asyncResp->res.jsonValue["Id"] = "CertificateLocations";
498 asyncResp->res.jsonValue["Description"] =
499 "Defines a resource that an administrator can use in order to "
500 "locate all certificates installed on a given service";
501
502 getCertificateList(asyncResp, certs::baseObjectPath,
503 "/Links/Certificates"_json_pointer,
504 "/Links/Certificates@odata.count"_json_pointer);
505}
506
Chandra Harkude26d3b0f2024-09-23 22:02:35 +0530507inline void handleError(const std::string_view dbusErrorName,
508 const std::string& id, const std::string& certificate,
509 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
510{
511 if (dbusErrorName == "org.freedesktop.DBus.Error.UnknownObject")
512 {
513 messages::resourceNotFound(asyncResp->res, "Certificate", id);
514 }
515 else if (dbusErrorName ==
516 "xyz.openbmc_project.Certs.Error.InvalidCertificate")
517 {
518 messages::propertyValueIncorrect(asyncResp->res, "Certificate",
519 certificate);
520 }
521 else
522 {
523 messages::internalError(asyncResp->res);
524 }
525}
526
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800527inline void handleReplaceCertificateAction(
528 App& app, const crow::Request& req,
529 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
530{
531 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
532 {
533 return;
534 }
535 std::string certificate;
Ed Tanous7a31e332024-03-06 12:17:43 -0800536 std::string certURI;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800537 std::optional<std::string> certificateType = "PEM";
538
Patrick Williams504af5a2025-02-03 14:29:03 -0500539 if (!json_util::readJsonAction( //
540 req, asyncResp->res, //
541 "CertificateString", certificate, //
Myung Baeafc474a2024-10-09 00:53:29 -0700542 "CertificateType", certificateType, //
543 "CertificateUri/@odata.id", certURI //
544 ))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800545 {
Ed Tanous62598e32023-07-17 17:06:25 -0700546 BMCWEB_LOG_ERROR("Required parameters are missing");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800547 return;
548 }
549
550 if (!certificateType)
551 {
552 // should never happen, but it never hurts to be paranoid.
553 return;
554 }
555 if (certificateType != "PEM")
556 {
557 messages::actionParameterNotSupported(asyncResp->res, "CertificateType",
558 "ReplaceCertificate");
559 return;
560 }
561
Ed Tanous62598e32023-07-17 17:06:25 -0700562 BMCWEB_LOG_INFO("Certificate URI to replace: {}", certURI);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800563
Ed Tanous6fd29552023-10-04 09:40:14 -0700564 boost::system::result<boost::urls::url> parsedUrl =
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800565 boost::urls::parse_relative_ref(certURI);
566 if (!parsedUrl)
567 {
568 messages::actionParameterValueFormatError(
569 asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate");
570 return;
571 }
572
573 std::string id;
574 sdbusplus::message::object_path objectPath;
575 std::string name;
576 std::string service;
577 if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers",
578 "bmc", "NetworkProtocol", "HTTPS",
579 "Certificates", std::ref(id)))
580 {
Patrick Williams89492a12023-05-10 07:51:34 -0500581 objectPath = sdbusplus::message::object_path(certs::httpsObjectPath) /
582 id;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800583 name = "HTTPS certificate";
584 service = certs::httpsServiceName;
585 }
586 else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
587 "AccountService", "LDAP",
588 "Certificates", std::ref(id)))
589 {
Patrick Williams89492a12023-05-10 07:51:34 -0500590 objectPath = sdbusplus::message::object_path(certs::ldapObjectPath) /
591 id;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800592 name = "LDAP certificate";
593 service = certs::ldapServiceName;
594 }
595 else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
596 "Managers", "bmc", "Truststore",
597 "Certificates", std::ref(id)))
598 {
599 objectPath =
600 sdbusplus::message::object_path(certs::authorityObjectPath) / id;
601 name = "TrustStore certificate";
602 service = certs::authorityServiceName;
603 }
604 else
605 {
606 messages::actionParameterNotSupported(asyncResp->res, "CertificateUri",
607 "ReplaceCertificate");
608 return;
609 }
610
611 std::shared_ptr<CertificateFile> certFile =
612 std::make_shared<CertificateFile>(certificate);
613 crow::connections::systemBus->async_method_call(
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);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800659 crow::connections::systemBus->async_method_call(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400660 [asyncResp,
661 certURI](const boost::system::error_code& ec, const std::string& csr) {
662 if (ec)
663 {
664 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
665 messages::internalError(asyncResp->res);
666 return;
667 }
668 if (csr.empty())
669 {
670 BMCWEB_LOG_ERROR("CSR read is empty");
671 messages::internalError(asyncResp->res);
672 return;
673 }
674 asyncResp->res.jsonValue["CSRString"] = csr;
675 asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
676 certURI;
677 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800678 service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
679}
680
Patrick Williams504af5a2025-02-03 14:29:03 -0500681inline void handleGenerateCSRAction(
682 App& app, const crow::Request& req,
683 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800684{
685 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
686 {
687 return;
688 }
689 static const int rsaKeyBitLength = 2048;
690
691 // Required parameters
692 std::string city;
693 std::string commonName;
694 std::string country;
695 std::string organization;
696 std::string organizationalUnit;
697 std::string state;
Ed Tanous7a31e332024-03-06 12:17:43 -0800698 std::string certURI;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800699
700 // Optional parameters
701 std::optional<std::vector<std::string>> optAlternativeNames =
702 std::vector<std::string>();
703 std::optional<std::string> optContactPerson = "";
704 std::optional<std::string> optChallengePassword = "";
705 std::optional<std::string> optEmail = "";
706 std::optional<std::string> optGivenName = "";
707 std::optional<std::string> optInitials = "";
708 std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
709 std::optional<std::string> optKeyCurveId = "secp384r1";
710 std::optional<std::string> optKeyPairAlgorithm = "EC";
711 std::optional<std::vector<std::string>> optKeyUsage =
712 std::vector<std::string>();
713 std::optional<std::string> optSurname = "";
714 std::optional<std::string> optUnstructuredName = "";
Patrick Williams504af5a2025-02-03 14:29:03 -0500715 if (!json_util::readJsonAction( //
716 req, asyncResp->res, //
717 "AlternativeNames", optAlternativeNames, //
Myung Baeafc474a2024-10-09 00:53:29 -0700718 "CertificateCollection/@odata.id", certURI, //
Patrick Williams504af5a2025-02-03 14:29:03 -0500719 "ChallengePassword", optChallengePassword, //
720 "City", city, //
721 "CommonName", commonName, //
722 "ContactPerson", optContactPerson, //
723 "Country", country, //
724 "Email", optEmail, //
725 "GivenName", optGivenName, //
726 "Initials", optInitials, //
727 "KeyBitLength", optKeyBitLength, //
728 "KeyCurveId", optKeyCurveId, //
729 "KeyPairAlgorithm", optKeyPairAlgorithm, //
730 "KeyUsage", optKeyUsage, //
731 "Organization", organization, //
732 "OrganizationalUnit", organizationalUnit, //
733 "State", state, //
734 "Surname", optSurname, //
735 "UnstructuredName", optUnstructuredName //
Myung Baeafc474a2024-10-09 00:53:29 -0700736 ))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800737 {
738 return;
739 }
740
741 // bmcweb has no way to store or decode a private key challenge
742 // password, which will likely cause bmcweb to crash on startup
743 // if this is not set on a post so not allowing the user to set
744 // value
745 if (!optChallengePassword->empty())
746 {
747 messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
748 "ChallengePassword");
749 return;
750 }
751
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800752 std::string objectPath;
753 std::string service;
Ed Tanous253f11b2024-05-16 09:38:31 -0700754 if (certURI.starts_with(std::format(
755 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
756 BMCWEB_REDFISH_MANAGER_URI_NAME)))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800757 {
758 objectPath = certs::httpsObjectPath;
759 service = certs::httpsServiceName;
760 }
761 else if (certURI.starts_with(
762 "/redfish/v1/AccountService/LDAP/Certificates"))
763 {
764 objectPath = certs::ldapObjectPath;
765 service = certs::ldapServiceName;
766 }
767 else
768 {
769 messages::actionParameterNotSupported(
770 asyncResp->res, "CertificateCollection", "GenerateCSR");
771 return;
772 }
773
774 // supporting only EC and RSA algorithm
775 if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
776 {
777 messages::actionParameterNotSupported(
778 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
779 return;
780 }
781
782 // supporting only 2048 key bit length for RSA algorithm due to
783 // time consumed in generating private key
784 if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength)
785 {
Ed Tanouse2616cc2022-06-27 12:45:55 -0700786 messages::propertyValueNotInList(asyncResp->res, *optKeyBitLength,
787 "KeyBitLength");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800788 return;
789 }
790
791 // validate KeyUsage supporting only 1 type based on URL
Ed Tanous253f11b2024-05-16 09:38:31 -0700792 if (certURI.starts_with(std::format(
793 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
794 BMCWEB_REDFISH_MANAGER_URI_NAME)))
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800795 {
796 if (optKeyUsage->empty())
797 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500798 optKeyUsage->emplace_back("ServerAuthentication");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800799 }
800 else if (optKeyUsage->size() == 1)
801 {
802 if ((*optKeyUsage)[0] != "ServerAuthentication")
803 {
804 messages::propertyValueNotInList(asyncResp->res,
805 (*optKeyUsage)[0], "KeyUsage");
806 return;
807 }
808 }
809 else
810 {
811 messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
812 "GenerateCSR");
813 return;
814 }
815 }
816 else if (certURI.starts_with(
817 "/redfish/v1/AccountService/LDAP/Certificates"))
818 {
819 if (optKeyUsage->empty())
820 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500821 optKeyUsage->emplace_back("ClientAuthentication");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800822 }
823 else if (optKeyUsage->size() == 1)
824 {
825 if ((*optKeyUsage)[0] != "ClientAuthentication")
826 {
827 messages::propertyValueNotInList(asyncResp->res,
828 (*optKeyUsage)[0], "KeyUsage");
829 return;
830 }
831 }
832 else
833 {
834 messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
835 "GenerateCSR");
836 return;
837 }
838 }
839
840 // Only allow one CSR matcher at a time so setting retry
841 // time-out and timer expiry to 10 seconds for now.
842 static const int timeOut = 10;
843 if (csrMatcher)
844 {
845 messages::serviceTemporarilyUnavailable(asyncResp->res,
846 std::to_string(timeOut));
847 return;
848 }
849
850 // Make this static so it survives outside this method
Ed Tanousd98a2f92025-02-06 17:36:31 -0800851 static boost::asio::steady_timer timeout(getIoContext());
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800852 timeout.expires_after(std::chrono::seconds(timeOut));
853 timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
854 csrMatcher = nullptr;
855 if (ec)
856 {
857 // operation_aborted is expected if timer is canceled
858 // before completion.
859 if (ec != boost::asio::error::operation_aborted)
860 {
Ed Tanous62598e32023-07-17 17:06:25 -0700861 BMCWEB_LOG_ERROR("Async_wait failed {}", ec);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800862 }
863 return;
864 }
Ed Tanous62598e32023-07-17 17:06:25 -0700865 BMCWEB_LOG_ERROR("Timed out waiting for Generating CSR");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800866 messages::internalError(asyncResp->res);
867 });
868
869 // create a matcher to wait on CSR object
Ed Tanous62598e32023-07-17 17:06:25 -0700870 BMCWEB_LOG_DEBUG("create matcher with path {}", objectPath);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800871 std::string match("type='signal',"
872 "interface='org.freedesktop.DBus.ObjectManager',"
873 "path='" +
874 objectPath +
875 "',"
876 "member='InterfacesAdded'");
877 csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
878 *crow::connections::systemBus, match,
879 [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400880 timeout.cancel();
881 if (m.is_method_error())
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800882 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400883 BMCWEB_LOG_ERROR("Dbus method error!!!");
884 messages::internalError(asyncResp->res);
885 return;
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800886 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400887
888 dbus::utility::DBusInterfacesMap interfacesProperties;
889
890 sdbusplus::message::object_path csrObjectPath;
891 m.read(csrObjectPath, interfacesProperties);
892 BMCWEB_LOG_DEBUG("CSR object added{}", csrObjectPath.str);
893 for (const auto& interface : interfacesProperties)
894 {
895 if (interface.first == "xyz.openbmc_project.Certs.CSR")
896 {
897 getCSR(asyncResp, certURI, service, objectPath,
898 csrObjectPath.str);
899 break;
900 }
901 }
902 });
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800903 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800904 [asyncResp](const boost::system::error_code& ec, const std::string&) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400905 if (ec)
906 {
907 BMCWEB_LOG_ERROR("DBUS response error: {}", ec.message());
908 messages::internalError(asyncResp->res);
909 return;
910 }
911 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800912 service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
913 "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
914 commonName, *optContactPerson, country, *optEmail, *optGivenName,
915 *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm,
916 *optKeyUsage, organization, organizationalUnit, state, *optSurname,
917 *optUnstructuredName);
918}
919
920inline void requestRoutesCertificateService(App& app)
921{
922 BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
923 .privileges(redfish::privileges::getCertificateService)
924 .methods(boost::beast::http::verb::get)(
925 std::bind_front(handleCertificateServiceGet, std::ref(app)));
926
927 BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
928 .privileges(redfish::privileges::getCertificateLocations)
929 .methods(boost::beast::http::verb::get)(
930 std::bind_front(handleCertificateLocationsGet, std::ref(app)));
931
George Liu0fda0f12021-11-16 10:06:17 +0800932 BMCWEB_ROUTE(
933 app,
934 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
Ed Tanoused398212021-06-09 17:05:54 -0700935 .privileges(redfish::privileges::postCertificateService)
Ed Tanous002d39b2022-05-31 08:59:27 -0700936 .methods(boost::beast::http::verb::post)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800937 std::bind_front(handleReplaceCertificateAction, std::ref(app)));
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600938
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800939 BMCWEB_ROUTE(
940 app,
941 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
942 .privileges(redfish::privileges::postCertificateService)
943 .methods(boost::beast::http::verb::post)(
944 std::bind_front(handleGenerateCSRAction, std::ref(app)));
945} // requestRoutesCertificateService
946
947inline void handleHTTPSCertificateCollectionGet(
948 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -0700949 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
950 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800951{
952 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
953 {
954 return;
955 }
956
Ed Tanous253f11b2024-05-16 09:38:31 -0700957 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
958 {
959 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
960 return;
961 }
962
963 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
964 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
965 BMCWEB_REDFISH_MANAGER_URI_NAME);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800966 asyncResp->res.jsonValue["@odata.type"] =
967 "#CertificateCollection.CertificateCollection";
968 asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
969 asyncResp->res.jsonValue["Description"] =
970 "A Collection of HTTPS certificate instances";
971
972 getCertificateList(asyncResp, certs::httpsObjectPath,
973 "/Members"_json_pointer,
974 "/Members@odata.count"_json_pointer);
975}
976
977inline void handleHTTPSCertificateCollectionPost(
978 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -0700979 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
980 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800981{
982 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
983 {
984 return;
985 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700986
987 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
988 {
989 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
990 return;
991 }
992
Ed Tanous62598e32023-07-17 17:06:25 -0700993 BMCWEB_LOG_DEBUG("HTTPSCertificateCollection::doPost");
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800994
995 asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
996 asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
997
Ed Tanousb2896142024-01-31 15:25:47 -0800998 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +0800999
Ed Tanousb2896142024-01-31 15:25:47 -08001000 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001001 {
Ed Tanous62598e32023-07-17 17:06:25 -07001002 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001003 messages::unrecognizedRequestBody(asyncResp->res);
1004 return;
1005 }
1006
1007 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001008 std::make_shared<CertificateFile>(certHttpBody);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001009
1010 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001011 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001012 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001013 if (ec)
1014 {
1015 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1016 messages::internalError(asyncResp->res);
1017 return;
1018 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001019
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001020 sdbusplus::message::object_path path(objectPath);
1021 std::string certId = path.filename();
1022 const boost::urls::url certURL = boost::urls::format(
1023 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
1024 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1025 getCertificateProperties(asyncResp, objectPath,
1026 certs::httpsServiceName, certId, certURL,
1027 "HTTPS Certificate");
1028 BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
1029 certFile->getCertFilePath());
1030 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001031 certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
1032 "Install", certFile->getCertFilePath());
1033}
Ed Tanous002d39b2022-05-31 08:59:27 -07001034
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001035inline void handleHTTPSCertificateGet(
1036 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001037 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1038 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001039{
1040 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1041 {
1042 return;
1043 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001044
Ed Tanous253f11b2024-05-16 09:38:31 -07001045 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1046 {
1047 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1048 return;
1049 }
1050
1051 BMCWEB_LOG_DEBUG("HTTPS Certificate ID={}", certId);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001052 const boost::urls::url certURL = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001053 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
1054 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001055 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001056 sdbusplus::message::object_path(certs::httpsObjectPath) / certId;
1057 getCertificateProperties(asyncResp, objPath, certs::httpsServiceName,
1058 certId, certURL, "HTTPS Certificate");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001059}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001060
1061inline void requestRoutesHTTPSCertificate(App& app)
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001062{
Ed Tanous253f11b2024-05-16 09:38:31 -07001063 BMCWEB_ROUTE(
1064 app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001065 .privileges(redfish::privileges::getCertificateCollection)
1066 .methods(boost::beast::http::verb::get)(std::bind_front(
1067 handleHTTPSCertificateCollectionGet, std::ref(app)));
1068
Ed Tanous253f11b2024-05-16 09:38:31 -07001069 BMCWEB_ROUTE(
1070 app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001071 .privileges(redfish::privileges::postCertificateCollection)
1072 .methods(boost::beast::http::verb::post)(std::bind_front(
1073 handleHTTPSCertificateCollectionPost, std::ref(app)));
1074
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001075 BMCWEB_ROUTE(
1076 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001077 "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001078 .privileges(redfish::privileges::getCertificate)
Jiaqing Zhao1e312592022-06-14 12:58:09 +08001079 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001080 std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001081}
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001082
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001083inline void handleLDAPCertificateCollectionGet(
1084 App& app, const crow::Request& req,
1085 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001086{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001087 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1088 {
1089 return;
1090 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001091
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001092 asyncResp->res.jsonValue["@odata.id"] =
1093 "/redfish/v1/AccountService/LDAP/Certificates";
1094 asyncResp->res.jsonValue["@odata.type"] =
1095 "#CertificateCollection.CertificateCollection";
1096 asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
1097 asyncResp->res.jsonValue["Description"] =
1098 "A Collection of LDAP certificate instances";
Ed Tanous002d39b2022-05-31 08:59:27 -07001099
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001100 getCertificateList(asyncResp, certs::ldapObjectPath,
1101 "/Members"_json_pointer,
1102 "/Members@odata.count"_json_pointer);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001103}
Marri Devender Rao37cce912019-02-20 01:05:22 -06001104
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001105inline void handleLDAPCertificateCollectionPost(
1106 App& app, const crow::Request& req,
1107 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Marri Devender Rao37cce912019-02-20 01:05:22 -06001108{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001109 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1110 {
1111 return;
1112 }
Ed Tanousb2896142024-01-31 15:25:47 -08001113 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001114
Ed Tanousb2896142024-01-31 15:25:47 -08001115 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001116 {
Ed Tanous62598e32023-07-17 17:06:25 -07001117 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001118 messages::unrecognizedRequestBody(asyncResp->res);
1119 return;
1120 }
1121
1122 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001123 std::make_shared<CertificateFile>(certHttpBody);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001124
1125 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001126 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001127 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001128 if (ec)
1129 {
1130 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1131 messages::internalError(asyncResp->res);
1132 return;
1133 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001134
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001135 sdbusplus::message::object_path path(objectPath);
1136 std::string certId = path.filename();
1137 const boost::urls::url certURL = boost::urls::format(
1138 "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
1139 getCertificateProperties(asyncResp, objectPath,
1140 certs::ldapServiceName, certId, certURL,
1141 "LDAP Certificate");
1142 BMCWEB_LOG_DEBUG("LDAP certificate install file={}",
1143 certFile->getCertFilePath());
1144 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001145 certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
1146 "Install", certFile->getCertFilePath());
1147}
Ed Tanous002d39b2022-05-31 08:59:27 -07001148
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001149inline void handleLDAPCertificateGet(
1150 App& app, const crow::Request& req,
1151 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1152{
1153 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1154 {
1155 return;
1156 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001157
Ed Tanous62598e32023-07-17 17:06:25 -07001158 BMCWEB_LOG_DEBUG("LDAP Certificate ID={}", id);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001159 const boost::urls::url certURL = boost::urls::format(
1160 "/redfish/v1/AccountService/LDAP/Certificates/{}", id);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001161 std::string objPath =
1162 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1163 getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1164 certURL, "LDAP Certificate");
1165}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001166
Jiaqing Zhao99612242022-09-29 15:31:09 +08001167inline void handleLDAPCertificateDelete(
1168 App& app, const crow::Request& req,
1169 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1170{
1171 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1172 {
1173 return;
1174 }
1175
Ed Tanous62598e32023-07-17 17:06:25 -07001176 BMCWEB_LOG_DEBUG("Delete LDAP Certificate ID={}", id);
Jiaqing Zhao99612242022-09-29 15:31:09 +08001177 std::string objPath =
1178 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1179
1180 deleteCertificate(asyncResp, certs::ldapServiceName, objPath);
1181}
1182
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001183inline void requestRoutesLDAPCertificate(App& app)
Marri Devender Rao37cce912019-02-20 01:05:22 -06001184{
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001185 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1186 .privileges(redfish::privileges::getCertificateCollection)
1187 .methods(boost::beast::http::verb::get)(
1188 std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app)));
1189
1190 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1191 .privileges(redfish::privileges::postCertificateCollection)
1192 .methods(boost::beast::http::verb::post)(std::bind_front(
1193 handleLDAPCertificateCollectionPost, std::ref(app)));
1194
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001195 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001196 .privileges(redfish::privileges::getCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001197 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001198 std::bind_front(handleLDAPCertificateGet, std::ref(app)));
Jiaqing Zhao99612242022-09-29 15:31:09 +08001199
1200 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1201 .privileges(redfish::privileges::deleteCertificate)
1202 .methods(boost::beast::http::verb::delete_)(
1203 std::bind_front(handleLDAPCertificateDelete, std::ref(app)));
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001204} // requestRoutesLDAPCertificate
1205
1206inline void handleTrustStoreCertificateCollectionGet(
1207 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001208 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1209 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001210{
1211 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1212 {
1213 return;
1214 }
1215
Ed Tanous253f11b2024-05-16 09:38:31 -07001216 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1217 {
1218 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1219 return;
1220 }
1221
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001222 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07001223 boost::urls::format("/redfish/v1/Managers/{}/Truststore/Certificates/",
1224 BMCWEB_REDFISH_MANAGER_URI_NAME);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001225 asyncResp->res.jsonValue["@odata.type"] =
1226 "#CertificateCollection.CertificateCollection";
1227 asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
1228 asyncResp->res.jsonValue["Description"] =
1229 "A Collection of TrustStore certificate instances";
1230
1231 getCertificateList(asyncResp, certs::authorityObjectPath,
1232 "/Members"_json_pointer,
1233 "/Members@odata.count"_json_pointer);
1234}
1235
1236inline void handleTrustStoreCertificateCollectionPost(
1237 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001238 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1239 const std::string& managerId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001240{
1241 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1242 {
1243 return;
1244 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001245
1246 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1247 {
1248 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1249 return;
1250 }
1251
Ed Tanousb2896142024-01-31 15:25:47 -08001252 std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001253
Ed Tanousb2896142024-01-31 15:25:47 -08001254 if (certHttpBody.empty())
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001255 {
Ed Tanous62598e32023-07-17 17:06:25 -07001256 BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001257 messages::unrecognizedRequestBody(asyncResp->res);
1258 return;
1259 }
1260
1261 std::shared_ptr<CertificateFile> certFile =
Ed Tanousb2896142024-01-31 15:25:47 -08001262 std::make_shared<CertificateFile>(certHttpBody);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001263 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001264 [asyncResp, certFile](const boost::system::error_code& ec,
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001265 const std::string& objectPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001266 if (ec)
1267 {
1268 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1269 messages::internalError(asyncResp->res);
1270 return;
1271 }
Jiaqing Zhao717b9802022-06-06 20:24:04 +08001272
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001273 sdbusplus::message::object_path path(objectPath);
1274 std::string certId = path.filename();
1275 const boost::urls::url certURL = boost::urls::format(
1276 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1277 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1278 getCertificateProperties(asyncResp, objectPath,
1279 certs::authorityServiceName, certId,
1280 certURL, "TrustStore Certificate");
1281 BMCWEB_LOG_DEBUG("TrustStore certificate install file={}",
1282 certFile->getCertFilePath());
1283 },
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001284 certs::authorityServiceName, certs::authorityObjectPath,
1285 certs::certInstallIntf, "Install", certFile->getCertFilePath());
1286}
1287
1288inline void handleTrustStoreCertificateGet(
1289 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001290 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1291 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001292{
1293 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1294 {
1295 return;
1296 }
1297
Ed Tanous253f11b2024-05-16 09:38:31 -07001298 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1299 {
1300 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1301 return;
1302 }
1303
1304 BMCWEB_LOG_DEBUG("Truststore Certificate ID={}", certId);
Ed Tanousef4c65b2023-04-24 15:28:50 -07001305 const boost::urls::url certURL = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001306 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1307 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001308 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001309 sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001310 getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
Ed Tanous253f11b2024-05-16 09:38:31 -07001311 certId, certURL, "TrustStore Certificate");
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001312}
1313
1314inline void handleTrustStoreCertificateDelete(
1315 App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001316 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1317 const std::string& managerId, const std::string& certId)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001318{
1319 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1320 {
1321 return;
1322 }
1323
Ed Tanous253f11b2024-05-16 09:38:31 -07001324 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1325 {
1326 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1327 return;
1328 }
1329
1330 BMCWEB_LOG_DEBUG("Delete TrustStore Certificate ID={}", certId);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001331 std::string objPath =
Ed Tanous253f11b2024-05-16 09:38:31 -07001332 sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001333
Jiaqing Zhao7a3a8f72022-09-29 15:15:58 +08001334 deleteCertificate(asyncResp, certs::authorityServiceName, objPath);
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001335}
1336
1337inline void requestRoutesTrustStoreCertificate(App& app)
Marri Devender Raocfcd5f62019-05-17 08:34:37 -05001338{
Ed Tanous253f11b2024-05-16 09:38:31 -07001339 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
Ed Tanoused398212021-06-09 17:05:54 -07001340 .privileges(redfish::privileges::getCertificate)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001341 .methods(boost::beast::http::verb::get)(std::bind_front(
1342 handleTrustStoreCertificateCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001343
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::postCertificateCollection)
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001346 .methods(boost::beast::http::verb::post)(std::bind_front(
1347 handleTrustStoreCertificateCollectionPost, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001348
Ed Tanous253f11b2024-05-16 09:38:31 -07001349 BMCWEB_ROUTE(app,
1350 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001351 .privileges(redfish::privileges::getCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001352 .methods(boost::beast::http::verb::get)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001353 std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001354
Ed Tanous253f11b2024-05-16 09:38:31 -07001355 BMCWEB_ROUTE(app,
1356 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001357 .privileges(redfish::privileges::deleteCertificate)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001358 .methods(boost::beast::http::verb::delete_)(
Jiaqing Zhao828252d2022-09-30 13:59:19 +08001359 std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001360} // requestRoutesTrustStoreCertificate
Marri Devender Rao5968cae2019-01-21 10:27:12 -06001361} // namespace redfish