xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 3021581655861c74e8c0c71ce1ca49bb7b54f72d)
15968caeeSMarri Devender Rao /*
25968caeeSMarri Devender Rao // Copyright (c) 2018 IBM Corporation
35968caeeSMarri Devender Rao //
45968caeeSMarri Devender Rao // Licensed under the Apache License, Version 2.0 (the "License");
55968caeeSMarri Devender Rao // you may not use this file except in compliance with the License.
65968caeeSMarri Devender Rao // You may obtain a copy of the License at
75968caeeSMarri Devender Rao //
85968caeeSMarri Devender Rao //      http://www.apache.org/licenses/LICENSE-2.0
95968caeeSMarri Devender Rao //
105968caeeSMarri Devender Rao // Unless required by applicable law or agreed to in writing, software
115968caeeSMarri Devender Rao // distributed under the License is distributed on an "AS IS" BASIS,
125968caeeSMarri Devender Rao // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135968caeeSMarri Devender Rao // See the License for the specific language governing permissions and
145968caeeSMarri Devender Rao // limitations under the License.
155968caeeSMarri Devender Rao */
165968caeeSMarri Devender Rao #pragma once
175968caeeSMarri Devender Rao 
185968caeeSMarri Devender Rao #include "node.hpp"
195968caeeSMarri Devender Rao 
205968caeeSMarri Devender Rao #include <variant>
215968caeeSMarri Devender Rao namespace redfish
225968caeeSMarri Devender Rao {
235968caeeSMarri Devender Rao namespace certs
245968caeeSMarri Devender Rao {
255968caeeSMarri Devender Rao constexpr char const *httpsObjectPath =
265968caeeSMarri Devender Rao     "/xyz/openbmc_project/certs/server/https";
275968caeeSMarri Devender Rao constexpr char const *certInstallIntf = "xyz.openbmc_project.Certs.Install";
285968caeeSMarri Devender Rao constexpr char const *certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
295968caeeSMarri Devender Rao constexpr char const *certPropIntf = "xyz.openbmc_project.Certs.Certificate";
305968caeeSMarri Devender Rao constexpr char const *dbusPropIntf = "org.freedesktop.DBus.Properties";
315968caeeSMarri Devender Rao constexpr char const *dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
3237cce918SMarri Devender Rao constexpr char const *ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
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";
375968caeeSMarri Devender Rao } // namespace certs
385968caeeSMarri Devender Rao 
395968caeeSMarri Devender Rao /**
405968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
415968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
425968caeeSMarri Devender Rao  * are installed.
435968caeeSMarri Devender Rao  */
445968caeeSMarri Devender Rao class CertificateService : public Node
455968caeeSMarri Devender Rao {
465968caeeSMarri Devender Rao   public:
475968caeeSMarri Devender Rao     CertificateService(CrowApp &app) :
485968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/")
495968caeeSMarri Devender Rao     {
505968caeeSMarri Devender Rao         // TODO: Issue#61 No entries are available for Certificate
515968caeeSMarri Devender Rao         // sevice at https://www.dmtf.org/standards/redfish
525968caeeSMarri Devender Rao         // "redfish standard registries". Need to modify after DMTF
535968caeeSMarri Devender Rao         // publish Privilege details for certificate service
545968caeeSMarri Devender Rao         entityPrivileges = {
555968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
565968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
575968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
585968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
595968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
605968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
615968caeeSMarri Devender Rao     }
625968caeeSMarri Devender Rao 
635968caeeSMarri Devender Rao   private:
645968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
655968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
665968caeeSMarri Devender Rao     {
675968caeeSMarri Devender Rao         res.jsonValue = {
685968caeeSMarri Devender Rao             {"@odata.type", "#CertificateService.v1_0_0.CertificateService"},
695968caeeSMarri Devender Rao             {"@odata.id", "/redfish/v1/CertificateService"},
705968caeeSMarri Devender Rao             {"@odata.context",
715968caeeSMarri Devender Rao              "/redfish/v1/$metadata#CertificateService.CertificateService"},
725968caeeSMarri Devender Rao             {"Id", "CertificateService"},
735968caeeSMarri Devender Rao             {"Name", "Certificate Service"},
745968caeeSMarri Devender Rao             {"Description", "Actions available to manage certificates"}};
755968caeeSMarri Devender Rao         res.jsonValue["CertificateLocations"] = {
765968caeeSMarri Devender Rao             {"@odata.id",
775968caeeSMarri Devender Rao              "/redfish/v1/CertificateService/CertificateLocations"}};
785968caeeSMarri Devender Rao         res.jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
795968caeeSMarri Devender Rao             {"target", "/redfish/v1/CertificateService/Actions/"
805968caeeSMarri Devender Rao                        "CertificateService.ReplaceCertificate"},
815968caeeSMarri Devender Rao             {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
82*30215816SMarri Devender Rao         res.jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
83*30215816SMarri Devender Rao             {"target", "/redfish/v1/CertificateService/Actions/"
84*30215816SMarri Devender Rao                        "CertificateService.GenerateCSR"}};
855968caeeSMarri Devender Rao         res.end();
865968caeeSMarri Devender Rao     }
875968caeeSMarri Devender Rao }; // CertificateService
8837cce918SMarri Devender Rao 
895968caeeSMarri Devender Rao /**
905968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
915968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
925968caeeSMarri Devender Rao  * @param[in] path URL
935968caeeSMarri Devender Rao  * @return -1 on failure and number on success
945968caeeSMarri Devender Rao  */
955968caeeSMarri Devender Rao long getIDFromURL(const std::string_view url)
965968caeeSMarri Devender Rao {
975968caeeSMarri Devender Rao     std::size_t found = url.rfind("/");
985968caeeSMarri Devender Rao     if (found == std::string::npos)
995968caeeSMarri Devender Rao     {
1005968caeeSMarri Devender Rao         return -1;
1015968caeeSMarri Devender Rao     }
1025968caeeSMarri Devender Rao     if ((found + 1) < url.length())
1035968caeeSMarri Devender Rao     {
1045968caeeSMarri Devender Rao         char *endPtr;
1055968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
1065968caeeSMarri Devender Rao         long value = std::strtol(str.data(), &endPtr, 10);
10737cce918SMarri Devender Rao         if (endPtr != str.end())
1085968caeeSMarri Devender Rao         {
1095968caeeSMarri Devender Rao             return -1;
1105968caeeSMarri Devender Rao         }
1115968caeeSMarri Devender Rao         return value;
1125968caeeSMarri Devender Rao     }
1135968caeeSMarri Devender Rao     return -1;
1145968caeeSMarri Devender Rao }
1155968caeeSMarri Devender Rao 
1165968caeeSMarri Devender Rao /**
1175968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1185968caeeSMarri Devender Rao  */
1195968caeeSMarri Devender Rao class CertificateFile
1205968caeeSMarri Devender Rao {
1215968caeeSMarri Devender Rao   public:
1225968caeeSMarri Devender Rao     CertificateFile() = delete;
1235968caeeSMarri Devender Rao     CertificateFile(const CertificateFile &) = delete;
1245968caeeSMarri Devender Rao     CertificateFile &operator=(const CertificateFile &) = delete;
1255968caeeSMarri Devender Rao     CertificateFile(CertificateFile &&) = delete;
1265968caeeSMarri Devender Rao     CertificateFile &operator=(CertificateFile &&) = delete;
1275968caeeSMarri Devender Rao     CertificateFile(const std::string &certString)
1285968caeeSMarri Devender Rao     {
1295968caeeSMarri Devender Rao         char dirTemplate[] = "/tmp/Certs.XXXXXX";
1305968caeeSMarri Devender Rao         char *tempDirectory = mkdtemp(dirTemplate);
1315968caeeSMarri Devender Rao         if (tempDirectory)
1325968caeeSMarri Devender Rao         {
1335968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1345968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1355968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1365968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1375968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1385968caeeSMarri Devender Rao             out << certString;
1395968caeeSMarri Devender Rao             out.close();
1405968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile;
1415968caeeSMarri Devender Rao         }
1425968caeeSMarri Devender Rao     }
1435968caeeSMarri Devender Rao     ~CertificateFile()
1445968caeeSMarri Devender Rao     {
1455968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1465968caeeSMarri Devender Rao         {
1475968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile;
1485968caeeSMarri Devender Rao             try
1495968caeeSMarri Devender Rao             {
1505968caeeSMarri Devender Rao                 std::filesystem::remove_all(certDirectory);
1515968caeeSMarri Devender Rao             }
1525968caeeSMarri Devender Rao             catch (const std::filesystem::filesystem_error &e)
1535968caeeSMarri Devender Rao             {
1545968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1555968caeeSMarri Devender Rao                                  << certDirectory;
1565968caeeSMarri Devender Rao             }
1575968caeeSMarri Devender Rao         }
1585968caeeSMarri Devender Rao     }
1595968caeeSMarri Devender Rao     std::string getCertFilePath()
1605968caeeSMarri Devender Rao     {
1615968caeeSMarri Devender Rao         return certificateFile;
1625968caeeSMarri Devender Rao     }
1635968caeeSMarri Devender Rao 
1645968caeeSMarri Devender Rao   private:
1655968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1665968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1675968caeeSMarri Devender Rao };
1685968caeeSMarri Devender Rao 
169*30215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher;
170*30215816SMarri Devender Rao /**
171*30215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
172*30215816SMarri Devender Rao  *
173*30215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
174*30215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
175*30215816SMarri Devender Rao  * @param[in] service D-Bus service name
176*30215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
177*30215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
178*30215816SMarri Devender Rao  * @return None
179*30215816SMarri Devender Rao  */
180*30215816SMarri Devender Rao static void getCSR(const std::shared_ptr<AsyncResp> &asyncResp,
181*30215816SMarri Devender Rao                    const std::string &certURI, const std::string &service,
182*30215816SMarri Devender Rao                    const std::string &certObjPath,
183*30215816SMarri Devender Rao                    const std::string &csrObjPath)
184*30215816SMarri Devender Rao {
185*30215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
186*30215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
187*30215816SMarri Devender Rao                      << " service=" << service;
188*30215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
189*30215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
190*30215816SMarri Devender Rao                              const std::string &csr) {
191*30215816SMarri Devender Rao             if (ec)
192*30215816SMarri Devender Rao             {
193*30215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
194*30215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
195*30215816SMarri Devender Rao                 return;
196*30215816SMarri Devender Rao             }
197*30215816SMarri Devender Rao             if (csr.empty())
198*30215816SMarri Devender Rao             {
199*30215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "CSR read is empty";
200*30215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
201*30215816SMarri Devender Rao                 return;
202*30215816SMarri Devender Rao             }
203*30215816SMarri Devender Rao             asyncResp->res.jsonValue["CSRString"] = csr;
204*30215816SMarri Devender Rao             asyncResp->res.jsonValue["CertificateCollection"] = {
205*30215816SMarri Devender Rao                 {"@odata.id", certURI}};
206*30215816SMarri Devender Rao         },
207*30215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
208*30215816SMarri Devender Rao }
209*30215816SMarri Devender Rao 
210*30215816SMarri Devender Rao /**
211*30215816SMarri Devender Rao  * Action to Generate CSR
212*30215816SMarri Devender Rao  */
213*30215816SMarri Devender Rao class CertificateActionGenerateCSR : public Node
214*30215816SMarri Devender Rao {
215*30215816SMarri Devender Rao   public:
216*30215816SMarri Devender Rao     CertificateActionGenerateCSR(CrowApp &app) :
217*30215816SMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/Actions/"
218*30215816SMarri Devender Rao                   "CertificateService.GenerateCSR/")
219*30215816SMarri Devender Rao     {
220*30215816SMarri Devender Rao         entityPrivileges = {
221*30215816SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
222*30215816SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
223*30215816SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
224*30215816SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
225*30215816SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
226*30215816SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
227*30215816SMarri Devender Rao     }
228*30215816SMarri Devender Rao 
229*30215816SMarri Devender Rao   private:
230*30215816SMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
231*30215816SMarri Devender Rao                 const std::vector<std::string> &params) override
232*30215816SMarri Devender Rao     {
233*30215816SMarri Devender Rao         static const int RSA_KEY_BIT_LENGTH = 2048;
234*30215816SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
235*30215816SMarri Devender Rao         // Required parameters
236*30215816SMarri Devender Rao         std::string city;
237*30215816SMarri Devender Rao         std::string commonName;
238*30215816SMarri Devender Rao         std::string country;
239*30215816SMarri Devender Rao         std::string organization;
240*30215816SMarri Devender Rao         std::string organizationalUnit;
241*30215816SMarri Devender Rao         std::string state;
242*30215816SMarri Devender Rao         nlohmann::json certificateCollection;
243*30215816SMarri Devender Rao 
244*30215816SMarri Devender Rao         // Optional parameters
245*30215816SMarri Devender Rao         std::optional<std::vector<std::string>> optAlternativeNames =
246*30215816SMarri Devender Rao             std::vector<std::string>();
247*30215816SMarri Devender Rao         std::optional<std::string> optContactPerson = "";
248*30215816SMarri Devender Rao         std::optional<std::string> optChallengePassword = "";
249*30215816SMarri Devender Rao         std::optional<std::string> optEmail = "";
250*30215816SMarri Devender Rao         std::optional<std::string> optGivenName = "";
251*30215816SMarri Devender Rao         std::optional<std::string> optInitials = "";
252*30215816SMarri Devender Rao         std::optional<int64_t> optKeyBitLength = RSA_KEY_BIT_LENGTH;
253*30215816SMarri Devender Rao         std::optional<std::string> optKeyCurveId = "prime256v1";
254*30215816SMarri Devender Rao         std::optional<std::string> optKeyPairAlgorithm = "EC";
255*30215816SMarri Devender Rao         std::optional<std::vector<std::string>> optKeyUsage =
256*30215816SMarri Devender Rao             std::vector<std::string>();
257*30215816SMarri Devender Rao         std::optional<std::string> optSurname = "";
258*30215816SMarri Devender Rao         std::optional<std::string> optUnstructuredName = "";
259*30215816SMarri Devender Rao         if (!json_util::readJson(
260*30215816SMarri Devender Rao                 req, asyncResp->res, "City", city, "CommonName", commonName,
261*30215816SMarri Devender Rao                 "ContactPerson", optContactPerson, "Country", country,
262*30215816SMarri Devender Rao                 "Organization", organization, "OrganizationalUnit",
263*30215816SMarri Devender Rao                 organizationalUnit, "State", state, "CertificateCollection",
264*30215816SMarri Devender Rao                 certificateCollection, "AlternativeNames", optAlternativeNames,
265*30215816SMarri Devender Rao                 "ChallengePassword", optChallengePassword, "Email", optEmail,
266*30215816SMarri Devender Rao                 "GivenName", optGivenName, "Initials", optInitials,
267*30215816SMarri Devender Rao                 "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
268*30215816SMarri Devender Rao                 "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
269*30215816SMarri Devender Rao                 optKeyUsage, "Surname", optSurname, "UnstructuredName",
270*30215816SMarri Devender Rao                 optUnstructuredName))
271*30215816SMarri Devender Rao         {
272*30215816SMarri Devender Rao             return;
273*30215816SMarri Devender Rao         }
274*30215816SMarri Devender Rao 
275*30215816SMarri Devender Rao         // bmcweb has no way to store or decode a private key challenge
276*30215816SMarri Devender Rao         // password, which will likely cause bmcweb to crash on startup if this
277*30215816SMarri Devender Rao         // is not set on a post so not allowing the user to set value
278*30215816SMarri Devender Rao         if (*optChallengePassword != "")
279*30215816SMarri Devender Rao         {
280*30215816SMarri Devender Rao             messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
281*30215816SMarri Devender Rao                                                   "ChallengePassword");
282*30215816SMarri Devender Rao             return;
283*30215816SMarri Devender Rao         }
284*30215816SMarri Devender Rao 
285*30215816SMarri Devender Rao         std::string certURI;
286*30215816SMarri Devender Rao         if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
287*30215816SMarri Devender Rao                                           "@odata.id", certURI))
288*30215816SMarri Devender Rao         {
289*30215816SMarri Devender Rao             return;
290*30215816SMarri Devender Rao         }
291*30215816SMarri Devender Rao 
292*30215816SMarri Devender Rao         std::string objectPath;
293*30215816SMarri Devender Rao         std::string service;
294*30215816SMarri Devender Rao         if (boost::starts_with(
295*30215816SMarri Devender Rao                 certURI,
296*30215816SMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
297*30215816SMarri Devender Rao         {
298*30215816SMarri Devender Rao             objectPath = certs::httpsObjectPath;
299*30215816SMarri Devender Rao             service = certs::httpsServiceName;
300*30215816SMarri Devender Rao         }
301*30215816SMarri Devender Rao         else
302*30215816SMarri Devender Rao         {
303*30215816SMarri Devender Rao             messages::actionParameterNotSupported(
304*30215816SMarri Devender Rao                 asyncResp->res, "CertificateCollection", "GenerateCSR");
305*30215816SMarri Devender Rao             return;
306*30215816SMarri Devender Rao         }
307*30215816SMarri Devender Rao 
308*30215816SMarri Devender Rao         // supporting only EC and RSA algorithm
309*30215816SMarri Devender Rao         if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
310*30215816SMarri Devender Rao         {
311*30215816SMarri Devender Rao             messages::actionParameterNotSupported(
312*30215816SMarri Devender Rao                 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
313*30215816SMarri Devender Rao             return;
314*30215816SMarri Devender Rao         }
315*30215816SMarri Devender Rao 
316*30215816SMarri Devender Rao         // supporting only 2048 key bit length for RSA algorithm due to time
317*30215816SMarri Devender Rao         // consumed in generating private key
318*30215816SMarri Devender Rao         if (*optKeyPairAlgorithm == "RSA" &&
319*30215816SMarri Devender Rao             *optKeyBitLength != RSA_KEY_BIT_LENGTH)
320*30215816SMarri Devender Rao         {
321*30215816SMarri Devender Rao             messages::propertyValueNotInList(asyncResp->res,
322*30215816SMarri Devender Rao                                              std::to_string(*optKeyBitLength),
323*30215816SMarri Devender Rao                                              "KeyBitLength");
324*30215816SMarri Devender Rao             return;
325*30215816SMarri Devender Rao         }
326*30215816SMarri Devender Rao 
327*30215816SMarri Devender Rao         // validate KeyUsage supporting only 1 type based on URL
328*30215816SMarri Devender Rao         if (boost::starts_with(
329*30215816SMarri Devender Rao                 certURI,
330*30215816SMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
331*30215816SMarri Devender Rao         {
332*30215816SMarri Devender Rao             if (optKeyUsage->size() == 0)
333*30215816SMarri Devender Rao             {
334*30215816SMarri Devender Rao                 optKeyUsage->push_back("ServerAuthentication");
335*30215816SMarri Devender Rao             }
336*30215816SMarri Devender Rao             else if (optKeyUsage->size() == 1)
337*30215816SMarri Devender Rao             {
338*30215816SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ServerAuthentication")
339*30215816SMarri Devender Rao                 {
340*30215816SMarri Devender Rao                     messages::propertyValueNotInList(
341*30215816SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
342*30215816SMarri Devender Rao                     return;
343*30215816SMarri Devender Rao                 }
344*30215816SMarri Devender Rao             }
345*30215816SMarri Devender Rao             else
346*30215816SMarri Devender Rao             {
347*30215816SMarri Devender Rao                 messages::actionParameterNotSupported(
348*30215816SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
349*30215816SMarri Devender Rao                 return;
350*30215816SMarri Devender Rao             }
351*30215816SMarri Devender Rao         }
352*30215816SMarri Devender Rao 
353*30215816SMarri Devender Rao         // Only allow one CSR matcher at a time so setting retry time-out and
354*30215816SMarri Devender Rao         // timer expiry to 10 seconds for now.
355*30215816SMarri Devender Rao         static const int TIME_OUT = 10;
356*30215816SMarri Devender Rao         if (csrMatcher)
357*30215816SMarri Devender Rao         {
358*30215816SMarri Devender Rao             res.addHeader("Retry-After", std::to_string(TIME_OUT));
359*30215816SMarri Devender Rao             messages::serviceTemporarilyUnavailable(asyncResp->res,
360*30215816SMarri Devender Rao                                                     std::to_string(TIME_OUT));
361*30215816SMarri Devender Rao             return;
362*30215816SMarri Devender Rao         }
363*30215816SMarri Devender Rao 
364*30215816SMarri Devender Rao         // Make this static so it survives outside this method
365*30215816SMarri Devender Rao         static boost::asio::steady_timer timeout(*req.ioService);
366*30215816SMarri Devender Rao         timeout.expires_after(std::chrono::seconds(TIME_OUT));
367*30215816SMarri Devender Rao         timeout.async_wait([asyncResp](const boost::system::error_code &ec) {
368*30215816SMarri Devender Rao             csrMatcher = nullptr;
369*30215816SMarri Devender Rao             if (ec)
370*30215816SMarri Devender Rao             {
371*30215816SMarri Devender Rao                 // operation_aborted is expected if timer is canceled before
372*30215816SMarri Devender Rao                 // completion.
373*30215816SMarri Devender Rao                 if (ec != boost::asio::error::operation_aborted)
374*30215816SMarri Devender Rao                 {
375*30215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
376*30215816SMarri Devender Rao                 }
377*30215816SMarri Devender Rao                 return;
378*30215816SMarri Devender Rao             }
379*30215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
380*30215816SMarri Devender Rao             messages::internalError(asyncResp->res);
381*30215816SMarri Devender Rao         });
382*30215816SMarri Devender Rao 
383*30215816SMarri Devender Rao         // create a matcher to wait on CSR object
384*30215816SMarri Devender Rao         BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
385*30215816SMarri Devender Rao         std::string match("type='signal',"
386*30215816SMarri Devender Rao                           "interface='org.freedesktop.DBus.ObjectManager',"
387*30215816SMarri Devender Rao                           "path='" +
388*30215816SMarri Devender Rao                           objectPath +
389*30215816SMarri Devender Rao                           "',"
390*30215816SMarri Devender Rao                           "member='InterfacesAdded'");
391*30215816SMarri Devender Rao         csrMatcher = std::make_unique<sdbusplus::bus::match::match>(
392*30215816SMarri Devender Rao             *crow::connections::systemBus, match,
393*30215816SMarri Devender Rao             [asyncResp, service, objectPath,
394*30215816SMarri Devender Rao              certURI](sdbusplus::message::message &m) {
395*30215816SMarri Devender Rao                 boost::system::error_code ec;
396*30215816SMarri Devender Rao                 timeout.cancel(ec);
397*30215816SMarri Devender Rao                 if (ec)
398*30215816SMarri Devender Rao                 {
399*30215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "error canceling timer " << ec;
400*30215816SMarri Devender Rao                     csrMatcher = nullptr;
401*30215816SMarri Devender Rao                 }
402*30215816SMarri Devender Rao                 if (m.is_method_error())
403*30215816SMarri Devender Rao                 {
404*30215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Dbus method error!!!";
405*30215816SMarri Devender Rao                     messages::internalError(asyncResp->res);
406*30215816SMarri Devender Rao                     return;
407*30215816SMarri Devender Rao                 }
408*30215816SMarri Devender Rao                 std::vector<std::pair<
409*30215816SMarri Devender Rao                     std::string, std::vector<std::pair<
410*30215816SMarri Devender Rao                                      std::string, std::variant<std::string>>>>>
411*30215816SMarri Devender Rao                     interfacesProperties;
412*30215816SMarri Devender Rao                 sdbusplus::message::object_path csrObjectPath;
413*30215816SMarri Devender Rao                 m.read(csrObjectPath, interfacesProperties);
414*30215816SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
415*30215816SMarri Devender Rao                 for (auto &interface : interfacesProperties)
416*30215816SMarri Devender Rao                 {
417*30215816SMarri Devender Rao                     if (interface.first == "xyz.openbmc_project.Certs.CSR")
418*30215816SMarri Devender Rao                     {
419*30215816SMarri Devender Rao                         getCSR(asyncResp, certURI, service, objectPath,
420*30215816SMarri Devender Rao                                csrObjectPath.str);
421*30215816SMarri Devender Rao                         break;
422*30215816SMarri Devender Rao                     }
423*30215816SMarri Devender Rao                 }
424*30215816SMarri Devender Rao             });
425*30215816SMarri Devender Rao         crow::connections::systemBus->async_method_call(
426*30215816SMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
427*30215816SMarri Devender Rao                         const std::string &path) {
428*30215816SMarri Devender Rao                 if (ec)
429*30215816SMarri Devender Rao                 {
430*30215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
431*30215816SMarri Devender Rao                     messages::internalError(asyncResp->res);
432*30215816SMarri Devender Rao                     return;
433*30215816SMarri Devender Rao                 }
434*30215816SMarri Devender Rao             },
435*30215816SMarri Devender Rao             service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
436*30215816SMarri Devender Rao             "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
437*30215816SMarri Devender Rao             commonName, *optContactPerson, country, *optEmail, *optGivenName,
438*30215816SMarri Devender Rao             *optInitials, *optKeyBitLength, *optKeyCurveId,
439*30215816SMarri Devender Rao             *optKeyPairAlgorithm, *optKeyUsage, organization,
440*30215816SMarri Devender Rao             organizationalUnit, state, *optSurname, *optUnstructuredName);
441*30215816SMarri Devender Rao     }
442*30215816SMarri Devender Rao }; // CertificateActionGenerateCSR
443*30215816SMarri Devender Rao 
4445968caeeSMarri Devender Rao /**
4455968caeeSMarri Devender Rao  * @brief Parse and update Certficate Issue/Subject property
4465968caeeSMarri Devender Rao  *
4475968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4485968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4495968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4505968caeeSMarri Devender Rao  * @return None
4515968caeeSMarri Devender Rao  */
4525968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json &out,
4535968caeeSMarri Devender Rao                                       const std::string_view value)
4545968caeeSMarri Devender Rao {
4555968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
4565968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
4575968caeeSMarri Devender Rao     while (i != value.end())
4585968caeeSMarri Devender Rao     {
4595968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
4605968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
4615968caeeSMarri Devender Rao         {
4625968caeeSMarri Devender Rao             i++;
4635968caeeSMarri Devender Rao         }
4645968caeeSMarri Devender Rao         if (i == value.end())
4655968caeeSMarri Devender Rao         {
4665968caeeSMarri Devender Rao             break;
4675968caeeSMarri Devender Rao         }
4685968caeeSMarri Devender Rao         const std::string_view key(tokenBegin, i - tokenBegin);
4695968caeeSMarri Devender Rao         i++;
4705968caeeSMarri Devender Rao         tokenBegin = i;
4715968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
4725968caeeSMarri Devender Rao         {
4735968caeeSMarri Devender Rao             i++;
4745968caeeSMarri Devender Rao         }
4755968caeeSMarri Devender Rao         const std::string_view val(tokenBegin, i - tokenBegin);
4765968caeeSMarri Devender Rao         if (key == "L")
4775968caeeSMarri Devender Rao         {
4785968caeeSMarri Devender Rao             out["City"] = val;
4795968caeeSMarri Devender Rao         }
4805968caeeSMarri Devender Rao         else if (key == "CN")
4815968caeeSMarri Devender Rao         {
4825968caeeSMarri Devender Rao             out["CommonName"] = val;
4835968caeeSMarri Devender Rao         }
4845968caeeSMarri Devender Rao         else if (key == "C")
4855968caeeSMarri Devender Rao         {
4865968caeeSMarri Devender Rao             out["Country"] = val;
4875968caeeSMarri Devender Rao         }
4885968caeeSMarri Devender Rao         else if (key == "O")
4895968caeeSMarri Devender Rao         {
4905968caeeSMarri Devender Rao             out["Organization"] = val;
4915968caeeSMarri Devender Rao         }
4925968caeeSMarri Devender Rao         else if (key == "OU")
4935968caeeSMarri Devender Rao         {
4945968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
4955968caeeSMarri Devender Rao         }
4965968caeeSMarri Devender Rao         else if (key == "ST")
4975968caeeSMarri Devender Rao         {
4985968caeeSMarri Devender Rao             out["State"] = val;
4995968caeeSMarri Devender Rao         }
5005968caeeSMarri Devender Rao         // skip comma character
5015968caeeSMarri Devender Rao         if (i != value.end())
5025968caeeSMarri Devender Rao         {
5035968caeeSMarri Devender Rao             i++;
5045968caeeSMarri Devender Rao         }
5055968caeeSMarri Devender Rao     }
5065968caeeSMarri Devender Rao }
5075968caeeSMarri Devender Rao 
5085968caeeSMarri Devender Rao /**
5095968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
5105968caeeSMarri Devender Rao  * message
5115968caeeSMarri Devender Rao  *
5125968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
5135968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
5145968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
5155968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
5165968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
5175968caeeSMarri Devender Rao  * @return None
5185968caeeSMarri Devender Rao  */
5195968caeeSMarri Devender Rao static void getCertificateProperties(
5205968caeeSMarri Devender Rao     const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath,
52137cce918SMarri Devender Rao     const std::string &service, long certId, const std::string &certURL,
52237cce918SMarri Devender Rao     const std::string &name)
5235968caeeSMarri Devender Rao {
5245968caeeSMarri Devender Rao     using PropertyType =
5255968caeeSMarri Devender Rao         std::variant<std::string, uint64_t, std::vector<std::string>>;
5265968caeeSMarri Devender Rao     using PropertiesMap = boost::container::flat_map<std::string, PropertyType>;
5275968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
5285968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
5295968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
53037cce918SMarri Devender Rao         [asyncResp, certURL, certId, name](const boost::system::error_code ec,
5315968caeeSMarri Devender Rao                                            const PropertiesMap &properties) {
5325968caeeSMarri Devender Rao             if (ec)
5335968caeeSMarri Devender Rao             {
5345968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5358aae75adSMarri Devender Rao                 messages::resourceNotFound(asyncResp->res, name,
5368aae75adSMarri Devender Rao                                            std::to_string(certId));
5375968caeeSMarri Devender Rao                 return;
5385968caeeSMarri Devender Rao             }
5395968caeeSMarri Devender Rao             asyncResp->res.jsonValue = {
5405968caeeSMarri Devender Rao                 {"@odata.id", certURL},
5415968caeeSMarri Devender Rao                 {"@odata.type", "#Certificate.v1_0_0.Certificate"},
5425968caeeSMarri Devender Rao                 {"@odata.context",
5435968caeeSMarri Devender Rao                  "/redfish/v1/$metadata#Certificate.Certificate"},
5445968caeeSMarri Devender Rao                 {"Id", std::to_string(certId)},
5455968caeeSMarri Devender Rao                 {"Name", name},
5465968caeeSMarri Devender Rao                 {"Description", name}};
5475968caeeSMarri Devender Rao             for (const auto &property : properties)
5485968caeeSMarri Devender Rao             {
5495968caeeSMarri Devender Rao                 if (property.first == "CertificateString")
5505968caeeSMarri Devender Rao                 {
5515968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = "";
5525968caeeSMarri Devender Rao                     const std::string *value =
5535968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
5545968caeeSMarri Devender Rao                     if (value)
5555968caeeSMarri Devender Rao                     {
55637cce918SMarri Devender Rao                         asyncResp->res.jsonValue["CertificateString"] = *value;
5575968caeeSMarri Devender Rao                     }
5585968caeeSMarri Devender Rao                 }
5595968caeeSMarri Devender Rao                 else if (property.first == "KeyUsage")
5605968caeeSMarri Devender Rao                 {
5615968caeeSMarri Devender Rao                     nlohmann::json &keyUsage =
5625968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["KeyUsage"];
5635968caeeSMarri Devender Rao                     keyUsage = nlohmann::json::array();
5645968caeeSMarri Devender Rao                     const std::vector<std::string> *value =
56537cce918SMarri Devender Rao                         std::get_if<std::vector<std::string>>(&property.second);
5665968caeeSMarri Devender Rao                     if (value)
5675968caeeSMarri Devender Rao                     {
5685968caeeSMarri Devender Rao                         for (const std::string &usage : *value)
5695968caeeSMarri Devender Rao                         {
5705968caeeSMarri Devender Rao                             keyUsage.push_back(usage);
5715968caeeSMarri Devender Rao                         }
5725968caeeSMarri Devender Rao                     }
5735968caeeSMarri Devender Rao                 }
5745968caeeSMarri Devender Rao                 else if (property.first == "Issuer")
5755968caeeSMarri Devender Rao                 {
5765968caeeSMarri Devender Rao                     const std::string *value =
5775968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
5785968caeeSMarri Devender Rao                     if (value)
5795968caeeSMarri Devender Rao                     {
5805968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
5815968caeeSMarri Devender Rao                             asyncResp->res.jsonValue["Issuer"], *value);
5825968caeeSMarri Devender Rao                     }
5835968caeeSMarri Devender Rao                 }
5845968caeeSMarri Devender Rao                 else if (property.first == "Subject")
5855968caeeSMarri Devender Rao                 {
5865968caeeSMarri Devender Rao                     const std::string *value =
5875968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
5885968caeeSMarri Devender Rao                     if (value)
5895968caeeSMarri Devender Rao                     {
5905968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
59137cce918SMarri Devender Rao                             asyncResp->res.jsonValue["Subject"], *value);
5925968caeeSMarri Devender Rao                     }
5935968caeeSMarri Devender Rao                 }
5945968caeeSMarri Devender Rao                 else if (property.first == "ValidNotAfter")
5955968caeeSMarri Devender Rao                 {
5965968caeeSMarri Devender Rao                     const uint64_t *value =
5975968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
5985968caeeSMarri Devender Rao                     if (value)
5995968caeeSMarri Devender Rao                     {
60037cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6015968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotAfter"] =
6025968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6035968caeeSMarri Devender Rao                     }
6045968caeeSMarri Devender Rao                 }
6055968caeeSMarri Devender Rao                 else if (property.first == "ValidNotBefore")
6065968caeeSMarri Devender Rao                 {
6075968caeeSMarri Devender Rao                     const uint64_t *value =
6085968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
6095968caeeSMarri Devender Rao                     if (value)
6105968caeeSMarri Devender Rao                     {
61137cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6125968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotBefore"] =
6135968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6145968caeeSMarri Devender Rao                     }
6155968caeeSMarri Devender Rao                 }
6165968caeeSMarri Devender Rao             }
6175968caeeSMarri Devender Rao             asyncResp->res.addHeader("Location", certURL);
6185968caeeSMarri Devender Rao         },
6195968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
6205968caeeSMarri Devender Rao         certs::certPropIntf);
6215968caeeSMarri Devender Rao }
6225968caeeSMarri Devender Rao 
6235968caeeSMarri Devender Rao using GetObjectType =
6245968caeeSMarri Devender Rao     std::vector<std::pair<std::string, std::vector<std::string>>>;
6255968caeeSMarri Devender Rao 
6265968caeeSMarri Devender Rao /**
6275968caeeSMarri Devender Rao  * Action to replace an existing certificate
6285968caeeSMarri Devender Rao  */
6295968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node
6305968caeeSMarri Devender Rao {
6315968caeeSMarri Devender Rao   public:
6325968caeeSMarri Devender Rao     CertificateActionsReplaceCertificate(CrowApp &app) :
6335968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/Actions/"
6345968caeeSMarri Devender Rao                   "CertificateService.ReplaceCertificate/")
6355968caeeSMarri Devender Rao     {
6365968caeeSMarri Devender Rao         entityPrivileges = {
6375968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
6385968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
6395968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
6405968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
6415968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
6425968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
6435968caeeSMarri Devender Rao     }
6445968caeeSMarri Devender Rao 
6455968caeeSMarri Devender Rao   private:
6465968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
6475968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
6485968caeeSMarri Devender Rao     {
6495968caeeSMarri Devender Rao         std::string certificate;
6505968caeeSMarri Devender Rao         nlohmann::json certificateUri;
6515968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
6525968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
6535968caeeSMarri Devender Rao         if (!json_util::readJson(req, asyncResp->res, "CertificateString",
6545968caeeSMarri Devender Rao                                  certificate, "CertificateUri", certificateUri,
6555968caeeSMarri Devender Rao                                  "CertificateType", certificateType))
6565968caeeSMarri Devender Rao         {
6575968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
6585968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
6595968caeeSMarri Devender Rao             return;
6605968caeeSMarri Devender Rao         }
6615968caeeSMarri Devender Rao 
6625968caeeSMarri Devender Rao         if (!certificateType)
6635968caeeSMarri Devender Rao         {
6645968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
6655968caeeSMarri Devender Rao             return;
6665968caeeSMarri Devender Rao         }
6675968caeeSMarri Devender Rao         if (certificateType != "PEM")
6685968caeeSMarri Devender Rao         {
6695968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
6705968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
6715968caeeSMarri Devender Rao             return;
6725968caeeSMarri Devender Rao         }
6735968caeeSMarri Devender Rao 
6745968caeeSMarri Devender Rao         std::string certURI;
6755968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
6765968caeeSMarri Devender Rao                                           "@odata.id", certURI))
6775968caeeSMarri Devender Rao         {
6785968caeeSMarri Devender Rao             messages::actionParameterMissing(
6795968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
6805968caeeSMarri Devender Rao             return;
6815968caeeSMarri Devender Rao         }
6825968caeeSMarri Devender Rao 
6835968caeeSMarri Devender Rao         BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
6845968caeeSMarri Devender Rao         long id = getIDFromURL(certURI);
6855968caeeSMarri Devender Rao         if (id < 0)
6865968caeeSMarri Devender Rao         {
6875968caeeSMarri Devender Rao             messages::actionParameterValueFormatError(asyncResp->res, certURI,
6885968caeeSMarri Devender Rao                                                       "CertificateUri",
6895968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
6905968caeeSMarri Devender Rao             return;
6915968caeeSMarri Devender Rao         }
6925968caeeSMarri Devender Rao         std::string objectPath;
6935968caeeSMarri Devender Rao         std::string name;
69437cce918SMarri Devender Rao         std::string service;
6955968caeeSMarri Devender Rao         if (boost::starts_with(
6965968caeeSMarri Devender Rao                 certURI,
6975968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"))
6985968caeeSMarri Devender Rao         {
6995968caeeSMarri Devender Rao             objectPath =
7005968caeeSMarri Devender Rao                 std::string(certs::httpsObjectPath) + "/" + std::to_string(id);
7015968caeeSMarri Devender Rao             name = "HTTPS certificate";
70237cce918SMarri Devender Rao             service = certs::httpsServiceName;
70337cce918SMarri Devender Rao         }
70437cce918SMarri Devender Rao         else if (boost::starts_with(
70537cce918SMarri Devender Rao                      certURI, "/redfish/v1/AccountService/LDAP/Certificates/"))
70637cce918SMarri Devender Rao         {
70737cce918SMarri Devender Rao             objectPath =
70837cce918SMarri Devender Rao                 std::string(certs::ldapObjectPath) + "/" + std::to_string(id);
70937cce918SMarri Devender Rao             name = "LDAP certificate";
71037cce918SMarri Devender Rao             service = certs::ldapServiceName;
7115968caeeSMarri Devender Rao         }
7125968caeeSMarri Devender Rao         else
7135968caeeSMarri Devender Rao         {
7145968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
7155968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
7165968caeeSMarri Devender Rao             return;
7175968caeeSMarri Devender Rao         }
7185968caeeSMarri Devender Rao 
7195968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
7205968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
7215968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
72237cce918SMarri Devender Rao             [asyncResp, certFile, objectPath, service, certURI, id,
7235968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
7245968caeeSMarri Devender Rao                 if (ec)
7255968caeeSMarri Devender Rao                 {
7265968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
7278aae75adSMarri Devender Rao                     messages::resourceNotFound(asyncResp->res, name,
7288aae75adSMarri Devender Rao                                                std::to_string(id));
7295968caeeSMarri Devender Rao                     return;
7305968caeeSMarri Devender Rao                 }
73137cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath, service, id,
7325968caeeSMarri Devender Rao                                          certURI, name);
7335968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
7345968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
7355968caeeSMarri Devender Rao             },
7365968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
7375968caeeSMarri Devender Rao             certFile->getCertFilePath());
7385968caeeSMarri Devender Rao     }
7395968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate
7405968caeeSMarri Devender Rao 
7415968caeeSMarri Devender Rao /**
7425968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
7435968caeeSMarri Devender Rao  * of a component, account or service.
7445968caeeSMarri Devender Rao  */
7455968caeeSMarri Devender Rao class HTTPSCertificate : public Node
7465968caeeSMarri Devender Rao {
7475968caeeSMarri Devender Rao   public:
7485968caeeSMarri Devender Rao     template <typename CrowApp>
7495968caeeSMarri Devender Rao     HTTPSCertificate(CrowApp &app) :
7505968caeeSMarri Devender Rao         Node(app,
7515968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
7525968caeeSMarri Devender Rao              "<str>/",
7535968caeeSMarri Devender Rao              std::string())
7545968caeeSMarri Devender Rao     {
7555968caeeSMarri Devender Rao         entityPrivileges = {
7565968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
7575968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
7585968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
7595968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
7605968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
7615968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
7625968caeeSMarri Devender Rao     }
7635968caeeSMarri Devender Rao 
7645968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
7655968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
7665968caeeSMarri Devender Rao     {
7675968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
7685968caeeSMarri Devender Rao         if (params.size() != 1)
7695968caeeSMarri Devender Rao         {
7705968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
7715968caeeSMarri Devender Rao             return;
7725968caeeSMarri Devender Rao         }
7735968caeeSMarri Devender Rao         long id = getIDFromURL(req.url);
7745968caeeSMarri Devender Rao 
7755968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id);
7765968caeeSMarri Devender Rao         std::string certURL =
7775968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
7785968caeeSMarri Devender Rao             std::to_string(id);
7795968caeeSMarri Devender Rao         std::string objectPath = certs::httpsObjectPath;
7805968caeeSMarri Devender Rao         objectPath += "/";
7815968caeeSMarri Devender Rao         objectPath += std::to_string(id);
78237cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
78337cce918SMarri Devender Rao                                  id, certURL, "HTTPS Certificate");
7845968caeeSMarri Devender Rao     }
7855968caeeSMarri Devender Rao 
7865968caeeSMarri Devender Rao }; // namespace redfish
7875968caeeSMarri Devender Rao 
7885968caeeSMarri Devender Rao /**
7895968caeeSMarri Devender Rao  * Collection of HTTPS certificates
7905968caeeSMarri Devender Rao  */
7915968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node
7925968caeeSMarri Devender Rao {
7935968caeeSMarri Devender Rao   public:
7945968caeeSMarri Devender Rao     template <typename CrowApp>
7955968caeeSMarri Devender Rao     HTTPSCertificateCollection(CrowApp &app) :
7965968caeeSMarri Devender Rao         Node(app,
7975968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
7985968caeeSMarri Devender Rao     {
7995968caeeSMarri Devender Rao         entityPrivileges = {
8005968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
8015968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
8025968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
8035968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
8045968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
8055968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
8065968caeeSMarri Devender Rao     }
8075968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
8085968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
8095968caeeSMarri Devender Rao     {
8105968caeeSMarri Devender Rao         res.jsonValue = {
8115968caeeSMarri Devender Rao             {"@odata.id",
8125968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
8135968caeeSMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
8145968caeeSMarri Devender Rao             {"@odata.context",
8155968caeeSMarri Devender Rao              "/redfish/v1/"
8165968caeeSMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
8175968caeeSMarri Devender Rao             {"Name", "HTTPS Certificates Collection"},
8185968caeeSMarri Devender Rao             {"Description", "A Collection of HTTPS certificate instances"}};
8195968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
8205968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
8215968caeeSMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
8225968caeeSMarri Devender Rao                         const ManagedObjectType &certs) {
8235968caeeSMarri Devender Rao                 if (ec)
8245968caeeSMarri Devender Rao                 {
8255968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8265968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
8275968caeeSMarri Devender Rao                     return;
8285968caeeSMarri Devender Rao                 }
82937cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
8305968caeeSMarri Devender Rao                 members = nlohmann::json::array();
8315968caeeSMarri Devender Rao                 for (const auto &cert : certs)
8325968caeeSMarri Devender Rao                 {
8335968caeeSMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
83437cce918SMarri Devender Rao                     if (id >= 0)
8355968caeeSMarri Devender Rao                     {
8365968caeeSMarri Devender Rao                         members.push_back(
8375968caeeSMarri Devender Rao                             {{"@odata.id",
8385968caeeSMarri Devender Rao                               "/redfish/v1/Managers/bmc/"
8395968caeeSMarri Devender Rao                               "NetworkProtocol/HTTPS/Certificates/" +
8405968caeeSMarri Devender Rao                                   std::to_string(id)}});
8415968caeeSMarri Devender Rao                     }
8425968caeeSMarri Devender Rao                 }
8435968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
8445968caeeSMarri Devender Rao                     members.size();
8455968caeeSMarri Devender Rao             },
84637cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
84737cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
8485968caeeSMarri Devender Rao     }
8495968caeeSMarri Devender Rao 
8505968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
8515968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
8525968caeeSMarri Devender Rao     {
8535968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
8545968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
8555968caeeSMarri Devender Rao         asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"},
8565968caeeSMarri Devender Rao                                     {"Description", "HTTPS Certificate"}};
8575968caeeSMarri Devender Rao 
8585968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
8595968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
8605968caeeSMarri Devender Rao 
8615968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
8625968caeeSMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
8635968caeeSMarri Devender Rao                 if (ec)
8645968caeeSMarri Devender Rao                 {
8655968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8665968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
8675968caeeSMarri Devender Rao                     return;
8685968caeeSMarri Devender Rao                 }
8695968caeeSMarri Devender Rao                 // TODO: Issue#84 supporting only 1 certificate
8705968caeeSMarri Devender Rao                 long certId = 1;
8715968caeeSMarri Devender Rao                 std::string certURL =
8725968caeeSMarri Devender Rao                     "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
8735968caeeSMarri Devender Rao                     "Certificates/" +
8745968caeeSMarri Devender Rao                     std::to_string(certId);
87537cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::httpsObjectPath) +
87637cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
87737cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
87837cce918SMarri Devender Rao                                          certs::httpsServiceName, certId,
8795968caeeSMarri Devender Rao                                          certURL, "HTTPS Certificate");
8805968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
8815968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
8825968caeeSMarri Devender Rao             },
88337cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
88437cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
8855968caeeSMarri Devender Rao     }
8865968caeeSMarri Devender Rao }; // HTTPSCertificateCollection
8875968caeeSMarri Devender Rao 
8885968caeeSMarri Devender Rao /**
8895968caeeSMarri Devender Rao  * The certificate location schema defines a resource that an administrator
8905968caeeSMarri Devender Rao  * can use in order to locate all certificates installed on a given service.
8915968caeeSMarri Devender Rao  */
8925968caeeSMarri Devender Rao class CertificateLocations : public Node
8935968caeeSMarri Devender Rao {
8945968caeeSMarri Devender Rao   public:
8955968caeeSMarri Devender Rao     template <typename CrowApp>
8965968caeeSMarri Devender Rao     CertificateLocations(CrowApp &app) :
8975968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/CertificateLocations/")
8985968caeeSMarri Devender Rao     {
8995968caeeSMarri Devender Rao         entityPrivileges = {
9005968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
9015968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
9025968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
9035968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
9045968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
9055968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
9065968caeeSMarri Devender Rao     }
9075968caeeSMarri Devender Rao 
9085968caeeSMarri Devender Rao   private:
9095968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
9105968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
9115968caeeSMarri Devender Rao     {
9125968caeeSMarri Devender Rao         res.jsonValue = {
9135968caeeSMarri Devender Rao             {"@odata.id",
9145968caeeSMarri Devender Rao              "/redfish/v1/CertificateService/CertificateLocations"},
9155968caeeSMarri Devender Rao             {"@odata.type",
9165968caeeSMarri Devender Rao              "#CertificateLocations.v1_0_0.CertificateLocations"},
9175968caeeSMarri Devender Rao             {"@odata.context",
9185968caeeSMarri Devender Rao              "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"},
9195968caeeSMarri Devender Rao             {"Name", "Certificate Locations"},
9205968caeeSMarri Devender Rao             {"Id", "CertificateLocations"},
9215968caeeSMarri Devender Rao             {"Description",
9225968caeeSMarri Devender Rao              "Defines a resource that an administrator can use in order to "
9235968caeeSMarri Devender Rao              "locate all certificates installed on a given service"}};
9245968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
9255968caeeSMarri Devender Rao         nlohmann::json &links =
9265968caeeSMarri Devender Rao             asyncResp->res.jsonValue["Links"]["Certificates"];
9275968caeeSMarri Devender Rao         links = nlohmann::json::array();
9285968caeeSMarri Devender Rao         getCertificateLocations(
9295968caeeSMarri Devender Rao             asyncResp,
9305968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
93137cce918SMarri Devender Rao             certs::httpsObjectPath, certs::httpsServiceName);
93237cce918SMarri Devender Rao         getCertificateLocations(asyncResp,
93337cce918SMarri Devender Rao                                 "/redfish/v1/AccountService/LDAP/Certificates/",
93437cce918SMarri Devender Rao                                 certs::ldapObjectPath, certs::ldapServiceName);
93537cce918SMarri Devender Rao     }
93637cce918SMarri Devender Rao     /**
93737cce918SMarri Devender Rao      * @brief Retrieve the certificates installed list and append to the
93837cce918SMarri Devender Rao      * response
93937cce918SMarri Devender Rao      *
94037cce918SMarri Devender Rao      * @param[in] asyncResp Shared pointer to the response message
94137cce918SMarri Devender Rao      * @param[in] certURL  Path of the certificate object
94237cce918SMarri Devender Rao      * @param[in] path  Path of the D-Bus service object
94337cce918SMarri Devender Rao      * @return None
94437cce918SMarri Devender Rao      */
94537cce918SMarri Devender Rao     void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp,
94637cce918SMarri Devender Rao                                  const std::string &certURL,
94737cce918SMarri Devender Rao                                  const std::string &path,
94837cce918SMarri Devender Rao                                  const std::string &service)
94937cce918SMarri Devender Rao     {
95037cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
95137cce918SMarri Devender Rao                          << " Path=" << path << " service= " << service;
95237cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
95337cce918SMarri Devender Rao             [asyncResp, certURL](const boost::system::error_code ec,
95437cce918SMarri Devender Rao                                  const ManagedObjectType &certs) {
95537cce918SMarri Devender Rao                 if (ec)
95637cce918SMarri Devender Rao                 {
95737cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
95837cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
95937cce918SMarri Devender Rao                     return;
96037cce918SMarri Devender Rao                 }
96137cce918SMarri Devender Rao                 nlohmann::json &links =
96237cce918SMarri Devender Rao                     asyncResp->res.jsonValue["Links"]["Certificates"];
96337cce918SMarri Devender Rao                 for (auto &cert : certs)
96437cce918SMarri Devender Rao                 {
96537cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
96637cce918SMarri Devender Rao                     if (id >= 0)
96737cce918SMarri Devender Rao                     {
96837cce918SMarri Devender Rao                         links.push_back(
96937cce918SMarri Devender Rao                             {{"@odata.id", certURL + std::to_string(id)}});
97037cce918SMarri Devender Rao                     }
97137cce918SMarri Devender Rao                 }
97237cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
97337cce918SMarri Devender Rao                     links.size();
97437cce918SMarri Devender Rao             },
97537cce918SMarri Devender Rao             service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
9765968caeeSMarri Devender Rao     }
9775968caeeSMarri Devender Rao }; // CertificateLocations
97837cce918SMarri Devender Rao 
97937cce918SMarri Devender Rao /**
98037cce918SMarri Devender Rao  * Collection of LDAP certificates
98137cce918SMarri Devender Rao  */
98237cce918SMarri Devender Rao class LDAPCertificateCollection : public Node
98337cce918SMarri Devender Rao {
98437cce918SMarri Devender Rao   public:
98537cce918SMarri Devender Rao     template <typename CrowApp>
98637cce918SMarri Devender Rao     LDAPCertificateCollection(CrowApp &app) :
98737cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/")
98837cce918SMarri Devender Rao     {
98937cce918SMarri Devender Rao         entityPrivileges = {
99037cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
99137cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
99237cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
99337cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
99437cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
99537cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
99637cce918SMarri Devender Rao     }
99737cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
99837cce918SMarri Devender Rao                const std::vector<std::string> &params) override
99937cce918SMarri Devender Rao     {
100037cce918SMarri Devender Rao         res.jsonValue = {
100137cce918SMarri Devender Rao             {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"},
100237cce918SMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
100337cce918SMarri Devender Rao             {"@odata.context",
100437cce918SMarri Devender Rao              "/redfish/v1/"
100537cce918SMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
100637cce918SMarri Devender Rao             {"Name", "LDAP Certificates Collection"},
100737cce918SMarri Devender Rao             {"Description", "A Collection of LDAP certificate instances"}};
100837cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
100937cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
101037cce918SMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
101137cce918SMarri Devender Rao                         const ManagedObjectType &certs) {
101237cce918SMarri Devender Rao                 if (ec)
101337cce918SMarri Devender Rao                 {
101437cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
101537cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
101637cce918SMarri Devender Rao                     return;
101737cce918SMarri Devender Rao                 }
101837cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
101937cce918SMarri Devender Rao                 members = nlohmann::json::array();
102037cce918SMarri Devender Rao                 for (const auto &cert : certs)
102137cce918SMarri Devender Rao                 {
102237cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
102337cce918SMarri Devender Rao                     if (id >= 0)
102437cce918SMarri Devender Rao                     {
102537cce918SMarri Devender Rao                         members.push_back(
102637cce918SMarri Devender Rao                             {{"@odata.id", "/redfish/v1/AccountService/"
102737cce918SMarri Devender Rao                                            "LDAP/Certificates/" +
102837cce918SMarri Devender Rao                                                std::to_string(id)}});
102937cce918SMarri Devender Rao                     }
103037cce918SMarri Devender Rao                 }
103137cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
103237cce918SMarri Devender Rao                     members.size();
103337cce918SMarri Devender Rao             },
103437cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
103537cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
103637cce918SMarri Devender Rao     }
103737cce918SMarri Devender Rao 
103837cce918SMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
103937cce918SMarri Devender Rao                 const std::vector<std::string> &params) override
104037cce918SMarri Devender Rao     {
104137cce918SMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
104237cce918SMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
104337cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
104437cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
104537cce918SMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
104637cce918SMarri Devender Rao                 if (ec)
104737cce918SMarri Devender Rao                 {
104837cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
104937cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
105037cce918SMarri Devender Rao                     return;
105137cce918SMarri Devender Rao                 }
105237cce918SMarri Devender Rao                 //// TODO: Issue#84 supporting only 1 certificate
105337cce918SMarri Devender Rao                 long certId = 1;
105437cce918SMarri Devender Rao                 std::string certURL =
105537cce918SMarri Devender Rao                     "/redfish/v1/AccountService/LDAP/Certificates/" +
105637cce918SMarri Devender Rao                     std::to_string(certId);
105737cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::ldapObjectPath) +
105837cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
105937cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
106037cce918SMarri Devender Rao                                          certs::ldapServiceName, certId,
106137cce918SMarri Devender Rao                                          certURL, "LDAP Certificate");
106237cce918SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "LDAP certificate install file="
106337cce918SMarri Devender Rao                                  << certFile->getCertFilePath();
106437cce918SMarri Devender Rao             },
106537cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
106637cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
106737cce918SMarri Devender Rao     }
106837cce918SMarri Devender Rao }; // LDAPCertificateCollection
106937cce918SMarri Devender Rao 
107037cce918SMarri Devender Rao /**
107137cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
107237cce918SMarri Devender Rao  * of a component, account or service.
107337cce918SMarri Devender Rao  */
107437cce918SMarri Devender Rao class LDAPCertificate : public Node
107537cce918SMarri Devender Rao {
107637cce918SMarri Devender Rao   public:
107737cce918SMarri Devender Rao     template <typename CrowApp>
107837cce918SMarri Devender Rao     LDAPCertificate(CrowApp &app) :
107937cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/",
108037cce918SMarri Devender Rao              std::string())
108137cce918SMarri Devender Rao     {
108237cce918SMarri Devender Rao         entityPrivileges = {
108337cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
108437cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
108537cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
108637cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
108737cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
108837cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
108937cce918SMarri Devender Rao     }
109037cce918SMarri Devender Rao 
109137cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
109237cce918SMarri Devender Rao                const std::vector<std::string> &params) override
109337cce918SMarri Devender Rao     {
109437cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
109537cce918SMarri Devender Rao         long id = getIDFromURL(req.url);
109637cce918SMarri Devender Rao         if (id < 0)
109737cce918SMarri Devender Rao         {
109837cce918SMarri Devender Rao             BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
109937cce918SMarri Devender Rao             messages::internalError(asyncResp->res);
110037cce918SMarri Devender Rao             return;
110137cce918SMarri Devender Rao         }
110237cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id);
110337cce918SMarri Devender Rao         std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" +
110437cce918SMarri Devender Rao                               std::to_string(id);
110537cce918SMarri Devender Rao         std::string objectPath = certs::ldapObjectPath;
110637cce918SMarri Devender Rao         objectPath += "/";
110737cce918SMarri Devender Rao         objectPath += std::to_string(id);
110837cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
110937cce918SMarri Devender Rao                                  id, certURL, "LDAP Certificate");
111037cce918SMarri Devender Rao     }
111137cce918SMarri Devender Rao }; // LDAPCertificate
11125968caeeSMarri Devender Rao } // namespace redfish
1113