xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 1aa0c2b84be62a20d8c37a11ad877e0a8a48c69d)
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"
6*1aa0c2b8SEd 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>
159b12d1f9SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
163ccb3adbSEd Tanous #include <sdbusplus/bus/match.hpp>
179b12d1f9SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
181214b7e7SGunnar Mills 
197a1dbc48SGeorge Liu #include <array>
203ccb3adbSEd Tanous #include <memory>
217a1dbc48SGeorge Liu #include <string_view>
227a1dbc48SGeorge Liu 
235968caeeSMarri Devender Rao namespace redfish
245968caeeSMarri Devender Rao {
255968caeeSMarri Devender Rao namespace certs
265968caeeSMarri Devender Rao {
275968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install";
285968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
2907a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
305968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
315968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties";
325968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
3337cce918SMarri Devender Rao constexpr char const* httpsServiceName =
3437cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
3537cce918SMarri Devender Rao constexpr char const* ldapServiceName =
3637cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
37cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName =
38cfcd5f6bSMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
39c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs";
40c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath =
41c6a8dfb1SJiaqing Zhao     "/xyz/openbmc_project/certs/server/https";
42c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
43cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath =
44cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
455968caeeSMarri Devender Rao } // namespace certs
465968caeeSMarri Devender Rao 
475968caeeSMarri Devender Rao /**
485968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
495968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
505968caeeSMarri Devender Rao  * are installed.
515968caeeSMarri Devender Rao  */
527e860f15SJohn Edward Broadbent 
538d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
548d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5558eb238fSKowalski, Kamil     const crow::Request& req)
5658eb238fSKowalski, Kamil {
57*1aa0c2b8SEd Tanous     nlohmann::json reqJson;
58*1aa0c2b8SEd Tanous     JsonParseResult ret = parseRequestAsJson(req, reqJson);
59*1aa0c2b8SEd Tanous     if (ret != JsonParseResult::Success)
6058eb238fSKowalski, Kamil     {
6158eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
6258eb238fSKowalski, Kamil         return req.body;
6358eb238fSKowalski, Kamil     }
6458eb238fSKowalski, Kamil 
6558eb238fSKowalski, Kamil     std::string certificate;
6658eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
6758eb238fSKowalski, Kamil 
6815ed6780SWilly Tu     if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
6915ed6780SWilly Tu                                   certificate, "CertificateType",
7015ed6780SWilly Tu                                   certificateType))
7158eb238fSKowalski, Kamil     {
7258eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
7358eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
74abb93cddSEd Tanous         return {};
7558eb238fSKowalski, Kamil     }
7658eb238fSKowalski, Kamil 
7758eb238fSKowalski, Kamil     if (*certificateType != "PEM")
7858eb238fSKowalski, Kamil     {
7958eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
8058eb238fSKowalski, Kamil                                          "CertificateType");
81abb93cddSEd Tanous         return {};
8258eb238fSKowalski, Kamil     }
8358eb238fSKowalski, Kamil 
8458eb238fSKowalski, Kamil     return certificate;
8558eb238fSKowalski, Kamil }
8658eb238fSKowalski, Kamil 
875968caeeSMarri Devender Rao /**
885968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
895968caeeSMarri Devender Rao  */
905968caeeSMarri Devender Rao class CertificateFile
915968caeeSMarri Devender Rao {
925968caeeSMarri Devender Rao   public:
935968caeeSMarri Devender Rao     CertificateFile() = delete;
945968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
955968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
965968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
975968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
984e23a444SEd Tanous     explicit CertificateFile(const std::string& certString)
995968caeeSMarri Devender Rao     {
10072d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1015207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1025207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1035207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
104e662eae8SEd Tanous         if (tempDirectory != nullptr)
1055968caeeSMarri Devender Rao         {
1065968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1075968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1085968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1095968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1105968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1115968caeeSMarri Devender Rao             out << certString;
1125968caeeSMarri Devender Rao             out.close();
1138cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Creating certificate file"
1148cc8edecSEd Tanous                              << certificateFile.string();
1155968caeeSMarri Devender Rao         }
1165968caeeSMarri Devender Rao     }
1175968caeeSMarri Devender Rao     ~CertificateFile()
1185968caeeSMarri Devender Rao     {
1195968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1205968caeeSMarri Devender Rao         {
1218cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Removing certificate file"
1228cc8edecSEd Tanous                              << certificateFile.string();
12323a21a1cSEd Tanous             std::error_code ec;
12423a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
12523a21a1cSEd Tanous             if (ec)
1265968caeeSMarri Devender Rao             {
1275968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1288cc8edecSEd Tanous                                  << certDirectory.string();
1295968caeeSMarri Devender Rao             }
1305968caeeSMarri Devender Rao         }
1315968caeeSMarri Devender Rao     }
1325968caeeSMarri Devender Rao     std::string getCertFilePath()
1335968caeeSMarri Devender Rao     {
1345968caeeSMarri Devender Rao         return certificateFile;
1355968caeeSMarri Devender Rao     }
1365968caeeSMarri Devender Rao 
1375968caeeSMarri Devender Rao   private:
1385968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1395968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1405968caeeSMarri Devender Rao };
1415968caeeSMarri Devender Rao 
1425968caeeSMarri Devender Rao /**
1434e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
1445968caeeSMarri Devender Rao  *
1455968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
1465968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
1475968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
1485968caeeSMarri Devender Rao  * @return None
1495968caeeSMarri Devender Rao  */
1505968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
1515968caeeSMarri Devender Rao                                       const std::string_view value)
1525968caeeSMarri Devender Rao {
1535968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
1545968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
1555968caeeSMarri Devender Rao     while (i != value.end())
1565968caeeSMarri Devender Rao     {
1575968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
1585968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
1595968caeeSMarri Devender Rao         {
16017a897dfSManojkiran Eda             ++i;
1615968caeeSMarri Devender Rao         }
1625968caeeSMarri Devender Rao         if (i == value.end())
1635968caeeSMarri Devender Rao         {
1645968caeeSMarri Devender Rao             break;
1655968caeeSMarri Devender Rao         }
166271584abSEd Tanous         const std::string_view key(tokenBegin,
167271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
16817a897dfSManojkiran Eda         ++i;
1695968caeeSMarri Devender Rao         tokenBegin = i;
1705968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
1715968caeeSMarri Devender Rao         {
17217a897dfSManojkiran Eda             ++i;
1735968caeeSMarri Devender Rao         }
174271584abSEd Tanous         const std::string_view val(tokenBegin,
175271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
1765968caeeSMarri Devender Rao         if (key == "L")
1775968caeeSMarri Devender Rao         {
1785968caeeSMarri Devender Rao             out["City"] = val;
1795968caeeSMarri Devender Rao         }
1805968caeeSMarri Devender Rao         else if (key == "CN")
1815968caeeSMarri Devender Rao         {
1825968caeeSMarri Devender Rao             out["CommonName"] = val;
1835968caeeSMarri Devender Rao         }
1845968caeeSMarri Devender Rao         else if (key == "C")
1855968caeeSMarri Devender Rao         {
1865968caeeSMarri Devender Rao             out["Country"] = val;
1875968caeeSMarri Devender Rao         }
1885968caeeSMarri Devender Rao         else if (key == "O")
1895968caeeSMarri Devender Rao         {
1905968caeeSMarri Devender Rao             out["Organization"] = val;
1915968caeeSMarri Devender Rao         }
1925968caeeSMarri Devender Rao         else if (key == "OU")
1935968caeeSMarri Devender Rao         {
1945968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
1955968caeeSMarri Devender Rao         }
1965968caeeSMarri Devender Rao         else if (key == "ST")
1975968caeeSMarri Devender Rao         {
1985968caeeSMarri Devender Rao             out["State"] = val;
1995968caeeSMarri Devender Rao         }
2005968caeeSMarri Devender Rao         // skip comma character
2015968caeeSMarri Devender Rao         if (i != value.end())
2025968caeeSMarri Devender Rao         {
20317a897dfSManojkiran Eda             ++i;
2045968caeeSMarri Devender Rao         }
2055968caeeSMarri Devender Rao     }
2065968caeeSMarri Devender Rao }
2075968caeeSMarri Devender Rao 
2085968caeeSMarri Devender Rao /**
209d3f92ce7SJiaqing Zhao  * @brief Retrieve the installed certificate list
210d3f92ce7SJiaqing Zhao  *
211d3f92ce7SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
212d3f92ce7SJiaqing Zhao  * @param[in] basePath DBus object path to search
213d3f92ce7SJiaqing Zhao  * @param[in] listPtr Json pointer to the list in asyncResp
214d3f92ce7SJiaqing Zhao  * @param[in] countPtr Json pointer to the count in asyncResp
215d3f92ce7SJiaqing Zhao  * @return None
216d3f92ce7SJiaqing Zhao  */
217d3f92ce7SJiaqing Zhao static void
218d3f92ce7SJiaqing Zhao     getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
219d3f92ce7SJiaqing Zhao                        const std::string& basePath,
220d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& listPtr,
221d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& countPtr)
222d3f92ce7SJiaqing Zhao {
2237a1dbc48SGeorge Liu     constexpr std::array<std::string_view, 1> interfaces = {
2247a1dbc48SGeorge Liu         certs::certPropIntf};
2257a1dbc48SGeorge Liu     dbus::utility::getSubTreePaths(
2267a1dbc48SGeorge Liu         basePath, 0, interfaces,
227d3f92ce7SJiaqing Zhao         [asyncResp, listPtr, countPtr](
2287a1dbc48SGeorge Liu             const boost::system::error_code& ec,
229d3f92ce7SJiaqing Zhao             const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
230d3f92ce7SJiaqing Zhao         if (ec)
231d3f92ce7SJiaqing Zhao         {
232d3f92ce7SJiaqing Zhao             BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec;
233d3f92ce7SJiaqing Zhao             messages::internalError(asyncResp->res);
234d3f92ce7SJiaqing Zhao             return;
235d3f92ce7SJiaqing Zhao         }
236d3f92ce7SJiaqing Zhao 
237d3f92ce7SJiaqing Zhao         nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
238d3f92ce7SJiaqing Zhao         links = nlohmann::json::array();
239d3f92ce7SJiaqing Zhao         for (const auto& certPath : certPaths)
240d3f92ce7SJiaqing Zhao         {
241d3f92ce7SJiaqing Zhao             sdbusplus::message::object_path objPath(certPath);
242d3f92ce7SJiaqing Zhao             std::string certId = objPath.filename();
243d3f92ce7SJiaqing Zhao             if (certId.empty())
244d3f92ce7SJiaqing Zhao             {
245d3f92ce7SJiaqing Zhao                 BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath;
246d3f92ce7SJiaqing Zhao                 continue;
247d3f92ce7SJiaqing Zhao             }
248d3f92ce7SJiaqing Zhao 
249d3f92ce7SJiaqing Zhao             boost::urls::url certURL;
250d3f92ce7SJiaqing Zhao             if (objPath.parent_path() == certs::httpsObjectPath)
251d3f92ce7SJiaqing Zhao             {
252d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
253d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
254d3f92ce7SJiaqing Zhao                     "HTTPS", "Certificates", certId);
255d3f92ce7SJiaqing Zhao             }
256d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::ldapObjectPath)
257d3f92ce7SJiaqing Zhao             {
258d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces("redfish", "v1",
259d3f92ce7SJiaqing Zhao                                                        "AccountService", "LDAP",
260d3f92ce7SJiaqing Zhao                                                        "Certificates", certId);
261d3f92ce7SJiaqing Zhao             }
262d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::authorityObjectPath)
263d3f92ce7SJiaqing Zhao             {
264d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
265d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "Truststore",
266d3f92ce7SJiaqing Zhao                     "Certificates", certId);
267d3f92ce7SJiaqing Zhao             }
268d3f92ce7SJiaqing Zhao             else
269d3f92ce7SJiaqing Zhao             {
270d3f92ce7SJiaqing Zhao                 continue;
271d3f92ce7SJiaqing Zhao             }
272d3f92ce7SJiaqing Zhao 
273d3f92ce7SJiaqing Zhao             nlohmann::json::object_t link;
274d3f92ce7SJiaqing Zhao             link["@odata.id"] = certURL;
275d3f92ce7SJiaqing Zhao             links.emplace_back(std::move(link));
276d3f92ce7SJiaqing Zhao         }
277d3f92ce7SJiaqing Zhao 
278d3f92ce7SJiaqing Zhao         asyncResp->res.jsonValue[countPtr] = links.size();
2797a1dbc48SGeorge Liu         });
280d3f92ce7SJiaqing Zhao }
281d3f92ce7SJiaqing Zhao 
282d3f92ce7SJiaqing Zhao /**
2835968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
2845968caeeSMarri Devender Rao  * message
2855968caeeSMarri Devender Rao  *
2865968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
2875968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
2885968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
2895968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
2905968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
2915968caeeSMarri Devender Rao  * @return None
2925968caeeSMarri Devender Rao  */
2935968caeeSMarri Devender Rao static void getCertificateProperties(
2948d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
295e19e97e2SJiaqing Zhao     const std::string& objectPath, const std::string& service,
2961e312598SJiaqing Zhao     const std::string& certId, const boost::urls::url& certURL,
297e19e97e2SJiaqing Zhao     const std::string& name)
2985968caeeSMarri Devender Rao {
2995968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
3005968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
3019b12d1f9SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
3029b12d1f9SKrzysztof Grobelny         *crow::connections::systemBus, service, objectPath, certs::certPropIntf,
303b9d36b47SEd Tanous         [asyncResp, certURL, certId,
304b9d36b47SEd Tanous          name](const boost::system::error_code ec,
305b9d36b47SEd Tanous                const dbus::utility::DBusPropertiesMap& properties) {
3065968caeeSMarri Devender Rao         if (ec)
3075968caeeSMarri Devender Rao         {
3085968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
309d8a5d5d8SJiaqing Zhao             messages::resourceNotFound(asyncResp->res, "Certificate", 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(
3219b12d1f9SKrzysztof Grobelny             dbus_utils::UnpackErrorPrinter(), properties, "CertificateString",
3229b12d1f9SKrzysztof Grobelny             certificateString, "KeyUsage", keyUsage, "Issuer", issuer,
3239b12d1f9SKrzysztof Grobelny             "Subject", subject, "ValidNotAfter", validNotAfter,
3249b12d1f9SKrzysztof Grobelny             "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         {
3439b12d1f9SKrzysztof Grobelny             asyncResp->res.jsonValue["CertificateString"] = *certificateString;
3445968caeeSMarri Devender Rao         }
3459b12d1f9SKrzysztof Grobelny 
3469b12d1f9SKrzysztof Grobelny         if (keyUsage != nullptr)
3475968caeeSMarri Devender Rao         {
3489b12d1f9SKrzysztof Grobelny             asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
3495968caeeSMarri Devender Rao         }
3509b12d1f9SKrzysztof Grobelny 
3519b12d1f9SKrzysztof Grobelny         if (issuer != nullptr)
3525968caeeSMarri Devender Rao         {
3539b12d1f9SKrzysztof Grobelny             updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
3549b12d1f9SKrzysztof Grobelny                                       *issuer);
3555968caeeSMarri Devender Rao         }
3569b12d1f9SKrzysztof Grobelny 
3579b12d1f9SKrzysztof Grobelny         if (subject != nullptr)
3585968caeeSMarri Devender Rao         {
3599b12d1f9SKrzysztof Grobelny             updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
3609b12d1f9SKrzysztof Grobelny                                       *subject);
3615968caeeSMarri Devender Rao         }
3629b12d1f9SKrzysztof Grobelny 
3639b12d1f9SKrzysztof Grobelny         if (validNotAfter != nullptr)
3645968caeeSMarri Devender Rao         {
3655968caeeSMarri Devender Rao             asyncResp->res.jsonValue["ValidNotAfter"] =
3669b12d1f9SKrzysztof Grobelny                 redfish::time_utils::getDateTimeUint(*validNotAfter);
3675968caeeSMarri Devender Rao         }
3689b12d1f9SKrzysztof Grobelny 
3699b12d1f9SKrzysztof Grobelny         if (validNotBefore != nullptr)
3705968caeeSMarri Devender Rao         {
3715968caeeSMarri Devender Rao             asyncResp->res.jsonValue["ValidNotBefore"] =
3729b12d1f9SKrzysztof Grobelny                 redfish::time_utils::getDateTimeUint(*validNotBefore);
3735968caeeSMarri Devender Rao         }
3749b12d1f9SKrzysztof Grobelny 
3751e312598SJiaqing Zhao         asyncResp->res.addHeader(
376d9f6c621SEd Tanous             boost::beast::http::field::location,
377d9f6c621SEd Tanous             std::string_view(certURL.data(), certURL.size()));
3789b12d1f9SKrzysztof Grobelny         });
3795968caeeSMarri Devender Rao }
3805968caeeSMarri Devender Rao 
3817a3a8f7aSJiaqing Zhao static void
3827a3a8f7aSJiaqing Zhao     deleteCertificate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3837a3a8f7aSJiaqing Zhao                       const std::string& service,
3847a3a8f7aSJiaqing Zhao                       const sdbusplus::message::object_path& objectPath)
3857a3a8f7aSJiaqing Zhao {
3867a3a8f7aSJiaqing Zhao     crow::connections::systemBus->async_method_call(
3877a3a8f7aSJiaqing Zhao         [asyncResp,
3887a3a8f7aSJiaqing Zhao          id{objectPath.filename()}](const boost::system::error_code ec) {
3897a3a8f7aSJiaqing Zhao         if (ec)
3907a3a8f7aSJiaqing Zhao         {
3917a3a8f7aSJiaqing Zhao             messages::resourceNotFound(asyncResp->res, "Certificate", id);
3927a3a8f7aSJiaqing Zhao             return;
3937a3a8f7aSJiaqing Zhao         }
3947a3a8f7aSJiaqing Zhao         BMCWEB_LOG_INFO << "Certificate deleted";
3957a3a8f7aSJiaqing Zhao         asyncResp->res.result(boost::beast::http::status::no_content);
3967a3a8f7aSJiaqing Zhao         },
3977a3a8f7aSJiaqing Zhao         service, objectPath, certs::objDeleteIntf, "Delete");
3987a3a8f7aSJiaqing Zhao }
3997a3a8f7aSJiaqing Zhao 
400828252d5SJiaqing Zhao inline void handleCertificateServiceGet(
401828252d5SJiaqing Zhao     App& app, const crow::Request& req,
402828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
4035968caeeSMarri Devender Rao {
404828252d5SJiaqing Zhao     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
405828252d5SJiaqing Zhao     {
406828252d5SJiaqing Zhao         return;
407828252d5SJiaqing Zhao     }
408828252d5SJiaqing Zhao 
409828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.type"] =
410828252d5SJiaqing Zhao         "#CertificateService.v1_0_0.CertificateService";
411828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService";
412828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Id"] = "CertificateService";
413828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Name"] = "Certificate Service";
414828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Description"] =
415828252d5SJiaqing Zhao         "Actions available to manage certificates";
416828252d5SJiaqing Zhao     // /redfish/v1/CertificateService/CertificateLocations is something
417828252d5SJiaqing Zhao     // only ConfigureManager can access then only display when the user
418828252d5SJiaqing Zhao     // has permissions ConfigureManager
419828252d5SJiaqing Zhao     Privileges effectiveUserPrivileges =
420828252d5SJiaqing Zhao         redfish::getUserPrivileges(req.userRole);
421828252d5SJiaqing Zhao     if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
422828252d5SJiaqing Zhao                                          effectiveUserPrivileges))
423828252d5SJiaqing Zhao     {
424828252d5SJiaqing Zhao         asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
425828252d5SJiaqing Zhao             "/redfish/v1/CertificateService/CertificateLocations";
426828252d5SJiaqing Zhao     }
427828252d5SJiaqing Zhao     nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
428828252d5SJiaqing Zhao     nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"];
429828252d5SJiaqing Zhao     replace["target"] =
430828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate";
431828252d5SJiaqing Zhao     nlohmann::json::array_t allowed;
432828252d5SJiaqing Zhao     allowed.push_back("PEM");
433828252d5SJiaqing Zhao     replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
434828252d5SJiaqing Zhao     actions["#CertificateService.GenerateCSR"]["target"] =
435828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
436828252d5SJiaqing Zhao }
437828252d5SJiaqing Zhao 
438828252d5SJiaqing Zhao inline void handleCertificateLocationsGet(
439828252d5SJiaqing Zhao     App& app, const crow::Request& req,
440828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
441828252d5SJiaqing Zhao {
442828252d5SJiaqing Zhao     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
443828252d5SJiaqing Zhao     {
444828252d5SJiaqing Zhao         return;
445828252d5SJiaqing Zhao     }
446828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.id"] =
447828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/CertificateLocations";
448828252d5SJiaqing Zhao     asyncResp->res.jsonValue["@odata.type"] =
449828252d5SJiaqing Zhao         "#CertificateLocations.v1_0_0.CertificateLocations";
450828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Name"] = "Certificate Locations";
451828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Id"] = "CertificateLocations";
452828252d5SJiaqing Zhao     asyncResp->res.jsonValue["Description"] =
453828252d5SJiaqing Zhao         "Defines a resource that an administrator can use in order to "
454828252d5SJiaqing Zhao         "locate all certificates installed on a given service";
455828252d5SJiaqing Zhao 
456828252d5SJiaqing Zhao     getCertificateList(asyncResp, certs::baseObjectPath,
457828252d5SJiaqing Zhao                        "/Links/Certificates"_json_pointer,
458828252d5SJiaqing Zhao                        "/Links/Certificates@odata.count"_json_pointer);
459828252d5SJiaqing Zhao }
460828252d5SJiaqing Zhao 
461828252d5SJiaqing Zhao inline void handleReplaceCertificateAction(
462828252d5SJiaqing Zhao     App& app, const crow::Request& req,
463828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
464828252d5SJiaqing Zhao {
4653ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
46645ca1b86SEd Tanous     {
46745ca1b86SEd Tanous         return;
46845ca1b86SEd Tanous     }
4695968caeeSMarri Devender Rao     std::string certificate;
4705968caeeSMarri Devender Rao     nlohmann::json certificateUri;
4715968caeeSMarri Devender Rao     std::optional<std::string> certificateType = "PEM";
4728d1b46d7Szhanghch05 
473002d39b4SEd Tanous     if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
474002d39b4SEd Tanous                                    certificate, "CertificateUri",
475002d39b4SEd Tanous                                    certificateUri, "CertificateType",
476002d39b4SEd Tanous                                    certificateType))
4775968caeeSMarri Devender Rao     {
4785968caeeSMarri Devender Rao         BMCWEB_LOG_ERROR << "Required parameters are missing";
4795968caeeSMarri Devender Rao         messages::internalError(asyncResp->res);
4805968caeeSMarri Devender Rao         return;
4815968caeeSMarri Devender Rao     }
4825968caeeSMarri Devender Rao 
4835968caeeSMarri Devender Rao     if (!certificateType)
4845968caeeSMarri Devender Rao     {
4855968caeeSMarri Devender Rao         // should never happen, but it never hurts to be paranoid.
4865968caeeSMarri Devender Rao         return;
4875968caeeSMarri Devender Rao     }
4885968caeeSMarri Devender Rao     if (certificateType != "PEM")
4895968caeeSMarri Devender Rao     {
490828252d5SJiaqing Zhao         messages::actionParameterNotSupported(asyncResp->res, "CertificateType",
491828252d5SJiaqing Zhao                                               "ReplaceCertificate");
4925968caeeSMarri Devender Rao         return;
4935968caeeSMarri Devender Rao     }
4945968caeeSMarri Devender Rao 
4955968caeeSMarri Devender Rao     std::string certURI;
4965968caeeSMarri Devender Rao     if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
4975968caeeSMarri Devender Rao                                       "@odata.id", certURI))
4985968caeeSMarri Devender Rao     {
499828252d5SJiaqing Zhao         messages::actionParameterMissing(asyncResp->res, "ReplaceCertificate",
500828252d5SJiaqing Zhao                                          "CertificateUri");
5015968caeeSMarri Devender Rao         return;
5025968caeeSMarri Devender Rao     }
50375b63a2cSJiaqing Zhao     BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI;
5045968caeeSMarri Devender Rao 
50575b63a2cSJiaqing Zhao     boost::urls::result<boost::urls::url_view> parsedUrl =
50675b63a2cSJiaqing Zhao         boost::urls::parse_relative_ref(certURI);
50775b63a2cSJiaqing Zhao     if (!parsedUrl)
5085968caeeSMarri Devender Rao     {
509828252d5SJiaqing Zhao         messages::actionParameterValueFormatError(
510828252d5SJiaqing Zhao             asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate");
5115968caeeSMarri Devender Rao         return;
5125968caeeSMarri Devender Rao     }
51375b63a2cSJiaqing Zhao 
51475b63a2cSJiaqing Zhao     std::string id;
51575b63a2cSJiaqing Zhao     sdbusplus::message::object_path objectPath;
5165968caeeSMarri Devender Rao     std::string name;
51737cce918SMarri Devender Rao     std::string service;
518828252d5SJiaqing Zhao     if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers",
519828252d5SJiaqing Zhao                                        "bmc", "NetworkProtocol", "HTTPS",
520828252d5SJiaqing Zhao                                        "Certificates", std::ref(id)))
5215968caeeSMarri Devender Rao     {
522002d39b4SEd Tanous         objectPath =
52375b63a2cSJiaqing Zhao             sdbusplus::message::object_path(certs::httpsObjectPath) / id;
5245968caeeSMarri Devender Rao         name = "HTTPS certificate";
52537cce918SMarri Devender Rao         service = certs::httpsServiceName;
52637cce918SMarri Devender Rao     }
52775b63a2cSJiaqing Zhao     else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
52875b63a2cSJiaqing Zhao                                             "AccountService", "LDAP",
52975b63a2cSJiaqing Zhao                                             "Certificates", std::ref(id)))
53037cce918SMarri Devender Rao     {
531002d39b4SEd Tanous         objectPath =
53275b63a2cSJiaqing Zhao             sdbusplus::message::object_path(certs::ldapObjectPath) / id;
53337cce918SMarri Devender Rao         name = "LDAP certificate";
53437cce918SMarri Devender Rao         service = certs::ldapServiceName;
5355968caeeSMarri Devender Rao     }
53675b63a2cSJiaqing Zhao     else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
53775b63a2cSJiaqing Zhao                                             "Managers", "bmc", "Truststore",
53875b63a2cSJiaqing Zhao                                             "Certificates", std::ref(id)))
539cfcd5f6bSMarri Devender Rao     {
54075b63a2cSJiaqing Zhao         objectPath =
541828252d5SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
542cfcd5f6bSMarri Devender Rao         name = "TrustStore certificate";
543cfcd5f6bSMarri Devender Rao         service = certs::authorityServiceName;
544cfcd5f6bSMarri Devender Rao     }
5455968caeeSMarri Devender Rao     else
5465968caeeSMarri Devender Rao     {
547828252d5SJiaqing Zhao         messages::actionParameterNotSupported(asyncResp->res, "CertificateUri",
548828252d5SJiaqing Zhao                                               "ReplaceCertificate");
5495968caeeSMarri Devender Rao         return;
5505968caeeSMarri Devender Rao     }
5515968caeeSMarri Devender Rao 
5525968caeeSMarri Devender Rao     std::shared_ptr<CertificateFile> certFile =
5535968caeeSMarri Devender Rao         std::make_shared<CertificateFile>(certificate);
5545968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
5551e312598SJiaqing Zhao         [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
5565968caeeSMarri Devender Rao          name](const boost::system::error_code ec) {
5575968caeeSMarri Devender Rao         if (ec)
5585968caeeSMarri Devender Rao         {
5595968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
56090d2d1e8SJiaqing Zhao             if (ec.value() ==
56190d2d1e8SJiaqing Zhao                 boost::system::linux_error::bad_request_descriptor)
56290d2d1e8SJiaqing Zhao             {
563828252d5SJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "Certificate", id);
5645968caeeSMarri Devender Rao                 return;
5655968caeeSMarri Devender Rao             }
56690d2d1e8SJiaqing Zhao             messages::internalError(asyncResp->res);
56790d2d1e8SJiaqing Zhao             return;
56890d2d1e8SJiaqing Zhao         }
569828252d5SJiaqing Zhao         getCertificateProperties(asyncResp, objectPath, service, id, url, name);
5705968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
5715968caeeSMarri Devender Rao                          << certFile->getCertFilePath();
5725968caeeSMarri Devender Rao         },
5735968caeeSMarri Devender Rao         service, objectPath, certs::certReplaceIntf, "Replace",
5745968caeeSMarri Devender Rao         certFile->getCertFilePath());
575828252d5SJiaqing Zhao }
5765968caeeSMarri Devender Rao 
577cf9e417dSEd Tanous // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
578828252d5SJiaqing Zhao static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
5795968caeeSMarri Devender Rao /**
580828252d5SJiaqing Zhao  * @brief Read data from CSR D-bus object and set to response
581828252d5SJiaqing Zhao  *
582828252d5SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
583828252d5SJiaqing Zhao  * @param[in] certURI Link to certifiate collection URI
584828252d5SJiaqing Zhao  * @param[in] service D-Bus service name
585828252d5SJiaqing Zhao  * @param[in] certObjPath certificate D-Bus object path
586828252d5SJiaqing Zhao  * @param[in] csrObjPath CSR D-Bus object path
587828252d5SJiaqing Zhao  * @return None
5885968caeeSMarri Devender Rao  */
589828252d5SJiaqing Zhao static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
590828252d5SJiaqing Zhao                    const std::string& certURI, const std::string& service,
591828252d5SJiaqing Zhao                    const std::string& certObjPath,
592828252d5SJiaqing Zhao                    const std::string& csrObjPath)
5935968caeeSMarri Devender Rao {
594828252d5SJiaqing Zhao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
595828252d5SJiaqing Zhao                      << " CSRObjectPath=" << csrObjPath
596828252d5SJiaqing Zhao                      << " service=" << service;
597828252d5SJiaqing Zhao     crow::connections::systemBus->async_method_call(
598828252d5SJiaqing Zhao         [asyncResp, certURI](const boost::system::error_code ec,
599828252d5SJiaqing Zhao                              const std::string& csr) {
600828252d5SJiaqing Zhao         if (ec)
601828252d5SJiaqing Zhao         {
602828252d5SJiaqing Zhao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
603828252d5SJiaqing Zhao             messages::internalError(asyncResp->res);
604828252d5SJiaqing Zhao             return;
605828252d5SJiaqing Zhao         }
606828252d5SJiaqing Zhao         if (csr.empty())
607828252d5SJiaqing Zhao         {
608828252d5SJiaqing Zhao             BMCWEB_LOG_ERROR << "CSR read is empty";
609828252d5SJiaqing Zhao             messages::internalError(asyncResp->res);
610828252d5SJiaqing Zhao             return;
611828252d5SJiaqing Zhao         }
612828252d5SJiaqing Zhao         asyncResp->res.jsonValue["CSRString"] = csr;
613828252d5SJiaqing Zhao         asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
614828252d5SJiaqing Zhao             certURI;
615828252d5SJiaqing Zhao         },
616828252d5SJiaqing Zhao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
617828252d5SJiaqing Zhao }
618828252d5SJiaqing Zhao 
619828252d5SJiaqing Zhao inline void
620828252d5SJiaqing Zhao     handleGenerateCSRAction(App& app, const crow::Request& req,
621828252d5SJiaqing Zhao                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
622828252d5SJiaqing Zhao {
6233ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
62445ca1b86SEd Tanous     {
62545ca1b86SEd Tanous         return;
62645ca1b86SEd Tanous     }
627828252d5SJiaqing Zhao     static const int rsaKeyBitLength = 2048;
6285968caeeSMarri Devender Rao 
629828252d5SJiaqing Zhao     // Required parameters
630828252d5SJiaqing Zhao     std::string city;
631828252d5SJiaqing Zhao     std::string commonName;
632828252d5SJiaqing Zhao     std::string country;
633828252d5SJiaqing Zhao     std::string organization;
634828252d5SJiaqing Zhao     std::string organizationalUnit;
635828252d5SJiaqing Zhao     std::string state;
636828252d5SJiaqing Zhao     nlohmann::json certificateCollection;
637828252d5SJiaqing Zhao 
638828252d5SJiaqing Zhao     // Optional parameters
639828252d5SJiaqing Zhao     std::optional<std::vector<std::string>> optAlternativeNames =
640828252d5SJiaqing Zhao         std::vector<std::string>();
641828252d5SJiaqing Zhao     std::optional<std::string> optContactPerson = "";
642828252d5SJiaqing Zhao     std::optional<std::string> optChallengePassword = "";
643828252d5SJiaqing Zhao     std::optional<std::string> optEmail = "";
644828252d5SJiaqing Zhao     std::optional<std::string> optGivenName = "";
645828252d5SJiaqing Zhao     std::optional<std::string> optInitials = "";
646828252d5SJiaqing Zhao     std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
647828252d5SJiaqing Zhao     std::optional<std::string> optKeyCurveId = "secp384r1";
648828252d5SJiaqing Zhao     std::optional<std::string> optKeyPairAlgorithm = "EC";
649828252d5SJiaqing Zhao     std::optional<std::vector<std::string>> optKeyUsage =
650828252d5SJiaqing Zhao         std::vector<std::string>();
651828252d5SJiaqing Zhao     std::optional<std::string> optSurname = "";
652828252d5SJiaqing Zhao     std::optional<std::string> optUnstructuredName = "";
653828252d5SJiaqing Zhao     if (!json_util::readJsonAction(
654828252d5SJiaqing Zhao             req, asyncResp->res, "City", city, "CommonName", commonName,
655828252d5SJiaqing Zhao             "ContactPerson", optContactPerson, "Country", country,
656828252d5SJiaqing Zhao             "Organization", organization, "OrganizationalUnit",
657828252d5SJiaqing Zhao             organizationalUnit, "State", state, "CertificateCollection",
658828252d5SJiaqing Zhao             certificateCollection, "AlternativeNames", optAlternativeNames,
659828252d5SJiaqing Zhao             "ChallengePassword", optChallengePassword, "Email", optEmail,
660828252d5SJiaqing Zhao             "GivenName", optGivenName, "Initials", optInitials, "KeyBitLength",
661828252d5SJiaqing Zhao             optKeyBitLength, "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm",
662828252d5SJiaqing Zhao             optKeyPairAlgorithm, "KeyUsage", optKeyUsage, "Surname", optSurname,
663828252d5SJiaqing Zhao             "UnstructuredName", optUnstructuredName))
664828252d5SJiaqing Zhao     {
665828252d5SJiaqing Zhao         return;
6665968caeeSMarri Devender Rao     }
6675968caeeSMarri Devender Rao 
668828252d5SJiaqing Zhao     // bmcweb has no way to store or decode a private key challenge
669828252d5SJiaqing Zhao     // password, which will likely cause bmcweb to crash on startup
670828252d5SJiaqing Zhao     // if this is not set on a post so not allowing the user to set
671828252d5SJiaqing Zhao     // value
672828252d5SJiaqing Zhao     if (!optChallengePassword->empty())
6735968caeeSMarri Devender Rao     {
674828252d5SJiaqing Zhao         messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
675828252d5SJiaqing Zhao                                               "ChallengePassword");
676828252d5SJiaqing Zhao         return;
677828252d5SJiaqing Zhao     }
678828252d5SJiaqing Zhao 
679828252d5SJiaqing Zhao     std::string certURI;
680828252d5SJiaqing Zhao     if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
681828252d5SJiaqing Zhao                                       "@odata.id", certURI))
682828252d5SJiaqing Zhao     {
683828252d5SJiaqing Zhao         return;
684828252d5SJiaqing Zhao     }
685828252d5SJiaqing Zhao 
686828252d5SJiaqing Zhao     std::string objectPath;
687828252d5SJiaqing Zhao     std::string service;
688828252d5SJiaqing Zhao     if (certURI.starts_with(
689828252d5SJiaqing Zhao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
690828252d5SJiaqing Zhao     {
691828252d5SJiaqing Zhao         objectPath = certs::httpsObjectPath;
692828252d5SJiaqing Zhao         service = certs::httpsServiceName;
693828252d5SJiaqing Zhao     }
694828252d5SJiaqing Zhao     else if (certURI.starts_with(
695828252d5SJiaqing Zhao                  "/redfish/v1/AccountService/LDAP/Certificates"))
696828252d5SJiaqing Zhao     {
697828252d5SJiaqing Zhao         objectPath = certs::ldapObjectPath;
698828252d5SJiaqing Zhao         service = certs::ldapServiceName;
699828252d5SJiaqing Zhao     }
700828252d5SJiaqing Zhao     else
701828252d5SJiaqing Zhao     {
702828252d5SJiaqing Zhao         messages::actionParameterNotSupported(
703828252d5SJiaqing Zhao             asyncResp->res, "CertificateCollection", "GenerateCSR");
704828252d5SJiaqing Zhao         return;
705828252d5SJiaqing Zhao     }
706828252d5SJiaqing Zhao 
707828252d5SJiaqing Zhao     // supporting only EC and RSA algorithm
708828252d5SJiaqing Zhao     if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
709828252d5SJiaqing Zhao     {
710828252d5SJiaqing Zhao         messages::actionParameterNotSupported(
711828252d5SJiaqing Zhao             asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
712828252d5SJiaqing Zhao         return;
713828252d5SJiaqing Zhao     }
714828252d5SJiaqing Zhao 
715828252d5SJiaqing Zhao     // supporting only 2048 key bit length for RSA algorithm due to
716828252d5SJiaqing Zhao     // time consumed in generating private key
717828252d5SJiaqing Zhao     if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength)
718828252d5SJiaqing Zhao     {
719828252d5SJiaqing Zhao         messages::propertyValueNotInList(
720828252d5SJiaqing Zhao             asyncResp->res, std::to_string(*optKeyBitLength), "KeyBitLength");
721828252d5SJiaqing Zhao         return;
722828252d5SJiaqing Zhao     }
723828252d5SJiaqing Zhao 
724828252d5SJiaqing Zhao     // validate KeyUsage supporting only 1 type based on URL
725828252d5SJiaqing Zhao     if (certURI.starts_with(
726828252d5SJiaqing Zhao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
727828252d5SJiaqing Zhao     {
728828252d5SJiaqing Zhao         if (optKeyUsage->empty())
729828252d5SJiaqing Zhao         {
730828252d5SJiaqing Zhao             optKeyUsage->push_back("ServerAuthentication");
731828252d5SJiaqing Zhao         }
732828252d5SJiaqing Zhao         else if (optKeyUsage->size() == 1)
733828252d5SJiaqing Zhao         {
734828252d5SJiaqing Zhao             if ((*optKeyUsage)[0] != "ServerAuthentication")
735828252d5SJiaqing Zhao             {
736828252d5SJiaqing Zhao                 messages::propertyValueNotInList(asyncResp->res,
737828252d5SJiaqing Zhao                                                  (*optKeyUsage)[0], "KeyUsage");
738828252d5SJiaqing Zhao                 return;
739828252d5SJiaqing Zhao             }
740828252d5SJiaqing Zhao         }
741828252d5SJiaqing Zhao         else
742828252d5SJiaqing Zhao         {
743828252d5SJiaqing Zhao             messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
744828252d5SJiaqing Zhao                                                   "GenerateCSR");
745828252d5SJiaqing Zhao             return;
746828252d5SJiaqing Zhao         }
747828252d5SJiaqing Zhao     }
748828252d5SJiaqing Zhao     else if (certURI.starts_with(
749828252d5SJiaqing Zhao                  "/redfish/v1/AccountService/LDAP/Certificates"))
750828252d5SJiaqing Zhao     {
751828252d5SJiaqing Zhao         if (optKeyUsage->empty())
752828252d5SJiaqing Zhao         {
753828252d5SJiaqing Zhao             optKeyUsage->push_back("ClientAuthentication");
754828252d5SJiaqing Zhao         }
755828252d5SJiaqing Zhao         else if (optKeyUsage->size() == 1)
756828252d5SJiaqing Zhao         {
757828252d5SJiaqing Zhao             if ((*optKeyUsage)[0] != "ClientAuthentication")
758828252d5SJiaqing Zhao             {
759828252d5SJiaqing Zhao                 messages::propertyValueNotInList(asyncResp->res,
760828252d5SJiaqing Zhao                                                  (*optKeyUsage)[0], "KeyUsage");
761828252d5SJiaqing Zhao                 return;
762828252d5SJiaqing Zhao             }
763828252d5SJiaqing Zhao         }
764828252d5SJiaqing Zhao         else
765828252d5SJiaqing Zhao         {
766828252d5SJiaqing Zhao             messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
767828252d5SJiaqing Zhao                                                   "GenerateCSR");
768828252d5SJiaqing Zhao             return;
769828252d5SJiaqing Zhao         }
770828252d5SJiaqing Zhao     }
771828252d5SJiaqing Zhao 
772828252d5SJiaqing Zhao     // Only allow one CSR matcher at a time so setting retry
773828252d5SJiaqing Zhao     // time-out and timer expiry to 10 seconds for now.
774828252d5SJiaqing Zhao     static const int timeOut = 10;
775828252d5SJiaqing Zhao     if (csrMatcher)
776828252d5SJiaqing Zhao     {
777828252d5SJiaqing Zhao         messages::serviceTemporarilyUnavailable(asyncResp->res,
778828252d5SJiaqing Zhao                                                 std::to_string(timeOut));
779828252d5SJiaqing Zhao         return;
780828252d5SJiaqing Zhao     }
781828252d5SJiaqing Zhao 
782828252d5SJiaqing Zhao     // Make this static so it survives outside this method
783828252d5SJiaqing Zhao     static boost::asio::steady_timer timeout(*req.ioService);
784828252d5SJiaqing Zhao     timeout.expires_after(std::chrono::seconds(timeOut));
785828252d5SJiaqing Zhao     timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
786828252d5SJiaqing Zhao         csrMatcher = nullptr;
787828252d5SJiaqing Zhao         if (ec)
788828252d5SJiaqing Zhao         {
789828252d5SJiaqing Zhao             // operation_aborted is expected if timer is canceled
790828252d5SJiaqing Zhao             // before completion.
791828252d5SJiaqing Zhao             if (ec != boost::asio::error::operation_aborted)
792828252d5SJiaqing Zhao             {
793828252d5SJiaqing Zhao                 BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
794828252d5SJiaqing Zhao             }
795828252d5SJiaqing Zhao             return;
796828252d5SJiaqing Zhao         }
797828252d5SJiaqing Zhao         BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
798828252d5SJiaqing Zhao         messages::internalError(asyncResp->res);
799828252d5SJiaqing Zhao     });
800828252d5SJiaqing Zhao 
801828252d5SJiaqing Zhao     // create a matcher to wait on CSR object
802828252d5SJiaqing Zhao     BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
803828252d5SJiaqing Zhao     std::string match("type='signal',"
804828252d5SJiaqing Zhao                       "interface='org.freedesktop.DBus.ObjectManager',"
805828252d5SJiaqing Zhao                       "path='" +
806828252d5SJiaqing Zhao                       objectPath +
807828252d5SJiaqing Zhao                       "',"
808828252d5SJiaqing Zhao                       "member='InterfacesAdded'");
809828252d5SJiaqing Zhao     csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
810828252d5SJiaqing Zhao         *crow::connections::systemBus, match,
811828252d5SJiaqing Zhao         [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
812828252d5SJiaqing Zhao         timeout.cancel();
813828252d5SJiaqing Zhao         if (m.is_method_error())
814828252d5SJiaqing Zhao         {
815828252d5SJiaqing Zhao             BMCWEB_LOG_ERROR << "Dbus method error!!!";
816828252d5SJiaqing Zhao             messages::internalError(asyncResp->res);
817828252d5SJiaqing Zhao             return;
818828252d5SJiaqing Zhao         }
819828252d5SJiaqing Zhao 
820828252d5SJiaqing Zhao         dbus::utility::DBusInteracesMap interfacesProperties;
821828252d5SJiaqing Zhao 
822828252d5SJiaqing Zhao         sdbusplus::message::object_path csrObjectPath;
823828252d5SJiaqing Zhao         m.read(csrObjectPath, interfacesProperties);
824828252d5SJiaqing Zhao         BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
825828252d5SJiaqing Zhao         for (const auto& interface : interfacesProperties)
826828252d5SJiaqing Zhao         {
827828252d5SJiaqing Zhao             if (interface.first == "xyz.openbmc_project.Certs.CSR")
828828252d5SJiaqing Zhao             {
829828252d5SJiaqing Zhao                 getCSR(asyncResp, certURI, service, objectPath,
830828252d5SJiaqing Zhao                        csrObjectPath.str);
831828252d5SJiaqing Zhao                 break;
832828252d5SJiaqing Zhao             }
833828252d5SJiaqing Zhao         }
834828252d5SJiaqing Zhao         });
835828252d5SJiaqing Zhao     crow::connections::systemBus->async_method_call(
836828252d5SJiaqing Zhao         [asyncResp](const boost::system::error_code ec, const std::string&) {
837828252d5SJiaqing Zhao         if (ec)
838828252d5SJiaqing Zhao         {
839828252d5SJiaqing Zhao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
840828252d5SJiaqing Zhao             messages::internalError(asyncResp->res);
841828252d5SJiaqing Zhao             return;
842828252d5SJiaqing Zhao         }
843828252d5SJiaqing Zhao         },
844828252d5SJiaqing Zhao         service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
845828252d5SJiaqing Zhao         "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
846828252d5SJiaqing Zhao         commonName, *optContactPerson, country, *optEmail, *optGivenName,
847828252d5SJiaqing Zhao         *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm,
848828252d5SJiaqing Zhao         *optKeyUsage, organization, organizationalUnit, state, *optSurname,
849828252d5SJiaqing Zhao         *optUnstructuredName);
850828252d5SJiaqing Zhao }
851828252d5SJiaqing Zhao 
852828252d5SJiaqing Zhao inline void requestRoutesCertificateService(App& app)
853828252d5SJiaqing Zhao {
854828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
855828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificateService)
856002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
857828252d5SJiaqing Zhao             std::bind_front(handleCertificateServiceGet, std::ref(app)));
858828252d5SJiaqing Zhao 
859828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
860828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificateLocations)
861828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
862828252d5SJiaqing Zhao             std::bind_front(handleCertificateLocationsGet, std::ref(app)));
863828252d5SJiaqing Zhao 
864828252d5SJiaqing Zhao     BMCWEB_ROUTE(
865828252d5SJiaqing Zhao         app,
866828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
867828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateService)
868828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(
869828252d5SJiaqing Zhao             std::bind_front(handleReplaceCertificateAction, std::ref(app)));
870828252d5SJiaqing Zhao 
871828252d5SJiaqing Zhao     BMCWEB_ROUTE(
872828252d5SJiaqing Zhao         app,
873828252d5SJiaqing Zhao         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
874828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateService)
875828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(
876828252d5SJiaqing Zhao             std::bind_front(handleGenerateCSRAction, std::ref(app)));
877828252d5SJiaqing Zhao } // requestRoutesCertificateService
878828252d5SJiaqing Zhao 
879828252d5SJiaqing Zhao inline void handleHTTPSCertificateCollectionGet(
880828252d5SJiaqing Zhao     App& app, const crow::Request& req,
881828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
882828252d5SJiaqing Zhao {
8833ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
88445ca1b86SEd Tanous     {
88545ca1b86SEd Tanous         return;
88645ca1b86SEd Tanous     }
8871476687dSEd Tanous 
8881476687dSEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
8891476687dSEd Tanous         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
8901476687dSEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
8911476687dSEd Tanous         "#CertificateCollection.CertificateCollection";
8921476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
8931476687dSEd Tanous     asyncResp->res.jsonValue["Description"] =
8941476687dSEd Tanous         "A Collection of HTTPS certificate instances";
8958d1b46d7Szhanghch05 
896d3f92ce7SJiaqing Zhao     getCertificateList(asyncResp, certs::httpsObjectPath,
897d3f92ce7SJiaqing Zhao                        "/Members"_json_pointer,
898d3f92ce7SJiaqing Zhao                        "/Members@odata.count"_json_pointer);
899828252d5SJiaqing Zhao }
9005968caeeSMarri Devender Rao 
901828252d5SJiaqing Zhao inline void handleHTTPSCertificateCollectionPost(
902828252d5SJiaqing Zhao     App& app, const crow::Request& req,
903828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
904828252d5SJiaqing Zhao {
9053ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
90645ca1b86SEd Tanous     {
90745ca1b86SEd Tanous         return;
90845ca1b86SEd Tanous     }
9095968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
9108d1b46d7Szhanghch05 
9111476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
9121476687dSEd Tanous     asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
9135968caeeSMarri Devender Rao 
914002d39b4SEd Tanous     std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
91558eb238fSKowalski, Kamil 
91658eb238fSKowalski, Kamil     if (certFileBody.empty())
91758eb238fSKowalski, Kamil     {
9180fda0f12SGeorge Liu         BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
919a08752f5SZbigniew Kurzynski         messages::unrecognizedRequestBody(asyncResp->res);
92058eb238fSKowalski, Kamil         return;
92158eb238fSKowalski, Kamil     }
92258eb238fSKowalski, Kamil 
9235968caeeSMarri Devender Rao     std::shared_ptr<CertificateFile> certFile =
92458eb238fSKowalski, Kamil         std::make_shared<CertificateFile>(certFileBody);
9255968caeeSMarri Devender Rao 
9265968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
927656ec7e3SZbigniew Kurzynski         [asyncResp, certFile](const boost::system::error_code ec,
928656ec7e3SZbigniew Kurzynski                               const std::string& objectPath) {
9295968caeeSMarri Devender Rao         if (ec)
9305968caeeSMarri Devender Rao         {
9315968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
9325968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
9335968caeeSMarri Devender Rao             return;
9345968caeeSMarri Devender Rao         }
935717b9802SJiaqing Zhao 
936717b9802SJiaqing Zhao         sdbusplus::message::object_path path(objectPath);
937717b9802SJiaqing Zhao         std::string certId = path.filename();
9381e312598SJiaqing Zhao         const boost::urls::url certURL = crow::utility::urlFromPieces(
9391e312598SJiaqing Zhao             "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
9401e312598SJiaqing Zhao             "Certificates", certId);
941828252d5SJiaqing Zhao         getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
942828252d5SJiaqing Zhao                                  certId, certURL, "HTTPS Certificate");
9435968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9445968caeeSMarri Devender Rao                          << certFile->getCertFilePath();
9455968caeeSMarri Devender Rao         },
946828252d5SJiaqing Zhao         certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
947828252d5SJiaqing Zhao         "Install", certFile->getCertFilePath());
948828252d5SJiaqing Zhao }
9495968caeeSMarri Devender Rao 
950828252d5SJiaqing Zhao inline void handleHTTPSCertificateGet(
951828252d5SJiaqing Zhao     App& app, const crow::Request& req,
952828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
9537e860f15SJohn Edward Broadbent {
9543ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
95545ca1b86SEd Tanous     {
95645ca1b86SEd Tanous         return;
95745ca1b86SEd Tanous     }
9587e860f15SJohn Edward Broadbent 
959828252d5SJiaqing Zhao     BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
960828252d5SJiaqing Zhao     const boost::urls::url certURL = crow::utility::urlFromPieces(
961828252d5SJiaqing Zhao         "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
962828252d5SJiaqing Zhao         "Certificates", id);
963828252d5SJiaqing Zhao     std::string objPath =
964828252d5SJiaqing Zhao         sdbusplus::message::object_path(certs::httpsObjectPath) / id;
965828252d5SJiaqing Zhao     getCertificateProperties(asyncResp, objPath, certs::httpsServiceName, id,
966828252d5SJiaqing Zhao                              certURL, "HTTPS Certificate");
9677e860f15SJohn Edward Broadbent }
96837cce918SMarri Devender Rao 
969828252d5SJiaqing Zhao inline void requestRoutesHTTPSCertificate(App& app)
97037cce918SMarri Devender Rao {
971828252d5SJiaqing Zhao     BMCWEB_ROUTE(app,
972828252d5SJiaqing Zhao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
973ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
974828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(std::bind_front(
975828252d5SJiaqing Zhao             handleHTTPSCertificateCollectionGet, std::ref(app)));
976828252d5SJiaqing Zhao 
977828252d5SJiaqing Zhao     BMCWEB_ROUTE(app,
978828252d5SJiaqing Zhao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
979828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateCollection)
980828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(std::bind_front(
981828252d5SJiaqing Zhao             handleHTTPSCertificateCollectionPost, std::ref(app)));
982828252d5SJiaqing Zhao 
983828252d5SJiaqing Zhao     BMCWEB_ROUTE(
984828252d5SJiaqing Zhao         app,
985828252d5SJiaqing Zhao         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
986828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificate)
987002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
988828252d5SJiaqing Zhao             std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
989828252d5SJiaqing Zhao }
990828252d5SJiaqing Zhao 
991828252d5SJiaqing Zhao inline void handleLDAPCertificateCollectionGet(
992828252d5SJiaqing Zhao     App& app, const crow::Request& req,
993828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
994828252d5SJiaqing Zhao {
9953ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
99645ca1b86SEd Tanous     {
99745ca1b86SEd Tanous         return;
99845ca1b86SEd Tanous     }
9991476687dSEd Tanous 
10001476687dSEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
10011476687dSEd Tanous         "/redfish/v1/AccountService/LDAP/Certificates";
10021476687dSEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
10031476687dSEd Tanous         "#CertificateCollection.CertificateCollection";
10041476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
10051476687dSEd Tanous     asyncResp->res.jsonValue["Description"] =
10061476687dSEd Tanous         "A Collection of LDAP certificate instances";
10078d1b46d7Szhanghch05 
1008d3f92ce7SJiaqing Zhao     getCertificateList(asyncResp, certs::ldapObjectPath,
1009d3f92ce7SJiaqing Zhao                        "/Members"_json_pointer,
1010d3f92ce7SJiaqing Zhao                        "/Members@odata.count"_json_pointer);
1011828252d5SJiaqing Zhao }
101237cce918SMarri Devender Rao 
1013828252d5SJiaqing Zhao inline void handleLDAPCertificateCollectionPost(
1014828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1015828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1016828252d5SJiaqing Zhao {
10173ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
101845ca1b86SEd Tanous     {
101945ca1b86SEd Tanous         return;
102045ca1b86SEd Tanous     }
1021002d39b4SEd Tanous     std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
102258eb238fSKowalski, Kamil 
102358eb238fSKowalski, Kamil     if (certFileBody.empty())
102458eb238fSKowalski, Kamil     {
1025002d39b4SEd Tanous         BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1026a08752f5SZbigniew Kurzynski         messages::unrecognizedRequestBody(asyncResp->res);
102758eb238fSKowalski, Kamil         return;
102858eb238fSKowalski, Kamil     }
102958eb238fSKowalski, Kamil 
103058eb238fSKowalski, Kamil     std::shared_ptr<CertificateFile> certFile =
103158eb238fSKowalski, Kamil         std::make_shared<CertificateFile>(certFileBody);
103258eb238fSKowalski, Kamil 
103337cce918SMarri Devender Rao     crow::connections::systemBus->async_method_call(
1034656ec7e3SZbigniew Kurzynski         [asyncResp, certFile](const boost::system::error_code ec,
1035656ec7e3SZbigniew Kurzynski                               const std::string& objectPath) {
103637cce918SMarri Devender Rao         if (ec)
103737cce918SMarri Devender Rao         {
103837cce918SMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
103937cce918SMarri Devender Rao             messages::internalError(asyncResp->res);
104037cce918SMarri Devender Rao             return;
104137cce918SMarri Devender Rao         }
1042717b9802SJiaqing Zhao 
1043717b9802SJiaqing Zhao         sdbusplus::message::object_path path(objectPath);
1044717b9802SJiaqing Zhao         std::string certId = path.filename();
1045828252d5SJiaqing Zhao         const boost::urls::url certURL = crow::utility::urlFromPieces(
1046828252d5SJiaqing Zhao             "redfish", "v1", "AccountService", "LDAP", "Certificates", certId);
1047828252d5SJiaqing Zhao         getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
1048828252d5SJiaqing Zhao                                  certId, certURL, "LDAP Certificate");
104937cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "LDAP certificate install file="
105037cce918SMarri Devender Rao                          << certFile->getCertFilePath();
105137cce918SMarri Devender Rao         },
1052828252d5SJiaqing Zhao         certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
1053828252d5SJiaqing Zhao         "Install", certFile->getCertFilePath());
1054828252d5SJiaqing Zhao }
105537cce918SMarri Devender Rao 
1056828252d5SJiaqing Zhao inline void handleLDAPCertificateGet(
1057828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1058828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
105937cce918SMarri Devender Rao {
10603ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
106145ca1b86SEd Tanous     {
106245ca1b86SEd Tanous         return;
106345ca1b86SEd Tanous     }
1064717b9802SJiaqing Zhao 
1065717b9802SJiaqing Zhao     BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
10661e312598SJiaqing Zhao     const boost::urls::url certURL = crow::utility::urlFromPieces(
10671e312598SJiaqing Zhao         "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
1068717b9802SJiaqing Zhao     std::string objPath =
1069717b9802SJiaqing Zhao         sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1070717b9802SJiaqing Zhao     getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1071717b9802SJiaqing Zhao                              certURL, "LDAP Certificate");
1072828252d5SJiaqing Zhao }
1073828252d5SJiaqing Zhao 
107499612247SJiaqing Zhao inline void handleLDAPCertificateDelete(
107599612247SJiaqing Zhao     App& app, const crow::Request& req,
107699612247SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
107799612247SJiaqing Zhao {
107899612247SJiaqing Zhao     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
107999612247SJiaqing Zhao     {
108099612247SJiaqing Zhao         return;
108199612247SJiaqing Zhao     }
108299612247SJiaqing Zhao 
108399612247SJiaqing Zhao     BMCWEB_LOG_DEBUG << "Delete LDAP Certificate ID=" << id;
108499612247SJiaqing Zhao     std::string objPath =
108599612247SJiaqing Zhao         sdbusplus::message::object_path(certs::ldapObjectPath) / id;
108699612247SJiaqing Zhao 
108799612247SJiaqing Zhao     deleteCertificate(asyncResp, certs::ldapServiceName, objPath);
108899612247SJiaqing Zhao }
108999612247SJiaqing Zhao 
1090828252d5SJiaqing Zhao inline void requestRoutesLDAPCertificate(App& app)
1091cfcd5f6bSMarri Devender Rao {
1092828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1093828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificateCollection)
1094828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
1095828252d5SJiaqing Zhao             std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app)));
1096828252d5SJiaqing Zhao 
1097828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1098828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateCollection)
1099828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(std::bind_front(
1100828252d5SJiaqing Zhao             handleLDAPCertificateCollectionPost, std::ref(app)));
1101828252d5SJiaqing Zhao 
1102828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1103ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
1104002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1105828252d5SJiaqing Zhao             std::bind_front(handleLDAPCertificateGet, std::ref(app)));
110699612247SJiaqing Zhao 
110799612247SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
110899612247SJiaqing Zhao         .privileges(redfish::privileges::deleteCertificate)
110999612247SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
111099612247SJiaqing Zhao             std::bind_front(handleLDAPCertificateDelete, std::ref(app)));
1111828252d5SJiaqing Zhao } // requestRoutesLDAPCertificate
1112828252d5SJiaqing Zhao 
1113828252d5SJiaqing Zhao inline void handleTrustStoreCertificateCollectionGet(
1114828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1115828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1116828252d5SJiaqing Zhao {
11173ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
111845ca1b86SEd Tanous     {
111945ca1b86SEd Tanous         return;
112045ca1b86SEd Tanous     }
11211476687dSEd Tanous 
11221476687dSEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
11231476687dSEd Tanous         "/redfish/v1/Managers/bmc/Truststore/Certificates/";
11241476687dSEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
11251476687dSEd Tanous         "#CertificateCollection.CertificateCollection";
1126002d39b4SEd Tanous     asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
11271476687dSEd Tanous     asyncResp->res.jsonValue["Description"] =
11281476687dSEd Tanous         "A Collection of TrustStore certificate instances";
11298d1b46d7Szhanghch05 
1130d3f92ce7SJiaqing Zhao     getCertificateList(asyncResp, certs::authorityObjectPath,
1131d3f92ce7SJiaqing Zhao                        "/Members"_json_pointer,
1132d3f92ce7SJiaqing Zhao                        "/Members@odata.count"_json_pointer);
1133828252d5SJiaqing Zhao }
1134cfcd5f6bSMarri Devender Rao 
1135828252d5SJiaqing Zhao inline void handleTrustStoreCertificateCollectionPost(
1136828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1137828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1138828252d5SJiaqing Zhao {
11393ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
114045ca1b86SEd Tanous     {
114145ca1b86SEd Tanous         return;
114245ca1b86SEd Tanous     }
1143002d39b4SEd Tanous     std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
1144a08752f5SZbigniew Kurzynski 
1145a08752f5SZbigniew Kurzynski     if (certFileBody.empty())
1146a08752f5SZbigniew Kurzynski     {
11470fda0f12SGeorge Liu         BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1148a08752f5SZbigniew Kurzynski         messages::unrecognizedRequestBody(asyncResp->res);
1149a08752f5SZbigniew Kurzynski         return;
1150a08752f5SZbigniew Kurzynski     }
1151a08752f5SZbigniew Kurzynski 
1152a08752f5SZbigniew Kurzynski     std::shared_ptr<CertificateFile> certFile =
1153a08752f5SZbigniew Kurzynski         std::make_shared<CertificateFile>(certFileBody);
1154cfcd5f6bSMarri Devender Rao     crow::connections::systemBus->async_method_call(
1155656ec7e3SZbigniew Kurzynski         [asyncResp, certFile](const boost::system::error_code ec,
1156656ec7e3SZbigniew Kurzynski                               const std::string& objectPath) {
1157cfcd5f6bSMarri Devender Rao         if (ec)
1158cfcd5f6bSMarri Devender Rao         {
1159cfcd5f6bSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1160cfcd5f6bSMarri Devender Rao             messages::internalError(asyncResp->res);
1161cfcd5f6bSMarri Devender Rao             return;
1162cfcd5f6bSMarri Devender Rao         }
1163656ec7e3SZbigniew Kurzynski 
1164717b9802SJiaqing Zhao         sdbusplus::message::object_path path(objectPath);
1165717b9802SJiaqing Zhao         std::string certId = path.filename();
1166828252d5SJiaqing Zhao         const boost::urls::url certURL =
1167828252d5SJiaqing Zhao             crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
1168828252d5SJiaqing Zhao                                          "Truststore", "Certificates", certId);
1169717b9802SJiaqing Zhao         getCertificateProperties(asyncResp, objectPath,
1170828252d5SJiaqing Zhao                                  certs::authorityServiceName, certId, certURL,
1171828252d5SJiaqing Zhao                                  "TrustStore Certificate");
11720fda0f12SGeorge Liu         BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
1173cfcd5f6bSMarri Devender Rao                          << certFile->getCertFilePath();
1174cfcd5f6bSMarri Devender Rao         },
1175cfcd5f6bSMarri Devender Rao         certs::authorityServiceName, certs::authorityObjectPath,
11760fda0f12SGeorge Liu         certs::certInstallIntf, "Install", certFile->getCertFilePath());
1177828252d5SJiaqing Zhao }
1178cfcd5f6bSMarri Devender Rao 
1179828252d5SJiaqing Zhao inline void handleTrustStoreCertificateGet(
1180828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1181828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1182cfcd5f6bSMarri Devender Rao {
11833ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
118445ca1b86SEd Tanous     {
118545ca1b86SEd Tanous         return;
118645ca1b86SEd Tanous     }
1187717b9802SJiaqing Zhao 
1188717b9802SJiaqing Zhao     BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
1189828252d5SJiaqing Zhao     const boost::urls::url certURL = crow::utility::urlFromPieces(
1190828252d5SJiaqing Zhao         "redfish", "v1", "Managers", "bmc", "Truststore", "Certificates", id);
1191717b9802SJiaqing Zhao     std::string objPath =
1192717b9802SJiaqing Zhao         sdbusplus::message::object_path(certs::authorityObjectPath) / id;
1193828252d5SJiaqing Zhao     getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
1194828252d5SJiaqing Zhao                              id, certURL, "TrustStore Certificate");
1195828252d5SJiaqing Zhao }
119607a60299SZbigniew Kurzynski 
1197828252d5SJiaqing Zhao inline void handleTrustStoreCertificateDelete(
1198828252d5SJiaqing Zhao     App& app, const crow::Request& req,
1199828252d5SJiaqing Zhao     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1200828252d5SJiaqing Zhao {
12013ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
120245ca1b86SEd Tanous     {
120345ca1b86SEd Tanous         return;
120445ca1b86SEd Tanous     }
120507a60299SZbigniew Kurzynski 
1206717b9802SJiaqing Zhao     BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id;
1207717b9802SJiaqing Zhao     std::string objPath =
1208717b9802SJiaqing Zhao         sdbusplus::message::object_path(certs::authorityObjectPath) / id;
120907a60299SZbigniew Kurzynski 
12107a3a8f7aSJiaqing Zhao     deleteCertificate(asyncResp, certs::authorityServiceName, objPath);
1211828252d5SJiaqing Zhao }
1212828252d5SJiaqing Zhao 
1213828252d5SJiaqing Zhao inline void requestRoutesTrustStoreCertificate(App& app)
1214828252d5SJiaqing Zhao {
1215828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1216828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificate)
1217828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(std::bind_front(
1218828252d5SJiaqing Zhao             handleTrustStoreCertificateCollectionGet, std::ref(app)));
1219828252d5SJiaqing Zhao 
1220828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1221828252d5SJiaqing Zhao         .privileges(redfish::privileges::postCertificateCollection)
1222828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::post)(std::bind_front(
1223828252d5SJiaqing Zhao             handleTrustStoreCertificateCollectionPost, std::ref(app)));
1224828252d5SJiaqing Zhao 
1225828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1226828252d5SJiaqing Zhao         .privileges(redfish::privileges::getCertificate)
1227828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
1228828252d5SJiaqing Zhao             std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));
1229828252d5SJiaqing Zhao 
1230828252d5SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1231828252d5SJiaqing Zhao         .privileges(redfish::privileges::deleteCertificate)
1232828252d5SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
1233828252d5SJiaqing Zhao             std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));
12347e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
12355968caeeSMarri Devender Rao } // namespace redfish
1236