15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
33ccb3adbSEd Tanous #include "app.hpp"
43ccb3adbSEd Tanous #include "async_resp.hpp"
57a1dbc48SGeorge Liu #include "dbus_utility.hpp"
61aa0c2b8SEd Tanous #include "http/parsing.hpp"
73ccb3adbSEd Tanous #include "http_response.hpp"
83ccb3adbSEd Tanous #include "query.hpp"
93ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
109b12d1f9SKrzysztof Grobelny #include "utils/dbus_utils.hpp"
113ccb3adbSEd Tanous #include "utils/json_utils.hpp"
123ccb3adbSEd Tanous #include "utils/time_utils.hpp"
139b12d1f9SKrzysztof Grobelny 
1490d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp>
15ef4c65b7SEd Tanous #include <boost/url/format.hpp>
169b12d1f9SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
173ccb3adbSEd Tanous #include <sdbusplus/bus/match.hpp>
189b12d1f9SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
191214b7e7SGunnar Mills 
207a1dbc48SGeorge Liu #include <array>
213ccb3adbSEd Tanous #include <memory>
227a1dbc48SGeorge Liu #include <string_view>
237a1dbc48SGeorge Liu 
245968caeeSMarri Devender Rao namespace redfish
255968caeeSMarri Devender Rao {
265968caeeSMarri Devender Rao namespace certs
275968caeeSMarri Devender Rao {
2889492a15SPatrick Williams constexpr const char* certInstallIntf = "xyz.openbmc_project.Certs.Install";
2989492a15SPatrick Williams constexpr const char* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
3089492a15SPatrick Williams constexpr const char* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
3189492a15SPatrick Williams constexpr const char* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
3289492a15SPatrick Williams constexpr const char* dbusPropIntf = "org.freedesktop.DBus.Properties";
3389492a15SPatrick Williams constexpr const char* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
3489492a15SPatrick Williams constexpr const char* httpsServiceName =
3537cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
3689492a15SPatrick Williams constexpr const char* ldapServiceName =
3737cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
3889492a15SPatrick Williams constexpr const char* authorityServiceName =
39b2254ccdSMichal Orzel     "xyz.openbmc_project.Certs.Manager.Authority.Truststore";
4089492a15SPatrick Williams constexpr const char* baseObjectPath = "/xyz/openbmc_project/certs";
4189492a15SPatrick Williams constexpr const char* httpsObjectPath =
42c6a8dfb1SJiaqing Zhao     "/xyz/openbmc_project/certs/server/https";
4389492a15SPatrick Williams constexpr const char* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
4489492a15SPatrick Williams constexpr const char* authorityObjectPath =
45b2254ccdSMichal Orzel     "/xyz/openbmc_project/certs/authority/truststore";
465968caeeSMarri Devender Rao } // namespace certs
475968caeeSMarri Devender Rao 
485968caeeSMarri Devender Rao /**
495968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
505968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
515968caeeSMarri Devender Rao  * are installed.
525968caeeSMarri Devender Rao  */
537e860f15SJohn Edward Broadbent 
getCertificateFromReqBody(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const crow::Request & req)548d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
558d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5658eb238fSKowalski, Kamil     const crow::Request& req)
5758eb238fSKowalski, Kamil {
581aa0c2b8SEd Tanous     nlohmann::json reqJson;
591aa0c2b8SEd Tanous     JsonParseResult ret = parseRequestAsJson(req, reqJson);
601aa0c2b8SEd Tanous     if (ret != JsonParseResult::Success)
6158eb238fSKowalski, Kamil     {
6258eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
6333c6b580SEd Tanous         return req.body();
6458eb238fSKowalski, Kamil     }
6558eb238fSKowalski, Kamil 
6658eb238fSKowalski, Kamil     std::string certificate;
6758eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
6858eb238fSKowalski, Kamil 
6915ed6780SWilly Tu     if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
7015ed6780SWilly Tu                                   certificate, "CertificateType",
7115ed6780SWilly Tu                                   certificateType))
7258eb238fSKowalski, Kamil     {
7362598e31SEd Tanous         BMCWEB_LOG_ERROR("Required parameters are missing");
7458eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
75abb93cddSEd Tanous         return {};
7658eb238fSKowalski, Kamil     }
7758eb238fSKowalski, Kamil 
7858eb238fSKowalski, Kamil     if (*certificateType != "PEM")
7958eb238fSKowalski, Kamil     {
8058eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
8158eb238fSKowalski, Kamil                                          "CertificateType");
82abb93cddSEd Tanous         return {};
8358eb238fSKowalski, Kamil     }
8458eb238fSKowalski, Kamil 
8558eb238fSKowalski, Kamil     return certificate;
8658eb238fSKowalski, Kamil }
8758eb238fSKowalski, Kamil 
885968caeeSMarri Devender Rao /**
895968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
905968caeeSMarri Devender Rao  */
915968caeeSMarri Devender Rao class CertificateFile
925968caeeSMarri Devender Rao {
935968caeeSMarri Devender Rao   public:
945968caeeSMarri Devender Rao     CertificateFile() = delete;
955968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
965968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
975968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
985968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
CertificateFile(const std::string & certString)994e23a444SEd Tanous     explicit CertificateFile(const std::string& certString)
1005968caeeSMarri Devender Rao     {
10172d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1025207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1035207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1045207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
105e662eae8SEd Tanous         if (tempDirectory != nullptr)
1065968caeeSMarri Devender Rao         {
1075968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1085968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
109bd79bce8SPatrick Williams             std::ofstream out(certificateFile,
110bd79bce8SPatrick Williams                               std::ofstream::out | std::ofstream::binary |
1115968caeeSMarri Devender Rao                                   std::ofstream::trunc);
1125968caeeSMarri Devender Rao             out << certString;
1135968caeeSMarri Devender Rao             out.close();
11462598e31SEd Tanous             BMCWEB_LOG_DEBUG("Creating certificate file{}",
11562598e31SEd Tanous                              certificateFile.string());
1165968caeeSMarri Devender Rao         }
1175968caeeSMarri Devender Rao     }
~CertificateFile()1185968caeeSMarri Devender Rao     ~CertificateFile()
1195968caeeSMarri Devender Rao     {
1205968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1215968caeeSMarri Devender Rao         {
12262598e31SEd Tanous             BMCWEB_LOG_DEBUG("Removing certificate file{}",
12362598e31SEd Tanous                              certificateFile.string());
12423a21a1cSEd Tanous             std::error_code ec;
12523a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
12623a21a1cSEd Tanous             if (ec)
1275968caeeSMarri Devender Rao             {
12862598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to remove temp directory{}",
12962598e31SEd Tanous                                  certDirectory.string());
1305968caeeSMarri Devender Rao             }
1315968caeeSMarri Devender Rao         }
1325968caeeSMarri Devender Rao     }
getCertFilePath()1335968caeeSMarri Devender Rao     std::string getCertFilePath()
1345968caeeSMarri Devender Rao     {
1355968caeeSMarri Devender Rao         return certificateFile;
1365968caeeSMarri Devender Rao     }
1375968caeeSMarri Devender Rao 
1385968caeeSMarri Devender Rao   private:
1395968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1405968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1415968caeeSMarri Devender Rao };
1425968caeeSMarri Devender Rao 
1435968caeeSMarri Devender Rao /**
1444e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
1455968caeeSMarri Devender Rao  *
1465968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
1475968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
1485968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
1495968caeeSMarri Devender Rao  * @return None
1505968caeeSMarri Devender Rao  */
updateCertIssuerOrSubject(nlohmann::json & out,std::string_view value)1514ff0f1f4SEd Tanous inline void updateCertIssuerOrSubject(nlohmann::json& out,
15226ccae32SEd Tanous                                       std::string_view value)
1535968caeeSMarri Devender Rao {
1545968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
1555968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
1565968caeeSMarri Devender Rao     while (i != value.end())
1575968caeeSMarri Devender Rao     {
1585968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
1595968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
1605968caeeSMarri Devender Rao         {
1616da47babSPatrick Williams             std::advance(i, 1);
1625968caeeSMarri Devender Rao         }
1635968caeeSMarri Devender Rao         if (i == value.end())
1645968caeeSMarri Devender Rao         {
1655968caeeSMarri Devender Rao             break;
1665968caeeSMarri Devender Rao         }
16726ccae32SEd Tanous         std::string_view key(tokenBegin, static_cast<size_t>(i - tokenBegin));
1686da47babSPatrick Williams         std::advance(i, 1);
1695968caeeSMarri Devender Rao         tokenBegin = i;
1705968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
1715968caeeSMarri Devender Rao         {
1726da47babSPatrick Williams             std::advance(i, 1);
1735968caeeSMarri Devender Rao         }
17426ccae32SEd Tanous         std::string_view val(tokenBegin, static_cast<size_t>(i - tokenBegin));
1755968caeeSMarri Devender Rao         if (key == "L")
1765968caeeSMarri Devender Rao         {
1775968caeeSMarri Devender Rao             out["City"] = val;
1785968caeeSMarri Devender Rao         }
1795968caeeSMarri Devender Rao         else if (key == "CN")
1805968caeeSMarri Devender Rao         {
1815968caeeSMarri Devender Rao             out["CommonName"] = val;
1825968caeeSMarri Devender Rao         }
1835968caeeSMarri Devender Rao         else if (key == "C")
1845968caeeSMarri Devender Rao         {
1855968caeeSMarri Devender Rao             out["Country"] = val;
1865968caeeSMarri Devender Rao         }
1875968caeeSMarri Devender Rao         else if (key == "O")
1885968caeeSMarri Devender Rao         {
1895968caeeSMarri Devender Rao             out["Organization"] = val;
1905968caeeSMarri Devender Rao         }
1915968caeeSMarri Devender Rao         else if (key == "OU")
1925968caeeSMarri Devender Rao         {
1935968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
1945968caeeSMarri Devender Rao         }
1955968caeeSMarri Devender Rao         else if (key == "ST")
1965968caeeSMarri Devender Rao         {
1975968caeeSMarri Devender Rao             out["State"] = val;
1985968caeeSMarri Devender Rao         }
1995968caeeSMarri Devender Rao         // skip comma character
2005968caeeSMarri Devender Rao         if (i != value.end())
2015968caeeSMarri Devender Rao         {
2026da47babSPatrick Williams             std::advance(i, 1);
2035968caeeSMarri Devender Rao         }
2045968caeeSMarri Devender Rao     }
2055968caeeSMarri Devender Rao }
2065968caeeSMarri Devender Rao 
2075968caeeSMarri Devender Rao /**
208d3f92ce7SJiaqing Zhao  * @brief Retrieve the installed certificate list
209d3f92ce7SJiaqing Zhao  *
210d3f92ce7SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
211d3f92ce7SJiaqing Zhao  * @param[in] basePath DBus object path to search
212d3f92ce7SJiaqing Zhao  * @param[in] listPtr Json pointer to the list in asyncResp
213d3f92ce7SJiaqing Zhao  * @param[in] countPtr Json pointer to the count in asyncResp
214d3f92ce7SJiaqing Zhao  * @return None
215d3f92ce7SJiaqing Zhao  */
getCertificateList(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & basePath,const nlohmann::json::json_pointer & listPtr,const nlohmann::json::json_pointer & countPtr)2164ff0f1f4SEd Tanous inline void getCertificateList(
217bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
218bd79bce8SPatrick Williams     const std::string& basePath, const nlohmann::json::json_pointer& listPtr,
219d3f92ce7SJiaqing Zhao     const nlohmann::json::json_pointer& countPtr)
220d3f92ce7SJiaqing Zhao {
2217a1dbc48SGeorge Liu     constexpr std::array<std::string_view, 1> interfaces = {
2227a1dbc48SGeorge Liu         certs::certPropIntf};
2237a1dbc48SGeorge Liu     dbus::utility::getSubTreePaths(
2247a1dbc48SGeorge Liu         basePath, 0, interfaces,
225d3f92ce7SJiaqing Zhao         [asyncResp, listPtr, countPtr](
2267a1dbc48SGeorge Liu             const boost::system::error_code& ec,
227d3f92ce7SJiaqing Zhao             const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
228d3f92ce7SJiaqing Zhao             if (ec)
229d3f92ce7SJiaqing Zhao             {
23062598e31SEd Tanous                 BMCWEB_LOG_ERROR("Certificate collection query failed: {}", ec);
231d3f92ce7SJiaqing Zhao                 messages::internalError(asyncResp->res);
232d3f92ce7SJiaqing Zhao                 return;
233d3f92ce7SJiaqing Zhao             }
234d3f92ce7SJiaqing Zhao 
235d3f92ce7SJiaqing Zhao             nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
236d3f92ce7SJiaqing Zhao             links = nlohmann::json::array();
237d3f92ce7SJiaqing Zhao             for (const auto& certPath : certPaths)
238d3f92ce7SJiaqing Zhao             {
239d3f92ce7SJiaqing Zhao                 sdbusplus::message::object_path objPath(certPath);
240d3f92ce7SJiaqing Zhao                 std::string certId = objPath.filename();
241d3f92ce7SJiaqing Zhao                 if (certId.empty())
242d3f92ce7SJiaqing Zhao                 {
243bd79bce8SPatrick Williams                     BMCWEB_LOG_ERROR("Invalid certificate objPath {}",
244bd79bce8SPatrick Williams                                      certPath);
245d3f92ce7SJiaqing Zhao                     continue;
246d3f92ce7SJiaqing Zhao                 }
247d3f92ce7SJiaqing Zhao 
248d3f92ce7SJiaqing Zhao                 boost::urls::url certURL;
249d3f92ce7SJiaqing Zhao                 if (objPath.parent_path() == certs::httpsObjectPath)
250d3f92ce7SJiaqing Zhao                 {
251ef4c65b7SEd Tanous                     certURL = boost::urls::format(
252253f11b8SEd Tanous                         "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
253253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
254d3f92ce7SJiaqing Zhao                 }
255d3f92ce7SJiaqing Zhao                 else if (objPath.parent_path() == certs::ldapObjectPath)
256d3f92ce7SJiaqing Zhao                 {
257ef4c65b7SEd Tanous                     certURL = boost::urls::format(
258bd79bce8SPatrick Williams                         "/redfish/v1/AccountService/LDAP/Certificates/{}",
259bd79bce8SPatrick Williams                         certId);
260d3f92ce7SJiaqing Zhao                 }
261d3f92ce7SJiaqing Zhao                 else if (objPath.parent_path() == certs::authorityObjectPath)
262d3f92ce7SJiaqing Zhao                 {
263ef4c65b7SEd Tanous                     certURL = boost::urls::format(
264253f11b8SEd Tanous                         "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
265253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
266d3f92ce7SJiaqing Zhao                 }
267d3f92ce7SJiaqing Zhao                 else
268d3f92ce7SJiaqing Zhao                 {
269d3f92ce7SJiaqing Zhao                     continue;
270d3f92ce7SJiaqing Zhao                 }
271d3f92ce7SJiaqing Zhao 
272d3f92ce7SJiaqing Zhao                 nlohmann::json::object_t link;
273d3f92ce7SJiaqing Zhao                 link["@odata.id"] = certURL;
274d3f92ce7SJiaqing Zhao                 links.emplace_back(std::move(link));
275d3f92ce7SJiaqing Zhao             }
276d3f92ce7SJiaqing Zhao 
277d3f92ce7SJiaqing Zhao             asyncResp->res.jsonValue[countPtr] = links.size();
2787a1dbc48SGeorge Liu         });
279d3f92ce7SJiaqing Zhao }
280d3f92ce7SJiaqing Zhao 
281d3f92ce7SJiaqing Zhao /**
2825968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
2835968caeeSMarri Devender Rao  * message
2845968caeeSMarri Devender Rao  *
2855968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
2865968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
2875968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
2885968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
2895968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
2905968caeeSMarri Devender Rao  * @return None
2915968caeeSMarri Devender Rao  */
getCertificateProperties(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & objectPath,const std::string & service,const std::string & certId,const boost::urls::url & certURL,const std::string & name)2924ff0f1f4SEd Tanous inline void getCertificateProperties(
2938d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
294e19e97e2SJiaqing Zhao     const std::string& objectPath, const std::string& service,
2951e312598SJiaqing Zhao     const std::string& certId, const boost::urls::url& certURL,
296e19e97e2SJiaqing Zhao     const std::string& name)
2975968caeeSMarri Devender Rao {
29862598e31SEd Tanous     BMCWEB_LOG_DEBUG("getCertificateProperties Path={} certId={} certURl={}",
29962598e31SEd Tanous                      objectPath, certId, certURL);
3009b12d1f9SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
3019b12d1f9SKrzysztof Grobelny         *crow::connections::systemBus, service, objectPath, certs::certPropIntf,
302b9d36b47SEd Tanous         [asyncResp, certURL, certId,
3035e7e2dc5SEd Tanous          name](const boost::system::error_code& ec,
304b9d36b47SEd Tanous                const dbus::utility::DBusPropertiesMap& properties) {
3055968caeeSMarri Devender Rao             if (ec)
3065968caeeSMarri Devender Rao             {
30762598e31SEd Tanous                 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
308bd79bce8SPatrick Williams                 messages::resourceNotFound(asyncResp->res, "Certificate",
309bd79bce8SPatrick Williams                                            certId);
3105968caeeSMarri Devender Rao                 return;
3115968caeeSMarri Devender Rao             }
3129b12d1f9SKrzysztof Grobelny 
3139b12d1f9SKrzysztof Grobelny             const std::string* certificateString = nullptr;
3149b12d1f9SKrzysztof Grobelny             const std::vector<std::string>* keyUsage = nullptr;
3159b12d1f9SKrzysztof Grobelny             const std::string* issuer = nullptr;
3169b12d1f9SKrzysztof Grobelny             const std::string* subject = nullptr;
3179b12d1f9SKrzysztof Grobelny             const uint64_t* validNotAfter = nullptr;
3189b12d1f9SKrzysztof Grobelny             const uint64_t* validNotBefore = nullptr;
3199b12d1f9SKrzysztof Grobelny 
3209b12d1f9SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
321bd79bce8SPatrick Williams                 dbus_utils::UnpackErrorPrinter(), properties,
322bd79bce8SPatrick Williams                 "CertificateString", certificateString, "KeyUsage", keyUsage,
323bd79bce8SPatrick Williams                 "Issuer", issuer, "Subject", subject, "ValidNotAfter",
324bd79bce8SPatrick Williams                 validNotAfter, "ValidNotBefore", validNotBefore);
3259b12d1f9SKrzysztof Grobelny 
3269b12d1f9SKrzysztof Grobelny             if (!success)
3279b12d1f9SKrzysztof Grobelny             {
3289b12d1f9SKrzysztof Grobelny                 messages::internalError(asyncResp->res);
3299b12d1f9SKrzysztof Grobelny                 return;
3309b12d1f9SKrzysztof Grobelny             }
3319b12d1f9SKrzysztof Grobelny 
3321476687dSEd Tanous             asyncResp->res.jsonValue["@odata.id"] = certURL;
3331476687dSEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
3341476687dSEd Tanous                 "#Certificate.v1_0_0.Certificate";
335e19e97e2SJiaqing Zhao             asyncResp->res.jsonValue["Id"] = certId;
3361476687dSEd Tanous             asyncResp->res.jsonValue["Name"] = name;
3371476687dSEd Tanous             asyncResp->res.jsonValue["Description"] = name;
3385968caeeSMarri Devender Rao             asyncResp->res.jsonValue["CertificateString"] = "";
3399b12d1f9SKrzysztof Grobelny             asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array();
3409b12d1f9SKrzysztof Grobelny 
3419b12d1f9SKrzysztof Grobelny             if (certificateString != nullptr)
3425968caeeSMarri Devender Rao             {
343bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["CertificateString"] =
344bd79bce8SPatrick Williams                     *certificateString;
3455968caeeSMarri Devender Rao             }
3469b12d1f9SKrzysztof Grobelny 
3479b12d1f9SKrzysztof Grobelny             if (keyUsage != nullptr)
3485968caeeSMarri Devender Rao             {
3499b12d1f9SKrzysztof Grobelny                 asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
3505968caeeSMarri Devender Rao             }
3519b12d1f9SKrzysztof Grobelny 
3529b12d1f9SKrzysztof Grobelny             if (issuer != nullptr)
3535968caeeSMarri Devender Rao             {
3549b12d1f9SKrzysztof Grobelny                 updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
3559b12d1f9SKrzysztof Grobelny                                           *issuer);
3565968caeeSMarri Devender Rao             }
3579b12d1f9SKrzysztof Grobelny 
3589b12d1f9SKrzysztof Grobelny             if (subject != nullptr)
3595968caeeSMarri Devender Rao             {
3609b12d1f9SKrzysztof Grobelny                 updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
3619b12d1f9SKrzysztof Grobelny                                           *subject);
3625968caeeSMarri Devender Rao             }
3639b12d1f9SKrzysztof Grobelny 
3649b12d1f9SKrzysztof Grobelny             if (validNotAfter != nullptr)
3655968caeeSMarri Devender Rao             {
3665968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["ValidNotAfter"] =
3679b12d1f9SKrzysztof Grobelny                     redfish::time_utils::getDateTimeUint(*validNotAfter);
3685968caeeSMarri Devender Rao             }
3699b12d1f9SKrzysztof Grobelny 
3709b12d1f9SKrzysztof Grobelny             if (validNotBefore != nullptr)
3715968caeeSMarri Devender Rao             {
3725968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["ValidNotBefore"] =
3739b12d1f9SKrzysztof Grobelny                     redfish::time_utils::getDateTimeUint(*validNotBefore);
3745968caeeSMarri Devender Rao             }
3759b12d1f9SKrzysztof Grobelny 
3761e312598SJiaqing Zhao             asyncResp->res.addHeader(
377d9f6c621SEd Tanous                 boost::beast::http::field::location,
378d9f6c621SEd Tanous                 std::string_view(certURL.data(), certURL.size()));
3799b12d1f9SKrzysztof Grobelny         });
3805968caeeSMarri Devender Rao }
3815968caeeSMarri Devender Rao 
3824ff0f1f4SEd Tanous inline void
deleteCertificate(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & service,const sdbusplus::message::object_path & objectPath)3837a3a8f7aSJiaqing Zhao     deleteCertificate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3847a3a8f7aSJiaqing Zhao                       const std::string& service,
3857a3a8f7aSJiaqing Zhao                       const sdbusplus::message::object_path& objectPath)
3867a3a8f7aSJiaqing Zhao {
3877a3a8f7aSJiaqing Zhao     crow::connections::systemBus->async_method_call(
3887a3a8f7aSJiaqing Zhao         [asyncResp,
3895e7e2dc5SEd Tanous          id{objectPath.filename()}](const boost::system::error_code& ec) {
3907a3a8f7aSJiaqing Zhao             if (ec)
3917a3a8f7aSJiaqing Zhao             {
3927a3a8f7aSJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "Certificate", id);
3937a3a8f7aSJiaqing Zhao                 return;
3947a3a8f7aSJiaqing Zhao             }
39562598e31SEd Tanous             BMCWEB_LOG_INFO("Certificate deleted");
3967a3a8f7aSJiaqing Zhao             asyncResp->res.result(boost::beast::http::status::no_content);
3977a3a8f7aSJiaqing Zhao         },
3987a3a8f7aSJiaqing Zhao         service, objectPath, certs::objDeleteIntf, "Delete");
3997a3a8f7aSJiaqing Zhao }
4007a3a8f7aSJiaqing Zhao 
handleCertificateServiceGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)401828252d5SJiaqing Zhao inline void handleCertificateServiceGet(
402828252d5SJiaqing Zhao     App& app, const crow::Request& req,
403828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
4045968caeeSMarri Devender Rao {
405828252d5SJiaqing Zhao     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
406828252d5SJiaqing Zhao     {
407828252d5SJiaqing Zhao         return;
408828252d5SJiaqing Zhao     }
409828252d5SJiaqing Zhao 
4103e72c202SNinad Palsule     if (req.session == nullptr)
4113e72c202SNinad Palsule     {
4123e72c202SNinad Palsule         messages::internalError(asyncResp->res);
4133e72c202SNinad Palsule         return;
4143e72c202SNinad Palsule     }
4153e72c202SNinad Palsule 
416828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.type"] =
417828252d5SJiaqing Zhao         "#CertificateService.v1_0_0.CertificateService";
418828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService";
419828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Id"] = "CertificateService";
420828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Name"] = "Certificate Service";
421828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Description"] =
422828252d5SJiaqing Zhao         "Actions available to manage certificates";
423828252d5SJiaqing Zhao     // /redfish/v1/CertificateService/CertificateLocations is something
424828252d5SJiaqing Zhao     // only ConfigureManager can access then only display when the user
425828252d5SJiaqing Zhao     // has permissions ConfigureManager
426828252d5SJiaqing Zhao     Privileges effectiveUserPrivileges =
4273e72c202SNinad Palsule         redfish::getUserPrivileges(*req.session);
428828252d5SJiaqing Zhao     if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
429828252d5SJiaqing Zhao                                          effectiveUserPrivileges))
430828252d5SJiaqing Zhao     {
431828252d5SJiaqing Zhao         asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
432828252d5SJiaqing Zhao             "/redfish/v1/CertificateService/CertificateLocations";
433828252d5SJiaqing Zhao     }
434828252d5SJiaqing Zhao     nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
435828252d5SJiaqing Zhao     nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"];
436828252d5SJiaqing Zhao     replace["target"] =
437828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate";
438828252d5SJiaqing Zhao     nlohmann::json::array_t allowed;
439ad539545SPatrick Williams     allowed.emplace_back("PEM");
440828252d5SJiaqing Zhao     replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
441828252d5SJiaqing Zhao     actions["#CertificateService.GenerateCSR"]["target"] =
442828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
443828252d5SJiaqing Zhao }
444828252d5SJiaqing Zhao 
handleCertificateLocationsGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)445828252d5SJiaqing Zhao inline void handleCertificateLocationsGet(
446828252d5SJiaqing Zhao     App& app, const crow::Request& req,
447828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
448828252d5SJiaqing Zhao {
449828252d5SJiaqing Zhao     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
450828252d5SJiaqing Zhao     {
451828252d5SJiaqing Zhao         return;
452828252d5SJiaqing Zhao     }
453828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.id"] =
454828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/CertificateLocations";
455828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.type"] =
456828252d5SJiaqing Zhao         "#CertificateLocations.v1_0_0.CertificateLocations";
457828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Name"] = "Certificate Locations";
458828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Id"] = "CertificateLocations";
459828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Description"] =
460828252d5SJiaqing Zhao         "Defines a resource that an administrator can use in order to "
461828252d5SJiaqing Zhao         "locate all certificates installed on a given service";
462828252d5SJiaqing Zhao 
463828252d5SJiaqing Zhao     getCertificateList(asyncResp, certs::baseObjectPath,
464828252d5SJiaqing Zhao                        "/Links/Certificates"_json_pointer,
465828252d5SJiaqing Zhao                        "/Links/Certificates@odata.count"_json_pointer);
466828252d5SJiaqing Zhao }
467828252d5SJiaqing Zhao 
handleError(const std::string_view dbusErrorName,const std::string & id,const std::string & certificate,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)46826d3b0fbSChandra Harkude inline void handleError(const std::string_view dbusErrorName,
46926d3b0fbSChandra Harkude                         const std::string& id, const std::string& certificate,
47026d3b0fbSChandra Harkude                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
47126d3b0fbSChandra Harkude {
47226d3b0fbSChandra Harkude     if (dbusErrorName == "org.freedesktop.DBus.Error.UnknownObject")
47326d3b0fbSChandra Harkude     {
47426d3b0fbSChandra Harkude         messages::resourceNotFound(asyncResp->res, "Certificate", id);
47526d3b0fbSChandra Harkude     }
47626d3b0fbSChandra Harkude     else if (dbusErrorName ==
47726d3b0fbSChandra Harkude              "xyz.openbmc_project.Certs.Error.InvalidCertificate")
47826d3b0fbSChandra Harkude     {
47926d3b0fbSChandra Harkude         messages::propertyValueIncorrect(asyncResp->res, "Certificate",
48026d3b0fbSChandra Harkude                                          certificate);
48126d3b0fbSChandra Harkude     }
48226d3b0fbSChandra Harkude     else
48326d3b0fbSChandra Harkude     {
48426d3b0fbSChandra Harkude         messages::internalError(asyncResp->res);
48526d3b0fbSChandra Harkude     }
48626d3b0fbSChandra Harkude }
48726d3b0fbSChandra Harkude 
handleReplaceCertificateAction(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)488828252d5SJiaqing Zhao inline void handleReplaceCertificateAction(
489828252d5SJiaqing Zhao     App& app, const crow::Request& req,
490828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
491828252d5SJiaqing Zhao {
4923ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
49345ca1b86SEd Tanous     {
49445ca1b86SEd Tanous         return;
49545ca1b86SEd Tanous     }
4965968caeeSMarri Devender Rao     std::string certificate;
4977a31e336SEd Tanous     std::string certURI;
4985968caeeSMarri Devender Rao     std::optional<std::string> certificateType = "PEM";
4998d1b46d7Szhanghch05 
500002d39b4SEd Tanous     if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
5017a31e336SEd Tanous                                    certificate, "CertificateUri/@odata.id",
5027a31e336SEd Tanous                                    certURI, "CertificateType", certificateType))
5035968caeeSMarri Devender Rao     {
50462598e31SEd Tanous         BMCWEB_LOG_ERROR("Required parameters are missing");
5055968caeeSMarri Devender Rao         return;
5065968caeeSMarri Devender Rao     }
5075968caeeSMarri Devender Rao 
5085968caeeSMarri Devender Rao     if (!certificateType)
5095968caeeSMarri Devender Rao     {
5105968caeeSMarri Devender Rao         // should never happen, but it never hurts to be paranoid.
5115968caeeSMarri Devender Rao         return;
5125968caeeSMarri Devender Rao     }
5135968caeeSMarri Devender Rao     if (certificateType != "PEM")
5145968caeeSMarri Devender Rao     {
515828252d5SJiaqing Zhao         messages::actionParameterNotSupported(asyncResp->res, "CertificateType",
516828252d5SJiaqing Zhao                                               "ReplaceCertificate");
5175968caeeSMarri Devender Rao         return;
5185968caeeSMarri Devender Rao     }
5195968caeeSMarri Devender Rao 
52062598e31SEd Tanous     BMCWEB_LOG_INFO("Certificate URI to replace: {}", certURI);
5215968caeeSMarri Devender Rao 
5226fd29553SEd Tanous     boost::system::result<boost::urls::url> parsedUrl =
52375b63a2cSJiaqing Zhao         boost::urls::parse_relative_ref(certURI);
52475b63a2cSJiaqing Zhao     if (!parsedUrl)
5255968caeeSMarri Devender Rao     {
526828252d5SJiaqing Zhao         messages::actionParameterValueFormatError(
527828252d5SJiaqing Zhao             asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate");
5285968caeeSMarri Devender Rao         return;
5295968caeeSMarri Devender Rao     }
53075b63a2cSJiaqing Zhao 
53175b63a2cSJiaqing Zhao     std::string id;
53275b63a2cSJiaqing Zhao     sdbusplus::message::object_path objectPath;
5335968caeeSMarri Devender Rao     std::string name;
53437cce918SMarri Devender Rao     std::string service;
535828252d5SJiaqing Zhao     if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers",
536828252d5SJiaqing Zhao                                        "bmc", "NetworkProtocol", "HTTPS",
537828252d5SJiaqing Zhao                                        "Certificates", std::ref(id)))
5385968caeeSMarri Devender Rao     {
53989492a15SPatrick Williams         objectPath = sdbusplus::message::object_path(certs::httpsObjectPath) /
54089492a15SPatrick Williams                      id;
5415968caeeSMarri Devender Rao         name = "HTTPS certificate";
54237cce918SMarri Devender Rao         service = certs::httpsServiceName;
54337cce918SMarri Devender Rao     }
54475b63a2cSJiaqing Zhao     else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
54575b63a2cSJiaqing Zhao                                             "AccountService", "LDAP",
54675b63a2cSJiaqing Zhao                                             "Certificates", std::ref(id)))
54737cce918SMarri Devender Rao     {
54889492a15SPatrick Williams         objectPath = sdbusplus::message::object_path(certs::ldapObjectPath) /
54989492a15SPatrick Williams                      id;
55037cce918SMarri Devender Rao         name = "LDAP certificate";
55137cce918SMarri Devender Rao         service = certs::ldapServiceName;
5525968caeeSMarri Devender Rao     }
55375b63a2cSJiaqing Zhao     else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
55475b63a2cSJiaqing Zhao                                             "Managers", "bmc", "Truststore",
55575b63a2cSJiaqing Zhao                                             "Certificates", std::ref(id)))
556cfcd5f6bSMarri Devender Rao     {
55775b63a2cSJiaqing Zhao         objectPath =
558828252d5SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
559cfcd5f6bSMarri Devender Rao         name = "TrustStore certificate";
560cfcd5f6bSMarri Devender Rao         service = certs::authorityServiceName;
561cfcd5f6bSMarri Devender Rao     }
5625968caeeSMarri Devender Rao     else
5635968caeeSMarri Devender Rao     {
564828252d5SJiaqing Zhao         messages::actionParameterNotSupported(asyncResp->res, "CertificateUri",
565828252d5SJiaqing Zhao                                               "ReplaceCertificate");
5665968caeeSMarri Devender Rao         return;
5675968caeeSMarri Devender Rao     }
5685968caeeSMarri Devender Rao 
5695968caeeSMarri Devender Rao     std::shared_ptr<CertificateFile> certFile =
5705968caeeSMarri Devender Rao         std::make_shared<CertificateFile>(certificate);
5715968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
57226d3b0fbSChandra Harkude         [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id, name,
57326d3b0fbSChandra Harkude          certificate](const boost::system::error_code& ec,
574*d3e0859cSPatrick Williams                       sdbusplus::message_t& m) {
5755968caeeSMarri Devender Rao             if (ec)
5765968caeeSMarri Devender Rao             {
57762598e31SEd Tanous                 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
57826d3b0fbSChandra Harkude                 const sd_bus_error* dbusError = m.get_error();
57926d3b0fbSChandra Harkude                 if ((dbusError != nullptr) && (dbusError->name != nullptr))
58090d2d1e8SJiaqing Zhao                 {
58126d3b0fbSChandra Harkude                     handleError(dbusError->name, id, certificate, asyncResp);
5825968caeeSMarri Devender Rao                 }
58326d3b0fbSChandra Harkude                 else
58426d3b0fbSChandra Harkude                 {
58590d2d1e8SJiaqing Zhao                     messages::internalError(asyncResp->res);
58626d3b0fbSChandra Harkude                 }
58790d2d1e8SJiaqing Zhao                 return;
58890d2d1e8SJiaqing Zhao             }
589bd79bce8SPatrick Williams             getCertificateProperties(asyncResp, objectPath, service, id, url,
590bd79bce8SPatrick Williams                                      name);
59162598e31SEd Tanous             BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
59262598e31SEd Tanous                              certFile->getCertFilePath());
5935968caeeSMarri Devender Rao         },
5945968caeeSMarri Devender Rao         service, objectPath, certs::certReplaceIntf, "Replace",
5955968caeeSMarri Devender Rao         certFile->getCertFilePath());
596828252d5SJiaqing Zhao }
5975968caeeSMarri Devender Rao 
598cf9e417dSEd Tanous // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
599828252d5SJiaqing Zhao static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
6005968caeeSMarri Devender Rao /**
601828252d5SJiaqing Zhao  * @brief Read data from CSR D-bus object and set to response
602828252d5SJiaqing Zhao  *
603828252d5SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
6048ece0e45SEd Tanous  * @param[in] certURI Link to certificate collection URI
605828252d5SJiaqing Zhao  * @param[in] service D-Bus service name
606828252d5SJiaqing Zhao  * @param[in] certObjPath certificate D-Bus object path
607828252d5SJiaqing Zhao  * @param[in] csrObjPath CSR D-Bus object path
608828252d5SJiaqing Zhao  * @return None
6095968caeeSMarri Devender Rao  */
getCSR(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & certURI,const std::string & service,const std::string & certObjPath,const std::string & csrObjPath)6104ff0f1f4SEd Tanous inline void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
611828252d5SJiaqing Zhao                    const std::string& certURI, const std::string& service,
612828252d5SJiaqing Zhao                    const std::string& certObjPath,
613828252d5SJiaqing Zhao                    const std::string& csrObjPath)
6145968caeeSMarri Devender Rao {
61562598e31SEd Tanous     BMCWEB_LOG_DEBUG("getCSR CertObjectPath{} CSRObjectPath={} service={}",
61662598e31SEd Tanous                      certObjPath, csrObjPath, service);
617828252d5SJiaqing Zhao     crow::connections::systemBus->async_method_call(
618bd79bce8SPatrick Williams         [asyncResp,
619bd79bce8SPatrick Williams          certURI](const boost::system::error_code& ec, const std::string& csr) {
620828252d5SJiaqing Zhao             if (ec)
621828252d5SJiaqing Zhao             {
62262598e31SEd Tanous                 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
623828252d5SJiaqing Zhao                 messages::internalError(asyncResp->res);
624828252d5SJiaqing Zhao                 return;
625828252d5SJiaqing Zhao             }
626828252d5SJiaqing Zhao             if (csr.empty())
627828252d5SJiaqing Zhao             {
62862598e31SEd Tanous                 BMCWEB_LOG_ERROR("CSR read is empty");
629828252d5SJiaqing Zhao                 messages::internalError(asyncResp->res);
630828252d5SJiaqing Zhao                 return;
631828252d5SJiaqing Zhao             }
632828252d5SJiaqing Zhao             asyncResp->res.jsonValue["CSRString"] = csr;
633828252d5SJiaqing Zhao             asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
634828252d5SJiaqing Zhao                 certURI;
635828252d5SJiaqing Zhao         },
636828252d5SJiaqing Zhao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
637828252d5SJiaqing Zhao }
638828252d5SJiaqing Zhao 
639828252d5SJiaqing Zhao inline void
handleGenerateCSRAction(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)640828252d5SJiaqing Zhao     handleGenerateCSRAction(App& app, const crow::Request& req,
641828252d5SJiaqing Zhao                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
642828252d5SJiaqing Zhao {
6433ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
64445ca1b86SEd Tanous     {
64545ca1b86SEd Tanous         return;
64645ca1b86SEd Tanous     }
647828252d5SJiaqing Zhao     static const int rsaKeyBitLength = 2048;
6485968caeeSMarri Devender Rao 
649828252d5SJiaqing Zhao     // Required parameters
650828252d5SJiaqing Zhao     std::string city;
651828252d5SJiaqing Zhao     std::string commonName;
652828252d5SJiaqing Zhao     std::string country;
653828252d5SJiaqing Zhao     std::string organization;
654828252d5SJiaqing Zhao     std::string organizationalUnit;
655828252d5SJiaqing Zhao     std::string state;
6567a31e336SEd Tanous     std::string certURI;
657828252d5SJiaqing Zhao 
658828252d5SJiaqing Zhao     // Optional parameters
659828252d5SJiaqing Zhao     std::optional<std::vector<std::string>> optAlternativeNames =
660828252d5SJiaqing Zhao         std::vector<std::string>();
661828252d5SJiaqing Zhao     std::optional<std::string> optContactPerson = "";
662828252d5SJiaqing Zhao     std::optional<std::string> optChallengePassword = "";
663828252d5SJiaqing Zhao     std::optional<std::string> optEmail = "";
664828252d5SJiaqing Zhao     std::optional<std::string> optGivenName = "";
665828252d5SJiaqing Zhao     std::optional<std::string> optInitials = "";
666828252d5SJiaqing Zhao     std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
667828252d5SJiaqing Zhao     std::optional<std::string> optKeyCurveId = "secp384r1";
668828252d5SJiaqing Zhao     std::optional<std::string> optKeyPairAlgorithm = "EC";
669828252d5SJiaqing Zhao     std::optional<std::vector<std::string>> optKeyUsage =
670828252d5SJiaqing Zhao         std::vector<std::string>();
671828252d5SJiaqing Zhao     std::optional<std::string> optSurname = "";
672828252d5SJiaqing Zhao     std::optional<std::string> optUnstructuredName = "";
673828252d5SJiaqing Zhao     if (!json_util::readJsonAction(
674828252d5SJiaqing Zhao             req, asyncResp->res, "City", city, "CommonName", commonName,
675828252d5SJiaqing Zhao             "ContactPerson", optContactPerson, "Country", country,
676828252d5SJiaqing Zhao             "Organization", organization, "OrganizationalUnit",
6777a31e336SEd Tanous             organizationalUnit, "State", state,
6787a31e336SEd Tanous             "CertificateCollection/@odata.id", certURI, "AlternativeNames",
6797a31e336SEd Tanous             optAlternativeNames, "ChallengePassword", optChallengePassword,
6807a31e336SEd Tanous             "Email", optEmail, "GivenName", optGivenName, "Initials",
6817a31e336SEd Tanous             optInitials, "KeyBitLength", optKeyBitLength, "KeyCurveId",
6827a31e336SEd Tanous             optKeyCurveId, "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
6837a31e336SEd Tanous             optKeyUsage, "Surname", optSurname, "UnstructuredName",
6847a31e336SEd Tanous             optUnstructuredName))
685828252d5SJiaqing Zhao     {
686828252d5SJiaqing Zhao         return;
6875968caeeSMarri Devender Rao     }
6885968caeeSMarri Devender Rao 
689828252d5SJiaqing Zhao     // bmcweb has no way to store or decode a private key challenge
690828252d5SJiaqing Zhao     // password, which will likely cause bmcweb to crash on startup
691828252d5SJiaqing Zhao     // if this is not set on a post so not allowing the user to set
692828252d5SJiaqing Zhao     // value
693828252d5SJiaqing Zhao     if (!optChallengePassword->empty())
6945968caeeSMarri Devender Rao     {
695828252d5SJiaqing Zhao         messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
696828252d5SJiaqing Zhao                                               "ChallengePassword");
697828252d5SJiaqing Zhao         return;
698828252d5SJiaqing Zhao     }
699828252d5SJiaqing Zhao 
700828252d5SJiaqing Zhao     std::string objectPath;
701828252d5SJiaqing Zhao     std::string service;
702253f11b8SEd Tanous     if (certURI.starts_with(std::format(
703253f11b8SEd Tanous             "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
704253f11b8SEd Tanous             BMCWEB_REDFISH_MANAGER_URI_NAME)))
705828252d5SJiaqing Zhao     {
706828252d5SJiaqing Zhao         objectPath = certs::httpsObjectPath;
707828252d5SJiaqing Zhao         service = certs::httpsServiceName;
708828252d5SJiaqing Zhao     }
709828252d5SJiaqing Zhao     else if (certURI.starts_with(
710828252d5SJiaqing Zhao                  "/redfish/v1/AccountService/LDAP/Certificates"))
711828252d5SJiaqing Zhao     {
712828252d5SJiaqing Zhao         objectPath = certs::ldapObjectPath;
713828252d5SJiaqing Zhao         service = certs::ldapServiceName;
714828252d5SJiaqing Zhao     }
715828252d5SJiaqing Zhao     else
716828252d5SJiaqing Zhao     {
717828252d5SJiaqing Zhao         messages::actionParameterNotSupported(
718828252d5SJiaqing Zhao             asyncResp->res, "CertificateCollection", "GenerateCSR");
719828252d5SJiaqing Zhao         return;
720828252d5SJiaqing Zhao     }
721828252d5SJiaqing Zhao 
722828252d5SJiaqing Zhao     // supporting only EC and RSA algorithm
723828252d5SJiaqing Zhao     if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
724828252d5SJiaqing Zhao     {
725828252d5SJiaqing Zhao         messages::actionParameterNotSupported(
726828252d5SJiaqing Zhao             asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
727828252d5SJiaqing Zhao         return;
728828252d5SJiaqing Zhao     }
729828252d5SJiaqing Zhao 
730828252d5SJiaqing Zhao     // supporting only 2048 key bit length for RSA algorithm due to
731828252d5SJiaqing Zhao     // time consumed in generating private key
732828252d5SJiaqing Zhao     if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength)
733828252d5SJiaqing Zhao     {
734e2616cc5SEd Tanous         messages::propertyValueNotInList(asyncResp->res, *optKeyBitLength,
735e2616cc5SEd Tanous                                          "KeyBitLength");
736828252d5SJiaqing Zhao         return;
737828252d5SJiaqing Zhao     }
738828252d5SJiaqing Zhao 
739828252d5SJiaqing Zhao     // validate KeyUsage supporting only 1 type based on URL
740253f11b8SEd Tanous     if (certURI.starts_with(std::format(
741253f11b8SEd Tanous             "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
742253f11b8SEd Tanous             BMCWEB_REDFISH_MANAGER_URI_NAME)))
743828252d5SJiaqing Zhao     {
744828252d5SJiaqing Zhao         if (optKeyUsage->empty())
745828252d5SJiaqing Zhao         {
746b2ba3072SPatrick Williams             optKeyUsage->emplace_back("ServerAuthentication");
747828252d5SJiaqing Zhao         }
748828252d5SJiaqing Zhao         else if (optKeyUsage->size() == 1)
749828252d5SJiaqing Zhao         {
750828252d5SJiaqing Zhao             if ((*optKeyUsage)[0] != "ServerAuthentication")
751828252d5SJiaqing Zhao             {
752828252d5SJiaqing Zhao                 messages::propertyValueNotInList(asyncResp->res,
753828252d5SJiaqing Zhao                                                  (*optKeyUsage)[0], "KeyUsage");
754828252d5SJiaqing Zhao                 return;
755828252d5SJiaqing Zhao             }
756828252d5SJiaqing Zhao         }
757828252d5SJiaqing Zhao         else
758828252d5SJiaqing Zhao         {
759828252d5SJiaqing Zhao             messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
760828252d5SJiaqing Zhao                                                   "GenerateCSR");
761828252d5SJiaqing Zhao             return;
762828252d5SJiaqing Zhao         }
763828252d5SJiaqing Zhao     }
764828252d5SJiaqing Zhao     else if (certURI.starts_with(
765828252d5SJiaqing Zhao                  "/redfish/v1/AccountService/LDAP/Certificates"))
766828252d5SJiaqing Zhao     {
767828252d5SJiaqing Zhao         if (optKeyUsage->empty())
768828252d5SJiaqing Zhao         {
769b2ba3072SPatrick Williams             optKeyUsage->emplace_back("ClientAuthentication");
770828252d5SJiaqing Zhao         }
771828252d5SJiaqing Zhao         else if (optKeyUsage->size() == 1)
772828252d5SJiaqing Zhao         {
773828252d5SJiaqing Zhao             if ((*optKeyUsage)[0] != "ClientAuthentication")
774828252d5SJiaqing Zhao             {
775828252d5SJiaqing Zhao                 messages::propertyValueNotInList(asyncResp->res,
776828252d5SJiaqing Zhao                                                  (*optKeyUsage)[0], "KeyUsage");
777828252d5SJiaqing Zhao                 return;
778828252d5SJiaqing Zhao             }
779828252d5SJiaqing Zhao         }
780828252d5SJiaqing Zhao         else
781828252d5SJiaqing Zhao         {
782828252d5SJiaqing Zhao             messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
783828252d5SJiaqing Zhao                                                   "GenerateCSR");
784828252d5SJiaqing Zhao             return;
785828252d5SJiaqing Zhao         }
786828252d5SJiaqing Zhao     }
787828252d5SJiaqing Zhao 
788828252d5SJiaqing Zhao     // Only allow one CSR matcher at a time so setting retry
789828252d5SJiaqing Zhao     // time-out and timer expiry to 10 seconds for now.
790828252d5SJiaqing Zhao     static const int timeOut = 10;
791828252d5SJiaqing Zhao     if (csrMatcher)
792828252d5SJiaqing Zhao     {
793828252d5SJiaqing Zhao         messages::serviceTemporarilyUnavailable(asyncResp->res,
794828252d5SJiaqing Zhao                                                 std::to_string(timeOut));
795828252d5SJiaqing Zhao         return;
796828252d5SJiaqing Zhao     }
797828252d5SJiaqing Zhao 
7988e8245dbSEd Tanous     if (req.ioService == nullptr)
7998e8245dbSEd Tanous     {
8008e8245dbSEd Tanous         messages::internalError(asyncResp->res);
8018e8245dbSEd Tanous         return;
8028e8245dbSEd Tanous     }
8038e8245dbSEd Tanous 
804828252d5SJiaqing Zhao     // Make this static so it survives outside this method
805828252d5SJiaqing Zhao     static boost::asio::steady_timer timeout(*req.ioService);
806828252d5SJiaqing Zhao     timeout.expires_after(std::chrono::seconds(timeOut));
807828252d5SJiaqing Zhao     timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
808828252d5SJiaqing Zhao         csrMatcher = nullptr;
809828252d5SJiaqing Zhao         if (ec)
810828252d5SJiaqing Zhao         {
811828252d5SJiaqing Zhao             // operation_aborted is expected if timer is canceled
812828252d5SJiaqing Zhao             // before completion.
813828252d5SJiaqing Zhao             if (ec != boost::asio::error::operation_aborted)
814828252d5SJiaqing Zhao             {
81562598e31SEd Tanous                 BMCWEB_LOG_ERROR("Async_wait failed {}", ec);
816828252d5SJiaqing Zhao             }
817828252d5SJiaqing Zhao             return;
818828252d5SJiaqing Zhao         }
81962598e31SEd Tanous         BMCWEB_LOG_ERROR("Timed out waiting for Generating CSR");
820828252d5SJiaqing Zhao         messages::internalError(asyncResp->res);
821828252d5SJiaqing Zhao     });
822828252d5SJiaqing Zhao 
823828252d5SJiaqing Zhao     // create a matcher to wait on CSR object
82462598e31SEd Tanous     BMCWEB_LOG_DEBUG("create matcher with path {}", objectPath);
825828252d5SJiaqing Zhao     std::string match("type='signal',"
826828252d5SJiaqing Zhao                       "interface='org.freedesktop.DBus.ObjectManager',"
827828252d5SJiaqing Zhao                       "path='" +
828828252d5SJiaqing Zhao                       objectPath +
829828252d5SJiaqing Zhao                       "',"
830828252d5SJiaqing Zhao                       "member='InterfacesAdded'");
831828252d5SJiaqing Zhao     csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
832828252d5SJiaqing Zhao         *crow::connections::systemBus, match,
833828252d5SJiaqing Zhao         [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
834828252d5SJiaqing Zhao             timeout.cancel();
835828252d5SJiaqing Zhao             if (m.is_method_error())
836828252d5SJiaqing Zhao             {
83762598e31SEd Tanous                 BMCWEB_LOG_ERROR("Dbus method error!!!");
838828252d5SJiaqing Zhao                 messages::internalError(asyncResp->res);
839828252d5SJiaqing Zhao                 return;
840828252d5SJiaqing Zhao             }
841828252d5SJiaqing Zhao 
84280f79a40SMichael Shen             dbus::utility::DBusInterfacesMap interfacesProperties;
843828252d5SJiaqing Zhao 
844828252d5SJiaqing Zhao             sdbusplus::message::object_path csrObjectPath;
845828252d5SJiaqing Zhao             m.read(csrObjectPath, interfacesProperties);
84662598e31SEd Tanous             BMCWEB_LOG_DEBUG("CSR object added{}", csrObjectPath.str);
847828252d5SJiaqing Zhao             for (const auto& interface : interfacesProperties)
848828252d5SJiaqing Zhao             {
849828252d5SJiaqing Zhao                 if (interface.first == "xyz.openbmc_project.Certs.CSR")
850828252d5SJiaqing Zhao                 {
851828252d5SJiaqing Zhao                     getCSR(asyncResp, certURI, service, objectPath,
852828252d5SJiaqing Zhao                            csrObjectPath.str);
853828252d5SJiaqing Zhao                     break;
854828252d5SJiaqing Zhao                 }
855828252d5SJiaqing Zhao             }
856828252d5SJiaqing Zhao         });
857828252d5SJiaqing Zhao     crow::connections::systemBus->async_method_call(
8585e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec, const std::string&) {
859828252d5SJiaqing Zhao             if (ec)
860828252d5SJiaqing Zhao             {
86162598e31SEd Tanous                 BMCWEB_LOG_ERROR("DBUS response error: {}", ec.message());
862828252d5SJiaqing Zhao                 messages::internalError(asyncResp->res);
863828252d5SJiaqing Zhao                 return;
864828252d5SJiaqing Zhao             }
865828252d5SJiaqing Zhao         },
866828252d5SJiaqing Zhao         service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
867828252d5SJiaqing Zhao         "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
868828252d5SJiaqing Zhao         commonName, *optContactPerson, country, *optEmail, *optGivenName,
869828252d5SJiaqing Zhao         *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm,
870828252d5SJiaqing Zhao         *optKeyUsage, organization, organizationalUnit, state, *optSurname,
871828252d5SJiaqing Zhao         *optUnstructuredName);
872828252d5SJiaqing Zhao }
873828252d5SJiaqing Zhao 
requestRoutesCertificateService(App & app)874828252d5SJiaqing Zhao inline void requestRoutesCertificateService(App& app)
875828252d5SJiaqing Zhao {
876828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
877828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificateService)
878002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
879828252d5SJiaqing Zhao             std::bind_front(handleCertificateServiceGet, std::ref(app)));
880828252d5SJiaqing Zhao 
881828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
882828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificateLocations)
883828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
884828252d5SJiaqing Zhao             std::bind_front(handleCertificateLocationsGet, std::ref(app)));
885828252d5SJiaqing Zhao 
886828252d5SJiaqing Zhao     BMCWEB_ROUTE(
887828252d5SJiaqing Zhao         app,
888828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
889828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateService)
890828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(
891828252d5SJiaqing Zhao             std::bind_front(handleReplaceCertificateAction, std::ref(app)));
892828252d5SJiaqing Zhao 
893828252d5SJiaqing Zhao     BMCWEB_ROUTE(
894828252d5SJiaqing Zhao         app,
895828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
896828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateService)
897828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(
898828252d5SJiaqing Zhao             std::bind_front(handleGenerateCSRAction, std::ref(app)));
899828252d5SJiaqing Zhao } // requestRoutesCertificateService
900828252d5SJiaqing Zhao 
handleHTTPSCertificateCollectionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerId)901828252d5SJiaqing Zhao inline void handleHTTPSCertificateCollectionGet(
902828252d5SJiaqing Zhao     App& app, const crow::Request& req,
903253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
904253f11b8SEd Tanous     const std::string& managerId)
905828252d5SJiaqing Zhao {
9063ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
90745ca1b86SEd Tanous     {
90845ca1b86SEd Tanous         return;
90945ca1b86SEd Tanous     }
9101476687dSEd Tanous 
911253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
912253f11b8SEd Tanous     {
913253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
914253f11b8SEd Tanous         return;
915253f11b8SEd Tanous     }
916253f11b8SEd Tanous 
917253f11b8SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
918253f11b8SEd Tanous         "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
919253f11b8SEd Tanous         BMCWEB_REDFISH_MANAGER_URI_NAME);
9201476687dSEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
9211476687dSEd Tanous         "#CertificateCollection.CertificateCollection";
9221476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
9231476687dSEd Tanous     asyncResp->res.jsonValue["Description"] =
9241476687dSEd Tanous         "A Collection of HTTPS certificate instances";
9258d1b46d7Szhanghch05 
926d3f92ce7SJiaqing Zhao     getCertificateList(asyncResp, certs::httpsObjectPath,
927d3f92ce7SJiaqing Zhao                        "/Members"_json_pointer,
928d3f92ce7SJiaqing Zhao                        "/Members@odata.count"_json_pointer);
929828252d5SJiaqing Zhao }
9305968caeeSMarri Devender Rao 
handleHTTPSCertificateCollectionPost(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerId)931828252d5SJiaqing Zhao inline void handleHTTPSCertificateCollectionPost(
932828252d5SJiaqing Zhao     App& app, const crow::Request& req,
933253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
934253f11b8SEd Tanous     const std::string& managerId)
935828252d5SJiaqing Zhao {
9363ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
93745ca1b86SEd Tanous     {
93845ca1b86SEd Tanous         return;
93945ca1b86SEd Tanous     }
940253f11b8SEd Tanous 
941253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
942253f11b8SEd Tanous     {
943253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
944253f11b8SEd Tanous         return;
945253f11b8SEd Tanous     }
946253f11b8SEd Tanous 
94762598e31SEd Tanous     BMCWEB_LOG_DEBUG("HTTPSCertificateCollection::doPost");
9488d1b46d7Szhanghch05 
9491476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
9501476687dSEd Tanous     asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
9515968caeeSMarri Devender Rao 
952b2896149SEd Tanous     std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
95358eb238fSKowalski, Kamil 
954b2896149SEd Tanous     if (certHttpBody.empty())
95558eb238fSKowalski, Kamil     {
95662598e31SEd Tanous         BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
957a08752f5SZbigniew Kurzynski         messages::unrecognizedRequestBody(asyncResp->res);
95858eb238fSKowalski, Kamil         return;
95958eb238fSKowalski, Kamil     }
96058eb238fSKowalski, Kamil 
9615968caeeSMarri Devender Rao     std::shared_ptr<CertificateFile> certFile =
962b2896149SEd Tanous         std::make_shared<CertificateFile>(certHttpBody);
9635968caeeSMarri Devender Rao 
9645968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
9655e7e2dc5SEd Tanous         [asyncResp, certFile](const boost::system::error_code& ec,
966656ec7e3SZbigniew Kurzynski                               const std::string& objectPath) {
9675968caeeSMarri Devender Rao             if (ec)
9685968caeeSMarri Devender Rao             {
96962598e31SEd Tanous                 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
9705968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
9715968caeeSMarri Devender Rao                 return;
9725968caeeSMarri Devender Rao             }
973717b9802SJiaqing Zhao 
974717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
975717b9802SJiaqing Zhao             std::string certId = path.filename();
976ef4c65b7SEd Tanous             const boost::urls::url certURL = boost::urls::format(
977253f11b8SEd Tanous                 "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
978253f11b8SEd Tanous                 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
979bd79bce8SPatrick Williams             getCertificateProperties(asyncResp, objectPath,
980bd79bce8SPatrick Williams                                      certs::httpsServiceName, certId, certURL,
981bd79bce8SPatrick Williams                                      "HTTPS Certificate");
98262598e31SEd Tanous             BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
98362598e31SEd Tanous                              certFile->getCertFilePath());
9845968caeeSMarri Devender Rao         },
985828252d5SJiaqing Zhao         certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
986828252d5SJiaqing Zhao         "Install", certFile->getCertFilePath());
987828252d5SJiaqing Zhao }
9885968caeeSMarri Devender Rao 
handleHTTPSCertificateGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerId,const std::string & certId)989828252d5SJiaqing Zhao inline void handleHTTPSCertificateGet(
990828252d5SJiaqing Zhao     App& app, const crow::Request& req,
991253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
992253f11b8SEd Tanous     const std::string& managerId, const std::string& certId)
9937e860f15SJohn Edward Broadbent {
9943ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
99545ca1b86SEd Tanous     {
99645ca1b86SEd Tanous         return;
99745ca1b86SEd Tanous     }
9987e860f15SJohn Edward Broadbent 
999253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1000253f11b8SEd Tanous     {
1001253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1002253f11b8SEd Tanous         return;
1003253f11b8SEd Tanous     }
1004253f11b8SEd Tanous 
1005253f11b8SEd Tanous     BMCWEB_LOG_DEBUG("HTTPS Certificate ID={}", certId);
1006ef4c65b7SEd Tanous     const boost::urls::url certURL = boost::urls::format(
1007253f11b8SEd Tanous         "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
1008253f11b8SEd Tanous         BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1009828252d5SJiaqing Zhao     std::string objPath =
1010253f11b8SEd Tanous         sdbusplus::message::object_path(certs::httpsObjectPath) / certId;
1011253f11b8SEd Tanous     getCertificateProperties(asyncResp, objPath, certs::httpsServiceName,
1012253f11b8SEd Tanous                              certId, certURL, "HTTPS Certificate");
10137e860f15SJohn Edward Broadbent }
101437cce918SMarri Devender Rao 
requestRoutesHTTPSCertificate(App & app)1015828252d5SJiaqing Zhao inline void requestRoutesHTTPSCertificate(App& app)
101637cce918SMarri Devender Rao {
1017253f11b8SEd Tanous     BMCWEB_ROUTE(
1018253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
1019ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
1020828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(std::bind_front(
1021828252d5SJiaqing Zhao             handleHTTPSCertificateCollectionGet, std::ref(app)));
1022828252d5SJiaqing Zhao 
1023253f11b8SEd Tanous     BMCWEB_ROUTE(
1024253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/")
1025828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateCollection)
1026828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(std::bind_front(
1027828252d5SJiaqing Zhao             handleHTTPSCertificateCollectionPost, std::ref(app)));
1028828252d5SJiaqing Zhao 
1029828252d5SJiaqing Zhao     BMCWEB_ROUTE(
1030828252d5SJiaqing Zhao         app,
1031253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/<str>/")
1032828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificate)
1033002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1034828252d5SJiaqing Zhao             std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
1035828252d5SJiaqing Zhao }
1036828252d5SJiaqing Zhao 
handleLDAPCertificateCollectionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1037828252d5SJiaqing Zhao inline void handleLDAPCertificateCollectionGet(
1038828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1039828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1040828252d5SJiaqing Zhao {
10413ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
104245ca1b86SEd Tanous     {
104345ca1b86SEd Tanous         return;
104445ca1b86SEd Tanous     }
10451476687dSEd Tanous 
10461476687dSEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
10471476687dSEd Tanous         "/redfish/v1/AccountService/LDAP/Certificates";
10481476687dSEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
10491476687dSEd Tanous         "#CertificateCollection.CertificateCollection";
10501476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
10511476687dSEd Tanous     asyncResp->res.jsonValue["Description"] =
10521476687dSEd Tanous         "A Collection of LDAP certificate instances";
10538d1b46d7Szhanghch05 
1054d3f92ce7SJiaqing Zhao     getCertificateList(asyncResp, certs::ldapObjectPath,
1055d3f92ce7SJiaqing Zhao                        "/Members"_json_pointer,
1056d3f92ce7SJiaqing Zhao                        "/Members@odata.count"_json_pointer);
1057828252d5SJiaqing Zhao }
105837cce918SMarri Devender Rao 
handleLDAPCertificateCollectionPost(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1059828252d5SJiaqing Zhao inline void handleLDAPCertificateCollectionPost(
1060828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1061828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1062828252d5SJiaqing Zhao {
10633ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
106445ca1b86SEd Tanous     {
106545ca1b86SEd Tanous         return;
106645ca1b86SEd Tanous     }
1067b2896149SEd Tanous     std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
106858eb238fSKowalski, Kamil 
1069b2896149SEd Tanous     if (certHttpBody.empty())
107058eb238fSKowalski, Kamil     {
107162598e31SEd Tanous         BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
1072a08752f5SZbigniew Kurzynski         messages::unrecognizedRequestBody(asyncResp->res);
107358eb238fSKowalski, Kamil         return;
107458eb238fSKowalski, Kamil     }
107558eb238fSKowalski, Kamil 
107658eb238fSKowalski, Kamil     std::shared_ptr<CertificateFile> certFile =
1077b2896149SEd Tanous         std::make_shared<CertificateFile>(certHttpBody);
107858eb238fSKowalski, Kamil 
107937cce918SMarri Devender Rao     crow::connections::systemBus->async_method_call(
10805e7e2dc5SEd Tanous         [asyncResp, certFile](const boost::system::error_code& ec,
1081656ec7e3SZbigniew Kurzynski                               const std::string& objectPath) {
108237cce918SMarri Devender Rao             if (ec)
108337cce918SMarri Devender Rao             {
108462598e31SEd Tanous                 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
108537cce918SMarri Devender Rao                 messages::internalError(asyncResp->res);
108637cce918SMarri Devender Rao                 return;
108737cce918SMarri Devender Rao             }
1088717b9802SJiaqing Zhao 
1089717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1090717b9802SJiaqing Zhao             std::string certId = path.filename();
1091ef4c65b7SEd Tanous             const boost::urls::url certURL = boost::urls::format(
1092ef4c65b7SEd Tanous                 "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
1093bd79bce8SPatrick Williams             getCertificateProperties(asyncResp, objectPath,
1094bd79bce8SPatrick Williams                                      certs::ldapServiceName, certId, certURL,
1095bd79bce8SPatrick Williams                                      "LDAP Certificate");
109662598e31SEd Tanous             BMCWEB_LOG_DEBUG("LDAP certificate install file={}",
109762598e31SEd Tanous                              certFile->getCertFilePath());
109837cce918SMarri Devender Rao         },
1099828252d5SJiaqing Zhao         certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
1100828252d5SJiaqing Zhao         "Install", certFile->getCertFilePath());
1101828252d5SJiaqing Zhao }
110237cce918SMarri Devender Rao 
handleLDAPCertificateGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & id)1103828252d5SJiaqing Zhao inline void handleLDAPCertificateGet(
1104828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1105828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
110637cce918SMarri Devender Rao {
11073ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
110845ca1b86SEd Tanous     {
110945ca1b86SEd Tanous         return;
111045ca1b86SEd Tanous     }
1111717b9802SJiaqing Zhao 
111262598e31SEd Tanous     BMCWEB_LOG_DEBUG("LDAP Certificate ID={}", id);
1113ef4c65b7SEd Tanous     const boost::urls::url certURL = boost::urls::format(
1114ef4c65b7SEd Tanous         "/redfish/v1/AccountService/LDAP/Certificates/{}", id);
1115717b9802SJiaqing Zhao     std::string objPath =
1116717b9802SJiaqing Zhao         sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1117717b9802SJiaqing Zhao     getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1118717b9802SJiaqing Zhao                              certURL, "LDAP Certificate");
1119828252d5SJiaqing Zhao }
1120828252d5SJiaqing Zhao 
handleLDAPCertificateDelete(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & id)112199612247SJiaqing Zhao inline void handleLDAPCertificateDelete(
112299612247SJiaqing Zhao     App& app, const crow::Request& req,
112399612247SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
112499612247SJiaqing Zhao {
112599612247SJiaqing Zhao     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
112699612247SJiaqing Zhao     {
112799612247SJiaqing Zhao         return;
112899612247SJiaqing Zhao     }
112999612247SJiaqing Zhao 
113062598e31SEd Tanous     BMCWEB_LOG_DEBUG("Delete LDAP Certificate ID={}", id);
113199612247SJiaqing Zhao     std::string objPath =
113299612247SJiaqing Zhao         sdbusplus::message::object_path(certs::ldapObjectPath) / id;
113399612247SJiaqing Zhao 
113499612247SJiaqing Zhao     deleteCertificate(asyncResp, certs::ldapServiceName, objPath);
113599612247SJiaqing Zhao }
113699612247SJiaqing Zhao 
requestRoutesLDAPCertificate(App & app)1137828252d5SJiaqing Zhao inline void requestRoutesLDAPCertificate(App& app)
1138cfcd5f6bSMarri Devender Rao {
1139828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1140828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificateCollection)
1141828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
1142828252d5SJiaqing Zhao             std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app)));
1143828252d5SJiaqing Zhao 
1144828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1145828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateCollection)
1146828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(std::bind_front(
1147828252d5SJiaqing Zhao             handleLDAPCertificateCollectionPost, std::ref(app)));
1148828252d5SJiaqing Zhao 
1149828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1150ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
1151002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1152828252d5SJiaqing Zhao             std::bind_front(handleLDAPCertificateGet, std::ref(app)));
115399612247SJiaqing Zhao 
115499612247SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
115599612247SJiaqing Zhao         .privileges(redfish::privileges::deleteCertificate)
115699612247SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
115799612247SJiaqing Zhao             std::bind_front(handleLDAPCertificateDelete, std::ref(app)));
1158828252d5SJiaqing Zhao } // requestRoutesLDAPCertificate
1159828252d5SJiaqing Zhao 
handleTrustStoreCertificateCollectionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerId)1160828252d5SJiaqing Zhao inline void handleTrustStoreCertificateCollectionGet(
1161828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1162253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1163253f11b8SEd Tanous     const std::string& managerId)
1164828252d5SJiaqing Zhao {
11653ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
116645ca1b86SEd Tanous     {
116745ca1b86SEd Tanous         return;
116845ca1b86SEd Tanous     }
11691476687dSEd Tanous 
1170253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1171253f11b8SEd Tanous     {
1172253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1173253f11b8SEd Tanous         return;
1174253f11b8SEd Tanous     }
1175253f11b8SEd Tanous 
11761476687dSEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
1177253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/Truststore/Certificates/",
1178253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
11791476687dSEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
11801476687dSEd Tanous         "#CertificateCollection.CertificateCollection";
1181002d39b4SEd Tanous     asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
11821476687dSEd Tanous     asyncResp->res.jsonValue["Description"] =
11831476687dSEd Tanous         "A Collection of TrustStore certificate instances";
11848d1b46d7Szhanghch05 
1185d3f92ce7SJiaqing Zhao     getCertificateList(asyncResp, certs::authorityObjectPath,
1186d3f92ce7SJiaqing Zhao                        "/Members"_json_pointer,
1187d3f92ce7SJiaqing Zhao                        "/Members@odata.count"_json_pointer);
1188828252d5SJiaqing Zhao }
1189cfcd5f6bSMarri Devender Rao 
handleTrustStoreCertificateCollectionPost(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerId)1190828252d5SJiaqing Zhao inline void handleTrustStoreCertificateCollectionPost(
1191828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1192253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1193253f11b8SEd Tanous     const std::string& managerId)
1194828252d5SJiaqing Zhao {
11953ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119645ca1b86SEd Tanous     {
119745ca1b86SEd Tanous         return;
119845ca1b86SEd Tanous     }
1199253f11b8SEd Tanous 
1200253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1201253f11b8SEd Tanous     {
1202253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1203253f11b8SEd Tanous         return;
1204253f11b8SEd Tanous     }
1205253f11b8SEd Tanous 
1206b2896149SEd Tanous     std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
1207a08752f5SZbigniew Kurzynski 
1208b2896149SEd Tanous     if (certHttpBody.empty())
1209a08752f5SZbigniew Kurzynski     {
121062598e31SEd Tanous         BMCWEB_LOG_ERROR("Cannot get certificate from request body.");
1211a08752f5SZbigniew Kurzynski         messages::unrecognizedRequestBody(asyncResp->res);
1212a08752f5SZbigniew Kurzynski         return;
1213a08752f5SZbigniew Kurzynski     }
1214a08752f5SZbigniew Kurzynski 
1215a08752f5SZbigniew Kurzynski     std::shared_ptr<CertificateFile> certFile =
1216b2896149SEd Tanous         std::make_shared<CertificateFile>(certHttpBody);
1217cfcd5f6bSMarri Devender Rao     crow::connections::systemBus->async_method_call(
12185e7e2dc5SEd Tanous         [asyncResp, certFile](const boost::system::error_code& ec,
1219656ec7e3SZbigniew Kurzynski                               const std::string& objectPath) {
1220cfcd5f6bSMarri Devender Rao             if (ec)
1221cfcd5f6bSMarri Devender Rao             {
122262598e31SEd Tanous                 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
1223cfcd5f6bSMarri Devender Rao                 messages::internalError(asyncResp->res);
1224cfcd5f6bSMarri Devender Rao                 return;
1225cfcd5f6bSMarri Devender Rao             }
1226656ec7e3SZbigniew Kurzynski 
1227717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1228717b9802SJiaqing Zhao             std::string certId = path.filename();
1229ef4c65b7SEd Tanous             const boost::urls::url certURL = boost::urls::format(
1230253f11b8SEd Tanous                 "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1231253f11b8SEd Tanous                 BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1232717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
1233bd79bce8SPatrick Williams                                      certs::authorityServiceName, certId,
1234bd79bce8SPatrick Williams                                      certURL, "TrustStore Certificate");
123562598e31SEd Tanous             BMCWEB_LOG_DEBUG("TrustStore certificate install file={}",
123662598e31SEd Tanous                              certFile->getCertFilePath());
1237cfcd5f6bSMarri Devender Rao         },
1238cfcd5f6bSMarri Devender Rao         certs::authorityServiceName, certs::authorityObjectPath,
12390fda0f12SGeorge Liu         certs::certInstallIntf, "Install", certFile->getCertFilePath());
1240828252d5SJiaqing Zhao }
1241cfcd5f6bSMarri Devender Rao 
handleTrustStoreCertificateGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerId,const std::string & certId)1242828252d5SJiaqing Zhao inline void handleTrustStoreCertificateGet(
1243828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1244253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1245253f11b8SEd Tanous     const std::string& managerId, const std::string& certId)
1246cfcd5f6bSMarri Devender Rao {
12473ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
124845ca1b86SEd Tanous     {
124945ca1b86SEd Tanous         return;
125045ca1b86SEd Tanous     }
1251717b9802SJiaqing Zhao 
1252253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1253253f11b8SEd Tanous     {
1254253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1255253f11b8SEd Tanous         return;
1256253f11b8SEd Tanous     }
1257253f11b8SEd Tanous 
1258253f11b8SEd Tanous     BMCWEB_LOG_DEBUG("Truststore Certificate ID={}", certId);
1259ef4c65b7SEd Tanous     const boost::urls::url certURL = boost::urls::format(
1260253f11b8SEd Tanous         "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
1261253f11b8SEd Tanous         BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
1262717b9802SJiaqing Zhao     std::string objPath =
1263253f11b8SEd Tanous         sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
1264828252d5SJiaqing Zhao     getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
1265253f11b8SEd Tanous                              certId, certURL, "TrustStore Certificate");
1266828252d5SJiaqing Zhao }
126707a60299SZbigniew Kurzynski 
handleTrustStoreCertificateDelete(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerId,const std::string & certId)1268828252d5SJiaqing Zhao inline void handleTrustStoreCertificateDelete(
1269828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1270253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1271253f11b8SEd Tanous     const std::string& managerId, const std::string& certId)
1272828252d5SJiaqing Zhao {
12733ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
127445ca1b86SEd Tanous     {
127545ca1b86SEd Tanous         return;
127645ca1b86SEd Tanous     }
127707a60299SZbigniew Kurzynski 
1278253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1279253f11b8SEd Tanous     {
1280253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1281253f11b8SEd Tanous         return;
1282253f11b8SEd Tanous     }
1283253f11b8SEd Tanous 
1284253f11b8SEd Tanous     BMCWEB_LOG_DEBUG("Delete TrustStore Certificate ID={}", certId);
1285717b9802SJiaqing Zhao     std::string objPath =
1286253f11b8SEd Tanous         sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
128707a60299SZbigniew Kurzynski 
12887a3a8f7aSJiaqing Zhao     deleteCertificate(asyncResp, certs::authorityServiceName, objPath);
1289828252d5SJiaqing Zhao }
1290828252d5SJiaqing Zhao 
requestRoutesTrustStoreCertificate(App & app)1291828252d5SJiaqing Zhao inline void requestRoutesTrustStoreCertificate(App& app)
1292828252d5SJiaqing Zhao {
1293253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
1294828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificate)
1295828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(std::bind_front(
1296828252d5SJiaqing Zhao             handleTrustStoreCertificateCollectionGet, std::ref(app)));
1297828252d5SJiaqing Zhao 
1298253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
1299828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateCollection)
1300828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(std::bind_front(
1301828252d5SJiaqing Zhao             handleTrustStoreCertificateCollectionPost, std::ref(app)));
1302828252d5SJiaqing Zhao 
1303253f11b8SEd Tanous     BMCWEB_ROUTE(app,
1304253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
1305828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificate)
1306828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
1307828252d5SJiaqing Zhao             std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));
1308828252d5SJiaqing Zhao 
1309253f11b8SEd Tanous     BMCWEB_ROUTE(app,
1310253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
1311828252d5SJiaqing Zhao         .privileges(redfish::privileges::deleteCertificate)
1312828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
1313828252d5SJiaqing Zhao             std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));
13147e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
13155968caeeSMarri Devender Rao } // namespace redfish
1316