xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision cfcd5f6bd9289c97e25d809068e579f7f3d45aeb)
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";
37*cfcd5f6bSMarri Devender Rao constexpr char const *authorityServiceName =
38*cfcd5f6bSMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
39*cfcd5f6bSMarri Devender Rao constexpr char const *authorityObjectPath =
40*cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
415968caeeSMarri Devender Rao } // namespace certs
425968caeeSMarri Devender Rao 
435968caeeSMarri Devender Rao /**
445968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
455968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
465968caeeSMarri Devender Rao  * are installed.
475968caeeSMarri Devender Rao  */
485968caeeSMarri Devender Rao class CertificateService : public Node
495968caeeSMarri Devender Rao {
505968caeeSMarri Devender Rao   public:
515968caeeSMarri Devender Rao     CertificateService(CrowApp &app) :
525968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/")
535968caeeSMarri Devender Rao     {
545968caeeSMarri Devender Rao         // TODO: Issue#61 No entries are available for Certificate
555968caeeSMarri Devender Rao         // sevice at https://www.dmtf.org/standards/redfish
565968caeeSMarri Devender Rao         // "redfish standard registries". Need to modify after DMTF
575968caeeSMarri Devender Rao         // publish Privilege details for certificate service
585968caeeSMarri Devender Rao         entityPrivileges = {
595968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
605968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
615968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
625968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
635968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
645968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
655968caeeSMarri Devender Rao     }
665968caeeSMarri Devender Rao 
675968caeeSMarri Devender Rao   private:
685968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
695968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
705968caeeSMarri Devender Rao     {
715968caeeSMarri Devender Rao         res.jsonValue = {
725968caeeSMarri Devender Rao             {"@odata.type", "#CertificateService.v1_0_0.CertificateService"},
735968caeeSMarri Devender Rao             {"@odata.id", "/redfish/v1/CertificateService"},
745968caeeSMarri Devender Rao             {"@odata.context",
755968caeeSMarri Devender Rao              "/redfish/v1/$metadata#CertificateService.CertificateService"},
765968caeeSMarri Devender Rao             {"Id", "CertificateService"},
775968caeeSMarri Devender Rao             {"Name", "Certificate Service"},
785968caeeSMarri Devender Rao             {"Description", "Actions available to manage certificates"}};
795968caeeSMarri Devender Rao         res.jsonValue["CertificateLocations"] = {
805968caeeSMarri Devender Rao             {"@odata.id",
815968caeeSMarri Devender Rao              "/redfish/v1/CertificateService/CertificateLocations"}};
825968caeeSMarri Devender Rao         res.jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
835968caeeSMarri Devender Rao             {"target", "/redfish/v1/CertificateService/Actions/"
845968caeeSMarri Devender Rao                        "CertificateService.ReplaceCertificate"},
855968caeeSMarri Devender Rao             {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
8630215816SMarri Devender Rao         res.jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
8730215816SMarri Devender Rao             {"target", "/redfish/v1/CertificateService/Actions/"
8830215816SMarri Devender Rao                        "CertificateService.GenerateCSR"}};
895968caeeSMarri Devender Rao         res.end();
905968caeeSMarri Devender Rao     }
915968caeeSMarri Devender Rao }; // CertificateService
9237cce918SMarri Devender Rao 
935968caeeSMarri Devender Rao /**
945968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
955968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
965968caeeSMarri Devender Rao  * @param[in] path URL
975968caeeSMarri Devender Rao  * @return -1 on failure and number on success
985968caeeSMarri Devender Rao  */
995968caeeSMarri Devender Rao long getIDFromURL(const std::string_view url)
1005968caeeSMarri Devender Rao {
1015968caeeSMarri Devender Rao     std::size_t found = url.rfind("/");
1025968caeeSMarri Devender Rao     if (found == std::string::npos)
1035968caeeSMarri Devender Rao     {
1045968caeeSMarri Devender Rao         return -1;
1055968caeeSMarri Devender Rao     }
1065968caeeSMarri Devender Rao     if ((found + 1) < url.length())
1075968caeeSMarri Devender Rao     {
1085968caeeSMarri Devender Rao         char *endPtr;
1095968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
1105968caeeSMarri Devender Rao         long value = std::strtol(str.data(), &endPtr, 10);
11137cce918SMarri Devender Rao         if (endPtr != str.end())
1125968caeeSMarri Devender Rao         {
1135968caeeSMarri Devender Rao             return -1;
1145968caeeSMarri Devender Rao         }
1155968caeeSMarri Devender Rao         return value;
1165968caeeSMarri Devender Rao     }
1175968caeeSMarri Devender Rao     return -1;
1185968caeeSMarri Devender Rao }
1195968caeeSMarri Devender Rao 
1205968caeeSMarri Devender Rao /**
1215968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1225968caeeSMarri Devender Rao  */
1235968caeeSMarri Devender Rao class CertificateFile
1245968caeeSMarri Devender Rao {
1255968caeeSMarri Devender Rao   public:
1265968caeeSMarri Devender Rao     CertificateFile() = delete;
1275968caeeSMarri Devender Rao     CertificateFile(const CertificateFile &) = delete;
1285968caeeSMarri Devender Rao     CertificateFile &operator=(const CertificateFile &) = delete;
1295968caeeSMarri Devender Rao     CertificateFile(CertificateFile &&) = delete;
1305968caeeSMarri Devender Rao     CertificateFile &operator=(CertificateFile &&) = delete;
1315968caeeSMarri Devender Rao     CertificateFile(const std::string &certString)
1325968caeeSMarri Devender Rao     {
1335968caeeSMarri Devender Rao         char dirTemplate[] = "/tmp/Certs.XXXXXX";
1345968caeeSMarri Devender Rao         char *tempDirectory = mkdtemp(dirTemplate);
1355968caeeSMarri Devender Rao         if (tempDirectory)
1365968caeeSMarri Devender Rao         {
1375968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1385968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1395968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1405968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1415968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1425968caeeSMarri Devender Rao             out << certString;
1435968caeeSMarri Devender Rao             out.close();
1445968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile;
1455968caeeSMarri Devender Rao         }
1465968caeeSMarri Devender Rao     }
1475968caeeSMarri Devender Rao     ~CertificateFile()
1485968caeeSMarri Devender Rao     {
1495968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1505968caeeSMarri Devender Rao         {
1515968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile;
1525968caeeSMarri Devender Rao             try
1535968caeeSMarri Devender Rao             {
1545968caeeSMarri Devender Rao                 std::filesystem::remove_all(certDirectory);
1555968caeeSMarri Devender Rao             }
1565968caeeSMarri Devender Rao             catch (const std::filesystem::filesystem_error &e)
1575968caeeSMarri Devender Rao             {
1585968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1595968caeeSMarri Devender Rao                                  << certDirectory;
1605968caeeSMarri Devender Rao             }
1615968caeeSMarri Devender Rao         }
1625968caeeSMarri Devender Rao     }
1635968caeeSMarri Devender Rao     std::string getCertFilePath()
1645968caeeSMarri Devender Rao     {
1655968caeeSMarri Devender Rao         return certificateFile;
1665968caeeSMarri Devender Rao     }
1675968caeeSMarri Devender Rao 
1685968caeeSMarri Devender Rao   private:
1695968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1705968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1715968caeeSMarri Devender Rao };
1725968caeeSMarri Devender Rao 
17330215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher;
17430215816SMarri Devender Rao /**
17530215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
17630215816SMarri Devender Rao  *
17730215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
17830215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
17930215816SMarri Devender Rao  * @param[in] service D-Bus service name
18030215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
18130215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
18230215816SMarri Devender Rao  * @return None
18330215816SMarri Devender Rao  */
18430215816SMarri Devender Rao static void getCSR(const std::shared_ptr<AsyncResp> &asyncResp,
18530215816SMarri Devender Rao                    const std::string &certURI, const std::string &service,
18630215816SMarri Devender Rao                    const std::string &certObjPath,
18730215816SMarri Devender Rao                    const std::string &csrObjPath)
18830215816SMarri Devender Rao {
18930215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
19030215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
19130215816SMarri Devender Rao                      << " service=" << service;
19230215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
19330215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
19430215816SMarri Devender Rao                              const std::string &csr) {
19530215816SMarri Devender Rao             if (ec)
19630215816SMarri Devender Rao             {
19730215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
19830215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
19930215816SMarri Devender Rao                 return;
20030215816SMarri Devender Rao             }
20130215816SMarri Devender Rao             if (csr.empty())
20230215816SMarri Devender Rao             {
20330215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "CSR read is empty";
20430215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
20530215816SMarri Devender Rao                 return;
20630215816SMarri Devender Rao             }
20730215816SMarri Devender Rao             asyncResp->res.jsonValue["CSRString"] = csr;
20830215816SMarri Devender Rao             asyncResp->res.jsonValue["CertificateCollection"] = {
20930215816SMarri Devender Rao                 {"@odata.id", certURI}};
21030215816SMarri Devender Rao         },
21130215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
21230215816SMarri Devender Rao }
21330215816SMarri Devender Rao 
21430215816SMarri Devender Rao /**
21530215816SMarri Devender Rao  * Action to Generate CSR
21630215816SMarri Devender Rao  */
21730215816SMarri Devender Rao class CertificateActionGenerateCSR : public Node
21830215816SMarri Devender Rao {
21930215816SMarri Devender Rao   public:
22030215816SMarri Devender Rao     CertificateActionGenerateCSR(CrowApp &app) :
22130215816SMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/Actions/"
22230215816SMarri Devender Rao                   "CertificateService.GenerateCSR/")
22330215816SMarri Devender Rao     {
22430215816SMarri Devender Rao         entityPrivileges = {
22530215816SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
22630215816SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
22730215816SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
22830215816SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
22930215816SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
23030215816SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
23130215816SMarri Devender Rao     }
23230215816SMarri Devender Rao 
23330215816SMarri Devender Rao   private:
23430215816SMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
23530215816SMarri Devender Rao                 const std::vector<std::string> &params) override
23630215816SMarri Devender Rao     {
23730215816SMarri Devender Rao         static const int RSA_KEY_BIT_LENGTH = 2048;
23830215816SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
23930215816SMarri Devender Rao         // Required parameters
24030215816SMarri Devender Rao         std::string city;
24130215816SMarri Devender Rao         std::string commonName;
24230215816SMarri Devender Rao         std::string country;
24330215816SMarri Devender Rao         std::string organization;
24430215816SMarri Devender Rao         std::string organizationalUnit;
24530215816SMarri Devender Rao         std::string state;
24630215816SMarri Devender Rao         nlohmann::json certificateCollection;
24730215816SMarri Devender Rao 
24830215816SMarri Devender Rao         // Optional parameters
24930215816SMarri Devender Rao         std::optional<std::vector<std::string>> optAlternativeNames =
25030215816SMarri Devender Rao             std::vector<std::string>();
25130215816SMarri Devender Rao         std::optional<std::string> optContactPerson = "";
25230215816SMarri Devender Rao         std::optional<std::string> optChallengePassword = "";
25330215816SMarri Devender Rao         std::optional<std::string> optEmail = "";
25430215816SMarri Devender Rao         std::optional<std::string> optGivenName = "";
25530215816SMarri Devender Rao         std::optional<std::string> optInitials = "";
25630215816SMarri Devender Rao         std::optional<int64_t> optKeyBitLength = RSA_KEY_BIT_LENGTH;
25730215816SMarri Devender Rao         std::optional<std::string> optKeyCurveId = "prime256v1";
25830215816SMarri Devender Rao         std::optional<std::string> optKeyPairAlgorithm = "EC";
25930215816SMarri Devender Rao         std::optional<std::vector<std::string>> optKeyUsage =
26030215816SMarri Devender Rao             std::vector<std::string>();
26130215816SMarri Devender Rao         std::optional<std::string> optSurname = "";
26230215816SMarri Devender Rao         std::optional<std::string> optUnstructuredName = "";
26330215816SMarri Devender Rao         if (!json_util::readJson(
26430215816SMarri Devender Rao                 req, asyncResp->res, "City", city, "CommonName", commonName,
26530215816SMarri Devender Rao                 "ContactPerson", optContactPerson, "Country", country,
26630215816SMarri Devender Rao                 "Organization", organization, "OrganizationalUnit",
26730215816SMarri Devender Rao                 organizationalUnit, "State", state, "CertificateCollection",
26830215816SMarri Devender Rao                 certificateCollection, "AlternativeNames", optAlternativeNames,
26930215816SMarri Devender Rao                 "ChallengePassword", optChallengePassword, "Email", optEmail,
27030215816SMarri Devender Rao                 "GivenName", optGivenName, "Initials", optInitials,
27130215816SMarri Devender Rao                 "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
27230215816SMarri Devender Rao                 "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
27330215816SMarri Devender Rao                 optKeyUsage, "Surname", optSurname, "UnstructuredName",
27430215816SMarri Devender Rao                 optUnstructuredName))
27530215816SMarri Devender Rao         {
27630215816SMarri Devender Rao             return;
27730215816SMarri Devender Rao         }
27830215816SMarri Devender Rao 
27930215816SMarri Devender Rao         // bmcweb has no way to store or decode a private key challenge
28030215816SMarri Devender Rao         // password, which will likely cause bmcweb to crash on startup if this
28130215816SMarri Devender Rao         // is not set on a post so not allowing the user to set value
28230215816SMarri Devender Rao         if (*optChallengePassword != "")
28330215816SMarri Devender Rao         {
28430215816SMarri Devender Rao             messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
28530215816SMarri Devender Rao                                                   "ChallengePassword");
28630215816SMarri Devender Rao             return;
28730215816SMarri Devender Rao         }
28830215816SMarri Devender Rao 
28930215816SMarri Devender Rao         std::string certURI;
29030215816SMarri Devender Rao         if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
29130215816SMarri Devender Rao                                           "@odata.id", certURI))
29230215816SMarri Devender Rao         {
29330215816SMarri Devender Rao             return;
29430215816SMarri Devender Rao         }
29530215816SMarri Devender Rao 
29630215816SMarri Devender Rao         std::string objectPath;
29730215816SMarri Devender Rao         std::string service;
29830215816SMarri Devender Rao         if (boost::starts_with(
29930215816SMarri Devender Rao                 certURI,
30030215816SMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
30130215816SMarri Devender Rao         {
30230215816SMarri Devender Rao             objectPath = certs::httpsObjectPath;
30330215816SMarri Devender Rao             service = certs::httpsServiceName;
30430215816SMarri Devender Rao         }
3053b7f0149SMarri Devender Rao         else if (boost::starts_with(
3063b7f0149SMarri Devender Rao                      certURI, "/redfish/v1/AccountService/LDAP/Certificates"))
3073b7f0149SMarri Devender Rao         {
3083b7f0149SMarri Devender Rao             objectPath = certs::ldapObjectPath;
3093b7f0149SMarri Devender Rao             service = certs::ldapServiceName;
3103b7f0149SMarri Devender Rao         }
31130215816SMarri Devender Rao         else
31230215816SMarri Devender Rao         {
31330215816SMarri Devender Rao             messages::actionParameterNotSupported(
31430215816SMarri Devender Rao                 asyncResp->res, "CertificateCollection", "GenerateCSR");
31530215816SMarri Devender Rao             return;
31630215816SMarri Devender Rao         }
31730215816SMarri Devender Rao 
31830215816SMarri Devender Rao         // supporting only EC and RSA algorithm
31930215816SMarri Devender Rao         if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
32030215816SMarri Devender Rao         {
32130215816SMarri Devender Rao             messages::actionParameterNotSupported(
32230215816SMarri Devender Rao                 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
32330215816SMarri Devender Rao             return;
32430215816SMarri Devender Rao         }
32530215816SMarri Devender Rao 
32630215816SMarri Devender Rao         // supporting only 2048 key bit length for RSA algorithm due to time
32730215816SMarri Devender Rao         // consumed in generating private key
32830215816SMarri Devender Rao         if (*optKeyPairAlgorithm == "RSA" &&
32930215816SMarri Devender Rao             *optKeyBitLength != RSA_KEY_BIT_LENGTH)
33030215816SMarri Devender Rao         {
33130215816SMarri Devender Rao             messages::propertyValueNotInList(asyncResp->res,
33230215816SMarri Devender Rao                                              std::to_string(*optKeyBitLength),
33330215816SMarri Devender Rao                                              "KeyBitLength");
33430215816SMarri Devender Rao             return;
33530215816SMarri Devender Rao         }
33630215816SMarri Devender Rao 
33730215816SMarri Devender Rao         // validate KeyUsage supporting only 1 type based on URL
33830215816SMarri Devender Rao         if (boost::starts_with(
33930215816SMarri Devender Rao                 certURI,
34030215816SMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
34130215816SMarri Devender Rao         {
34230215816SMarri Devender Rao             if (optKeyUsage->size() == 0)
34330215816SMarri Devender Rao             {
34430215816SMarri Devender Rao                 optKeyUsage->push_back("ServerAuthentication");
34530215816SMarri Devender Rao             }
34630215816SMarri Devender Rao             else if (optKeyUsage->size() == 1)
34730215816SMarri Devender Rao             {
34830215816SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ServerAuthentication")
34930215816SMarri Devender Rao                 {
35030215816SMarri Devender Rao                     messages::propertyValueNotInList(
35130215816SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
35230215816SMarri Devender Rao                     return;
35330215816SMarri Devender Rao                 }
35430215816SMarri Devender Rao             }
35530215816SMarri Devender Rao             else
35630215816SMarri Devender Rao             {
35730215816SMarri Devender Rao                 messages::actionParameterNotSupported(
35830215816SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
35930215816SMarri Devender Rao                 return;
36030215816SMarri Devender Rao             }
36130215816SMarri Devender Rao         }
3623b7f0149SMarri Devender Rao         else if (boost::starts_with(
3633b7f0149SMarri Devender Rao                      certURI, "/redfish/v1/AccountService/LDAP/Certificates"))
3643b7f0149SMarri Devender Rao         {
3653b7f0149SMarri Devender Rao             if (optKeyUsage->size() == 0)
3663b7f0149SMarri Devender Rao             {
3673b7f0149SMarri Devender Rao                 optKeyUsage->push_back("ClientAuthentication");
3683b7f0149SMarri Devender Rao             }
3693b7f0149SMarri Devender Rao             else if (optKeyUsage->size() == 1)
3703b7f0149SMarri Devender Rao             {
3713b7f0149SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ClientAuthentication")
3723b7f0149SMarri Devender Rao                 {
3733b7f0149SMarri Devender Rao                     messages::propertyValueNotInList(
3743b7f0149SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3753b7f0149SMarri Devender Rao                     return;
3763b7f0149SMarri Devender Rao                 }
3773b7f0149SMarri Devender Rao             }
3783b7f0149SMarri Devender Rao             else
3793b7f0149SMarri Devender Rao             {
3803b7f0149SMarri Devender Rao                 messages::actionParameterNotSupported(
3813b7f0149SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
3823b7f0149SMarri Devender Rao                 return;
3833b7f0149SMarri Devender Rao             }
3843b7f0149SMarri Devender Rao         }
38530215816SMarri Devender Rao 
38630215816SMarri Devender Rao         // Only allow one CSR matcher at a time so setting retry time-out and
38730215816SMarri Devender Rao         // timer expiry to 10 seconds for now.
38830215816SMarri Devender Rao         static const int TIME_OUT = 10;
38930215816SMarri Devender Rao         if (csrMatcher)
39030215816SMarri Devender Rao         {
39130215816SMarri Devender Rao             res.addHeader("Retry-After", std::to_string(TIME_OUT));
39230215816SMarri Devender Rao             messages::serviceTemporarilyUnavailable(asyncResp->res,
39330215816SMarri Devender Rao                                                     std::to_string(TIME_OUT));
39430215816SMarri Devender Rao             return;
39530215816SMarri Devender Rao         }
39630215816SMarri Devender Rao 
39730215816SMarri Devender Rao         // Make this static so it survives outside this method
39830215816SMarri Devender Rao         static boost::asio::steady_timer timeout(*req.ioService);
39930215816SMarri Devender Rao         timeout.expires_after(std::chrono::seconds(TIME_OUT));
40030215816SMarri Devender Rao         timeout.async_wait([asyncResp](const boost::system::error_code &ec) {
40130215816SMarri Devender Rao             csrMatcher = nullptr;
40230215816SMarri Devender Rao             if (ec)
40330215816SMarri Devender Rao             {
40430215816SMarri Devender Rao                 // operation_aborted is expected if timer is canceled before
40530215816SMarri Devender Rao                 // completion.
40630215816SMarri Devender Rao                 if (ec != boost::asio::error::operation_aborted)
40730215816SMarri Devender Rao                 {
40830215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
40930215816SMarri Devender Rao                 }
41030215816SMarri Devender Rao                 return;
41130215816SMarri Devender Rao             }
41230215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
41330215816SMarri Devender Rao             messages::internalError(asyncResp->res);
41430215816SMarri Devender Rao         });
41530215816SMarri Devender Rao 
41630215816SMarri Devender Rao         // create a matcher to wait on CSR object
41730215816SMarri Devender Rao         BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
41830215816SMarri Devender Rao         std::string match("type='signal',"
41930215816SMarri Devender Rao                           "interface='org.freedesktop.DBus.ObjectManager',"
42030215816SMarri Devender Rao                           "path='" +
42130215816SMarri Devender Rao                           objectPath +
42230215816SMarri Devender Rao                           "',"
42330215816SMarri Devender Rao                           "member='InterfacesAdded'");
42430215816SMarri Devender Rao         csrMatcher = std::make_unique<sdbusplus::bus::match::match>(
42530215816SMarri Devender Rao             *crow::connections::systemBus, match,
42630215816SMarri Devender Rao             [asyncResp, service, objectPath,
42730215816SMarri Devender Rao              certURI](sdbusplus::message::message &m) {
42830215816SMarri Devender Rao                 boost::system::error_code ec;
42930215816SMarri Devender Rao                 timeout.cancel(ec);
43030215816SMarri Devender Rao                 if (ec)
43130215816SMarri Devender Rao                 {
43230215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "error canceling timer " << ec;
43330215816SMarri Devender Rao                     csrMatcher = nullptr;
43430215816SMarri Devender Rao                 }
43530215816SMarri Devender Rao                 if (m.is_method_error())
43630215816SMarri Devender Rao                 {
43730215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Dbus method error!!!";
43830215816SMarri Devender Rao                     messages::internalError(asyncResp->res);
43930215816SMarri Devender Rao                     return;
44030215816SMarri Devender Rao                 }
44130215816SMarri Devender Rao                 std::vector<std::pair<
44230215816SMarri Devender Rao                     std::string, std::vector<std::pair<
44330215816SMarri Devender Rao                                      std::string, std::variant<std::string>>>>>
44430215816SMarri Devender Rao                     interfacesProperties;
44530215816SMarri Devender Rao                 sdbusplus::message::object_path csrObjectPath;
44630215816SMarri Devender Rao                 m.read(csrObjectPath, interfacesProperties);
44730215816SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
44830215816SMarri Devender Rao                 for (auto &interface : interfacesProperties)
44930215816SMarri Devender Rao                 {
45030215816SMarri Devender Rao                     if (interface.first == "xyz.openbmc_project.Certs.CSR")
45130215816SMarri Devender Rao                     {
45230215816SMarri Devender Rao                         getCSR(asyncResp, certURI, service, objectPath,
45330215816SMarri Devender Rao                                csrObjectPath.str);
45430215816SMarri Devender Rao                         break;
45530215816SMarri Devender Rao                     }
45630215816SMarri Devender Rao                 }
45730215816SMarri Devender Rao             });
45830215816SMarri Devender Rao         crow::connections::systemBus->async_method_call(
45930215816SMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
46030215816SMarri Devender Rao                         const std::string &path) {
46130215816SMarri Devender Rao                 if (ec)
46230215816SMarri Devender Rao                 {
46330215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
46430215816SMarri Devender Rao                     messages::internalError(asyncResp->res);
46530215816SMarri Devender Rao                     return;
46630215816SMarri Devender Rao                 }
46730215816SMarri Devender Rao             },
46830215816SMarri Devender Rao             service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
46930215816SMarri Devender Rao             "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
47030215816SMarri Devender Rao             commonName, *optContactPerson, country, *optEmail, *optGivenName,
47130215816SMarri Devender Rao             *optInitials, *optKeyBitLength, *optKeyCurveId,
47230215816SMarri Devender Rao             *optKeyPairAlgorithm, *optKeyUsage, organization,
47330215816SMarri Devender Rao             organizationalUnit, state, *optSurname, *optUnstructuredName);
47430215816SMarri Devender Rao     }
47530215816SMarri Devender Rao }; // CertificateActionGenerateCSR
47630215816SMarri Devender Rao 
4775968caeeSMarri Devender Rao /**
4785968caeeSMarri Devender Rao  * @brief Parse and update Certficate Issue/Subject property
4795968caeeSMarri Devender Rao  *
4805968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4815968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4825968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4835968caeeSMarri Devender Rao  * @return None
4845968caeeSMarri Devender Rao  */
4855968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json &out,
4865968caeeSMarri Devender Rao                                       const std::string_view value)
4875968caeeSMarri Devender Rao {
4885968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
4895968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
4905968caeeSMarri Devender Rao     while (i != value.end())
4915968caeeSMarri Devender Rao     {
4925968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
4935968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
4945968caeeSMarri Devender Rao         {
4955968caeeSMarri Devender Rao             i++;
4965968caeeSMarri Devender Rao         }
4975968caeeSMarri Devender Rao         if (i == value.end())
4985968caeeSMarri Devender Rao         {
4995968caeeSMarri Devender Rao             break;
5005968caeeSMarri Devender Rao         }
5015968caeeSMarri Devender Rao         const std::string_view key(tokenBegin, i - tokenBegin);
5025968caeeSMarri Devender Rao         i++;
5035968caeeSMarri Devender Rao         tokenBegin = i;
5045968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
5055968caeeSMarri Devender Rao         {
5065968caeeSMarri Devender Rao             i++;
5075968caeeSMarri Devender Rao         }
5085968caeeSMarri Devender Rao         const std::string_view val(tokenBegin, i - tokenBegin);
5095968caeeSMarri Devender Rao         if (key == "L")
5105968caeeSMarri Devender Rao         {
5115968caeeSMarri Devender Rao             out["City"] = val;
5125968caeeSMarri Devender Rao         }
5135968caeeSMarri Devender Rao         else if (key == "CN")
5145968caeeSMarri Devender Rao         {
5155968caeeSMarri Devender Rao             out["CommonName"] = val;
5165968caeeSMarri Devender Rao         }
5175968caeeSMarri Devender Rao         else if (key == "C")
5185968caeeSMarri Devender Rao         {
5195968caeeSMarri Devender Rao             out["Country"] = val;
5205968caeeSMarri Devender Rao         }
5215968caeeSMarri Devender Rao         else if (key == "O")
5225968caeeSMarri Devender Rao         {
5235968caeeSMarri Devender Rao             out["Organization"] = val;
5245968caeeSMarri Devender Rao         }
5255968caeeSMarri Devender Rao         else if (key == "OU")
5265968caeeSMarri Devender Rao         {
5275968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5285968caeeSMarri Devender Rao         }
5295968caeeSMarri Devender Rao         else if (key == "ST")
5305968caeeSMarri Devender Rao         {
5315968caeeSMarri Devender Rao             out["State"] = val;
5325968caeeSMarri Devender Rao         }
5335968caeeSMarri Devender Rao         // skip comma character
5345968caeeSMarri Devender Rao         if (i != value.end())
5355968caeeSMarri Devender Rao         {
5365968caeeSMarri Devender Rao             i++;
5375968caeeSMarri Devender Rao         }
5385968caeeSMarri Devender Rao     }
5395968caeeSMarri Devender Rao }
5405968caeeSMarri Devender Rao 
5415968caeeSMarri Devender Rao /**
5425968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
5435968caeeSMarri Devender Rao  * message
5445968caeeSMarri Devender Rao  *
5455968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
5465968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
5475968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
5485968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
5495968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
5505968caeeSMarri Devender Rao  * @return None
5515968caeeSMarri Devender Rao  */
5525968caeeSMarri Devender Rao static void getCertificateProperties(
5535968caeeSMarri Devender Rao     const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath,
55437cce918SMarri Devender Rao     const std::string &service, long certId, const std::string &certURL,
55537cce918SMarri Devender Rao     const std::string &name)
5565968caeeSMarri Devender Rao {
5575968caeeSMarri Devender Rao     using PropertyType =
5585968caeeSMarri Devender Rao         std::variant<std::string, uint64_t, std::vector<std::string>>;
5595968caeeSMarri Devender Rao     using PropertiesMap = boost::container::flat_map<std::string, PropertyType>;
5605968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
5615968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
5625968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
56337cce918SMarri Devender Rao         [asyncResp, certURL, certId, name](const boost::system::error_code ec,
5645968caeeSMarri Devender Rao                                            const PropertiesMap &properties) {
5655968caeeSMarri Devender Rao             if (ec)
5665968caeeSMarri Devender Rao             {
5675968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5688aae75adSMarri Devender Rao                 messages::resourceNotFound(asyncResp->res, name,
5698aae75adSMarri Devender Rao                                            std::to_string(certId));
5705968caeeSMarri Devender Rao                 return;
5715968caeeSMarri Devender Rao             }
5725968caeeSMarri Devender Rao             asyncResp->res.jsonValue = {
5735968caeeSMarri Devender Rao                 {"@odata.id", certURL},
5745968caeeSMarri Devender Rao                 {"@odata.type", "#Certificate.v1_0_0.Certificate"},
5755968caeeSMarri Devender Rao                 {"@odata.context",
5765968caeeSMarri Devender Rao                  "/redfish/v1/$metadata#Certificate.Certificate"},
5775968caeeSMarri Devender Rao                 {"Id", std::to_string(certId)},
5785968caeeSMarri Devender Rao                 {"Name", name},
5795968caeeSMarri Devender Rao                 {"Description", name}};
5805968caeeSMarri Devender Rao             for (const auto &property : properties)
5815968caeeSMarri Devender Rao             {
5825968caeeSMarri Devender Rao                 if (property.first == "CertificateString")
5835968caeeSMarri Devender Rao                 {
5845968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = "";
5855968caeeSMarri Devender Rao                     const std::string *value =
5865968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
5875968caeeSMarri Devender Rao                     if (value)
5885968caeeSMarri Devender Rao                     {
58937cce918SMarri Devender Rao                         asyncResp->res.jsonValue["CertificateString"] = *value;
5905968caeeSMarri Devender Rao                     }
5915968caeeSMarri Devender Rao                 }
5925968caeeSMarri Devender Rao                 else if (property.first == "KeyUsage")
5935968caeeSMarri Devender Rao                 {
5945968caeeSMarri Devender Rao                     nlohmann::json &keyUsage =
5955968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["KeyUsage"];
5965968caeeSMarri Devender Rao                     keyUsage = nlohmann::json::array();
5975968caeeSMarri Devender Rao                     const std::vector<std::string> *value =
59837cce918SMarri Devender Rao                         std::get_if<std::vector<std::string>>(&property.second);
5995968caeeSMarri Devender Rao                     if (value)
6005968caeeSMarri Devender Rao                     {
6015968caeeSMarri Devender Rao                         for (const std::string &usage : *value)
6025968caeeSMarri Devender Rao                         {
6035968caeeSMarri Devender Rao                             keyUsage.push_back(usage);
6045968caeeSMarri Devender Rao                         }
6055968caeeSMarri Devender Rao                     }
6065968caeeSMarri Devender Rao                 }
6075968caeeSMarri Devender Rao                 else if (property.first == "Issuer")
6085968caeeSMarri Devender Rao                 {
6095968caeeSMarri Devender Rao                     const std::string *value =
6105968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
6115968caeeSMarri Devender Rao                     if (value)
6125968caeeSMarri Devender Rao                     {
6135968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
6145968caeeSMarri Devender Rao                             asyncResp->res.jsonValue["Issuer"], *value);
6155968caeeSMarri Devender Rao                     }
6165968caeeSMarri Devender Rao                 }
6175968caeeSMarri Devender Rao                 else if (property.first == "Subject")
6185968caeeSMarri Devender Rao                 {
6195968caeeSMarri Devender Rao                     const std::string *value =
6205968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
6215968caeeSMarri Devender Rao                     if (value)
6225968caeeSMarri Devender Rao                     {
6235968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
62437cce918SMarri Devender Rao                             asyncResp->res.jsonValue["Subject"], *value);
6255968caeeSMarri Devender Rao                     }
6265968caeeSMarri Devender Rao                 }
6275968caeeSMarri Devender Rao                 else if (property.first == "ValidNotAfter")
6285968caeeSMarri Devender Rao                 {
6295968caeeSMarri Devender Rao                     const uint64_t *value =
6305968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
6315968caeeSMarri Devender Rao                     if (value)
6325968caeeSMarri Devender Rao                     {
63337cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6345968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotAfter"] =
6355968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6365968caeeSMarri Devender Rao                     }
6375968caeeSMarri Devender Rao                 }
6385968caeeSMarri Devender Rao                 else if (property.first == "ValidNotBefore")
6395968caeeSMarri Devender Rao                 {
6405968caeeSMarri Devender Rao                     const uint64_t *value =
6415968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
6425968caeeSMarri Devender Rao                     if (value)
6435968caeeSMarri Devender Rao                     {
64437cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6455968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotBefore"] =
6465968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6475968caeeSMarri Devender Rao                     }
6485968caeeSMarri Devender Rao                 }
6495968caeeSMarri Devender Rao             }
6505968caeeSMarri Devender Rao             asyncResp->res.addHeader("Location", certURL);
6515968caeeSMarri Devender Rao         },
6525968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
6535968caeeSMarri Devender Rao         certs::certPropIntf);
6545968caeeSMarri Devender Rao }
6555968caeeSMarri Devender Rao 
6565968caeeSMarri Devender Rao using GetObjectType =
6575968caeeSMarri Devender Rao     std::vector<std::pair<std::string, std::vector<std::string>>>;
6585968caeeSMarri Devender Rao 
6595968caeeSMarri Devender Rao /**
6605968caeeSMarri Devender Rao  * Action to replace an existing certificate
6615968caeeSMarri Devender Rao  */
6625968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node
6635968caeeSMarri Devender Rao {
6645968caeeSMarri Devender Rao   public:
6655968caeeSMarri Devender Rao     CertificateActionsReplaceCertificate(CrowApp &app) :
6665968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/Actions/"
6675968caeeSMarri Devender Rao                   "CertificateService.ReplaceCertificate/")
6685968caeeSMarri Devender Rao     {
6695968caeeSMarri Devender Rao         entityPrivileges = {
6705968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
6715968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
6725968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
6735968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
6745968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
6755968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
6765968caeeSMarri Devender Rao     }
6775968caeeSMarri Devender Rao 
6785968caeeSMarri Devender Rao   private:
6795968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
6805968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
6815968caeeSMarri Devender Rao     {
6825968caeeSMarri Devender Rao         std::string certificate;
6835968caeeSMarri Devender Rao         nlohmann::json certificateUri;
6845968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
6855968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
6865968caeeSMarri Devender Rao         if (!json_util::readJson(req, asyncResp->res, "CertificateString",
6875968caeeSMarri Devender Rao                                  certificate, "CertificateUri", certificateUri,
6885968caeeSMarri Devender Rao                                  "CertificateType", certificateType))
6895968caeeSMarri Devender Rao         {
6905968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
6915968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
6925968caeeSMarri Devender Rao             return;
6935968caeeSMarri Devender Rao         }
6945968caeeSMarri Devender Rao 
6955968caeeSMarri Devender Rao         if (!certificateType)
6965968caeeSMarri Devender Rao         {
6975968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
6985968caeeSMarri Devender Rao             return;
6995968caeeSMarri Devender Rao         }
7005968caeeSMarri Devender Rao         if (certificateType != "PEM")
7015968caeeSMarri Devender Rao         {
7025968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
7035968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
7045968caeeSMarri Devender Rao             return;
7055968caeeSMarri Devender Rao         }
7065968caeeSMarri Devender Rao 
7075968caeeSMarri Devender Rao         std::string certURI;
7085968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7095968caeeSMarri Devender Rao                                           "@odata.id", certURI))
7105968caeeSMarri Devender Rao         {
7115968caeeSMarri Devender Rao             messages::actionParameterMissing(
7125968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
7135968caeeSMarri Devender Rao             return;
7145968caeeSMarri Devender Rao         }
7155968caeeSMarri Devender Rao 
7165968caeeSMarri Devender Rao         BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
7175968caeeSMarri Devender Rao         long id = getIDFromURL(certURI);
7185968caeeSMarri Devender Rao         if (id < 0)
7195968caeeSMarri Devender Rao         {
7205968caeeSMarri Devender Rao             messages::actionParameterValueFormatError(asyncResp->res, certURI,
7215968caeeSMarri Devender Rao                                                       "CertificateUri",
7225968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
7235968caeeSMarri Devender Rao             return;
7245968caeeSMarri Devender Rao         }
7255968caeeSMarri Devender Rao         std::string objectPath;
7265968caeeSMarri Devender Rao         std::string name;
72737cce918SMarri Devender Rao         std::string service;
7285968caeeSMarri Devender Rao         if (boost::starts_with(
7295968caeeSMarri Devender Rao                 certURI,
7305968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"))
7315968caeeSMarri Devender Rao         {
7325968caeeSMarri Devender Rao             objectPath =
7335968caeeSMarri Devender Rao                 std::string(certs::httpsObjectPath) + "/" + std::to_string(id);
7345968caeeSMarri Devender Rao             name = "HTTPS certificate";
73537cce918SMarri Devender Rao             service = certs::httpsServiceName;
73637cce918SMarri Devender Rao         }
73737cce918SMarri Devender Rao         else if (boost::starts_with(
73837cce918SMarri Devender Rao                      certURI, "/redfish/v1/AccountService/LDAP/Certificates/"))
73937cce918SMarri Devender Rao         {
74037cce918SMarri Devender Rao             objectPath =
74137cce918SMarri Devender Rao                 std::string(certs::ldapObjectPath) + "/" + std::to_string(id);
74237cce918SMarri Devender Rao             name = "LDAP certificate";
74337cce918SMarri Devender Rao             service = certs::ldapServiceName;
7445968caeeSMarri Devender Rao         }
745*cfcd5f6bSMarri Devender Rao         else if (boost::starts_with(
746*cfcd5f6bSMarri Devender Rao                      certURI,
747*cfcd5f6bSMarri Devender Rao                      "/redfish/v1/Managers/bmc/Truststore/Certificates/"))
748*cfcd5f6bSMarri Devender Rao         {
749*cfcd5f6bSMarri Devender Rao             objectPath = std::string(certs::authorityObjectPath) + "/" +
750*cfcd5f6bSMarri Devender Rao                          std::to_string(id);
751*cfcd5f6bSMarri Devender Rao             name = "TrustStore certificate";
752*cfcd5f6bSMarri Devender Rao             service = certs::authorityServiceName;
753*cfcd5f6bSMarri Devender Rao         }
7545968caeeSMarri Devender Rao         else
7555968caeeSMarri Devender Rao         {
7565968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
7575968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
7585968caeeSMarri Devender Rao             return;
7595968caeeSMarri Devender Rao         }
7605968caeeSMarri Devender Rao 
7615968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
7625968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
7635968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
76437cce918SMarri Devender Rao             [asyncResp, certFile, objectPath, service, certURI, id,
7655968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
7665968caeeSMarri Devender Rao                 if (ec)
7675968caeeSMarri Devender Rao                 {
7685968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
7698aae75adSMarri Devender Rao                     messages::resourceNotFound(asyncResp->res, name,
7708aae75adSMarri Devender Rao                                                std::to_string(id));
7715968caeeSMarri Devender Rao                     return;
7725968caeeSMarri Devender Rao                 }
77337cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath, service, id,
7745968caeeSMarri Devender Rao                                          certURI, name);
7755968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
7765968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
7775968caeeSMarri Devender Rao             },
7785968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
7795968caeeSMarri Devender Rao             certFile->getCertFilePath());
7805968caeeSMarri Devender Rao     }
7815968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate
7825968caeeSMarri Devender Rao 
7835968caeeSMarri Devender Rao /**
7845968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
7855968caeeSMarri Devender Rao  * of a component, account or service.
7865968caeeSMarri Devender Rao  */
7875968caeeSMarri Devender Rao class HTTPSCertificate : public Node
7885968caeeSMarri Devender Rao {
7895968caeeSMarri Devender Rao   public:
7905968caeeSMarri Devender Rao     template <typename CrowApp>
7915968caeeSMarri Devender Rao     HTTPSCertificate(CrowApp &app) :
7925968caeeSMarri Devender Rao         Node(app,
7935968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
7945968caeeSMarri Devender Rao              "<str>/",
7955968caeeSMarri Devender Rao              std::string())
7965968caeeSMarri Devender Rao     {
7975968caeeSMarri Devender Rao         entityPrivileges = {
7985968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
7995968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
8005968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
8015968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
8025968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
8035968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
8045968caeeSMarri Devender Rao     }
8055968caeeSMarri Devender Rao 
8065968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
8075968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
8085968caeeSMarri Devender Rao     {
8095968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
8105968caeeSMarri Devender Rao         if (params.size() != 1)
8115968caeeSMarri Devender Rao         {
8125968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
8135968caeeSMarri Devender Rao             return;
8145968caeeSMarri Devender Rao         }
8155968caeeSMarri Devender Rao         long id = getIDFromURL(req.url);
8165968caeeSMarri Devender Rao 
8175968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id);
8185968caeeSMarri Devender Rao         std::string certURL =
8195968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
8205968caeeSMarri Devender Rao             std::to_string(id);
8215968caeeSMarri Devender Rao         std::string objectPath = certs::httpsObjectPath;
8225968caeeSMarri Devender Rao         objectPath += "/";
8235968caeeSMarri Devender Rao         objectPath += std::to_string(id);
82437cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
82537cce918SMarri Devender Rao                                  id, certURL, "HTTPS Certificate");
8265968caeeSMarri Devender Rao     }
8275968caeeSMarri Devender Rao 
8285968caeeSMarri Devender Rao }; // namespace redfish
8295968caeeSMarri Devender Rao 
8305968caeeSMarri Devender Rao /**
8315968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8325968caeeSMarri Devender Rao  */
8335968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node
8345968caeeSMarri Devender Rao {
8355968caeeSMarri Devender Rao   public:
8365968caeeSMarri Devender Rao     template <typename CrowApp>
8375968caeeSMarri Devender Rao     HTTPSCertificateCollection(CrowApp &app) :
8385968caeeSMarri Devender Rao         Node(app,
8395968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
8405968caeeSMarri Devender Rao     {
8415968caeeSMarri Devender Rao         entityPrivileges = {
8425968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
8435968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
8445968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
8455968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
8465968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
8475968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
8485968caeeSMarri Devender Rao     }
8495968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
8505968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
8515968caeeSMarri Devender Rao     {
8525968caeeSMarri Devender Rao         res.jsonValue = {
8535968caeeSMarri Devender Rao             {"@odata.id",
8545968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
8555968caeeSMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
8565968caeeSMarri Devender Rao             {"@odata.context",
8575968caeeSMarri Devender Rao              "/redfish/v1/"
8585968caeeSMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
8595968caeeSMarri Devender Rao             {"Name", "HTTPS Certificates Collection"},
8605968caeeSMarri Devender Rao             {"Description", "A Collection of HTTPS certificate instances"}};
8615968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
8625968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
8635968caeeSMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
8645968caeeSMarri Devender Rao                         const ManagedObjectType &certs) {
8655968caeeSMarri Devender Rao                 if (ec)
8665968caeeSMarri Devender Rao                 {
8675968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8685968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
8695968caeeSMarri Devender Rao                     return;
8705968caeeSMarri Devender Rao                 }
87137cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
8725968caeeSMarri Devender Rao                 members = nlohmann::json::array();
8735968caeeSMarri Devender Rao                 for (const auto &cert : certs)
8745968caeeSMarri Devender Rao                 {
8755968caeeSMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
87637cce918SMarri Devender Rao                     if (id >= 0)
8775968caeeSMarri Devender Rao                     {
8785968caeeSMarri Devender Rao                         members.push_back(
8795968caeeSMarri Devender Rao                             {{"@odata.id",
8805968caeeSMarri Devender Rao                               "/redfish/v1/Managers/bmc/"
8815968caeeSMarri Devender Rao                               "NetworkProtocol/HTTPS/Certificates/" +
8825968caeeSMarri Devender Rao                                   std::to_string(id)}});
8835968caeeSMarri Devender Rao                     }
8845968caeeSMarri Devender Rao                 }
8855968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
8865968caeeSMarri Devender Rao                     members.size();
8875968caeeSMarri Devender Rao             },
88837cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
88937cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
8905968caeeSMarri Devender Rao     }
8915968caeeSMarri Devender Rao 
8925968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
8935968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
8945968caeeSMarri Devender Rao     {
8955968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
8965968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
8975968caeeSMarri Devender Rao         asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"},
8985968caeeSMarri Devender Rao                                     {"Description", "HTTPS Certificate"}};
8995968caeeSMarri Devender Rao 
9005968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
9015968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
9025968caeeSMarri Devender Rao 
9035968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
9045968caeeSMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
9055968caeeSMarri Devender Rao                 if (ec)
9065968caeeSMarri Devender Rao                 {
9075968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
9085968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
9095968caeeSMarri Devender Rao                     return;
9105968caeeSMarri Devender Rao                 }
9115968caeeSMarri Devender Rao                 // TODO: Issue#84 supporting only 1 certificate
9125968caeeSMarri Devender Rao                 long certId = 1;
9135968caeeSMarri Devender Rao                 std::string certURL =
9145968caeeSMarri Devender Rao                     "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
9155968caeeSMarri Devender Rao                     "Certificates/" +
9165968caeeSMarri Devender Rao                     std::to_string(certId);
91737cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::httpsObjectPath) +
91837cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
91937cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
92037cce918SMarri Devender Rao                                          certs::httpsServiceName, certId,
9215968caeeSMarri Devender Rao                                          certURL, "HTTPS Certificate");
9225968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9235968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
9245968caeeSMarri Devender Rao             },
92537cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
92637cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
9275968caeeSMarri Devender Rao     }
9285968caeeSMarri Devender Rao }; // HTTPSCertificateCollection
9295968caeeSMarri Devender Rao 
9305968caeeSMarri Devender Rao /**
9315968caeeSMarri Devender Rao  * The certificate location schema defines a resource that an administrator
9325968caeeSMarri Devender Rao  * can use in order to locate all certificates installed on a given service.
9335968caeeSMarri Devender Rao  */
9345968caeeSMarri Devender Rao class CertificateLocations : public Node
9355968caeeSMarri Devender Rao {
9365968caeeSMarri Devender Rao   public:
9375968caeeSMarri Devender Rao     template <typename CrowApp>
9385968caeeSMarri Devender Rao     CertificateLocations(CrowApp &app) :
9395968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/CertificateLocations/")
9405968caeeSMarri Devender Rao     {
9415968caeeSMarri Devender Rao         entityPrivileges = {
9425968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
9435968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
9445968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
9455968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
9465968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
9475968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
9485968caeeSMarri Devender Rao     }
9495968caeeSMarri Devender Rao 
9505968caeeSMarri Devender Rao   private:
9515968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
9525968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
9535968caeeSMarri Devender Rao     {
9545968caeeSMarri Devender Rao         res.jsonValue = {
9555968caeeSMarri Devender Rao             {"@odata.id",
9565968caeeSMarri Devender Rao              "/redfish/v1/CertificateService/CertificateLocations"},
9575968caeeSMarri Devender Rao             {"@odata.type",
9585968caeeSMarri Devender Rao              "#CertificateLocations.v1_0_0.CertificateLocations"},
9595968caeeSMarri Devender Rao             {"@odata.context",
9605968caeeSMarri Devender Rao              "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"},
9615968caeeSMarri Devender Rao             {"Name", "Certificate Locations"},
9625968caeeSMarri Devender Rao             {"Id", "CertificateLocations"},
9635968caeeSMarri Devender Rao             {"Description",
9645968caeeSMarri Devender Rao              "Defines a resource that an administrator can use in order to "
9655968caeeSMarri Devender Rao              "locate all certificates installed on a given service"}};
9665968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
9675968caeeSMarri Devender Rao         nlohmann::json &links =
9685968caeeSMarri Devender Rao             asyncResp->res.jsonValue["Links"]["Certificates"];
9695968caeeSMarri Devender Rao         links = nlohmann::json::array();
9705968caeeSMarri Devender Rao         getCertificateLocations(
9715968caeeSMarri Devender Rao             asyncResp,
9725968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
97337cce918SMarri Devender Rao             certs::httpsObjectPath, certs::httpsServiceName);
97437cce918SMarri Devender Rao         getCertificateLocations(asyncResp,
97537cce918SMarri Devender Rao                                 "/redfish/v1/AccountService/LDAP/Certificates/",
97637cce918SMarri Devender Rao                                 certs::ldapObjectPath, certs::ldapServiceName);
977*cfcd5f6bSMarri Devender Rao         getCertificateLocations(
978*cfcd5f6bSMarri Devender Rao             asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/",
979*cfcd5f6bSMarri Devender Rao             certs::authorityObjectPath, certs::authorityServiceName);
98037cce918SMarri Devender Rao     }
98137cce918SMarri Devender Rao     /**
98237cce918SMarri Devender Rao      * @brief Retrieve the certificates installed list and append to the
98337cce918SMarri Devender Rao      * response
98437cce918SMarri Devender Rao      *
98537cce918SMarri Devender Rao      * @param[in] asyncResp Shared pointer to the response message
98637cce918SMarri Devender Rao      * @param[in] certURL  Path of the certificate object
98737cce918SMarri Devender Rao      * @param[in] path  Path of the D-Bus service object
98837cce918SMarri Devender Rao      * @return None
98937cce918SMarri Devender Rao      */
99037cce918SMarri Devender Rao     void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp,
99137cce918SMarri Devender Rao                                  const std::string &certURL,
99237cce918SMarri Devender Rao                                  const std::string &path,
99337cce918SMarri Devender Rao                                  const std::string &service)
99437cce918SMarri Devender Rao     {
99537cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
99637cce918SMarri Devender Rao                          << " Path=" << path << " service= " << service;
99737cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
99837cce918SMarri Devender Rao             [asyncResp, certURL](const boost::system::error_code ec,
99937cce918SMarri Devender Rao                                  const ManagedObjectType &certs) {
100037cce918SMarri Devender Rao                 if (ec)
100137cce918SMarri Devender Rao                 {
100237cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
100337cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
100437cce918SMarri Devender Rao                     return;
100537cce918SMarri Devender Rao                 }
100637cce918SMarri Devender Rao                 nlohmann::json &links =
100737cce918SMarri Devender Rao                     asyncResp->res.jsonValue["Links"]["Certificates"];
100837cce918SMarri Devender Rao                 for (auto &cert : certs)
100937cce918SMarri Devender Rao                 {
101037cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
101137cce918SMarri Devender Rao                     if (id >= 0)
101237cce918SMarri Devender Rao                     {
101337cce918SMarri Devender Rao                         links.push_back(
101437cce918SMarri Devender Rao                             {{"@odata.id", certURL + std::to_string(id)}});
101537cce918SMarri Devender Rao                     }
101637cce918SMarri Devender Rao                 }
101737cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
101837cce918SMarri Devender Rao                     links.size();
101937cce918SMarri Devender Rao             },
102037cce918SMarri Devender Rao             service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
10215968caeeSMarri Devender Rao     }
10225968caeeSMarri Devender Rao }; // CertificateLocations
102337cce918SMarri Devender Rao 
102437cce918SMarri Devender Rao /**
102537cce918SMarri Devender Rao  * Collection of LDAP certificates
102637cce918SMarri Devender Rao  */
102737cce918SMarri Devender Rao class LDAPCertificateCollection : public Node
102837cce918SMarri Devender Rao {
102937cce918SMarri Devender Rao   public:
103037cce918SMarri Devender Rao     template <typename CrowApp>
103137cce918SMarri Devender Rao     LDAPCertificateCollection(CrowApp &app) :
103237cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/")
103337cce918SMarri Devender Rao     {
103437cce918SMarri Devender Rao         entityPrivileges = {
103537cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
103637cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
103737cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
103837cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
103937cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
104037cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
104137cce918SMarri Devender Rao     }
104237cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
104337cce918SMarri Devender Rao                const std::vector<std::string> &params) override
104437cce918SMarri Devender Rao     {
104537cce918SMarri Devender Rao         res.jsonValue = {
104637cce918SMarri Devender Rao             {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"},
104737cce918SMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
104837cce918SMarri Devender Rao             {"@odata.context",
104937cce918SMarri Devender Rao              "/redfish/v1/"
105037cce918SMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
105137cce918SMarri Devender Rao             {"Name", "LDAP Certificates Collection"},
105237cce918SMarri Devender Rao             {"Description", "A Collection of LDAP certificate instances"}};
105337cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
105437cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
105537cce918SMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
105637cce918SMarri Devender Rao                         const ManagedObjectType &certs) {
105737cce918SMarri Devender Rao                 if (ec)
105837cce918SMarri Devender Rao                 {
105937cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
106037cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
106137cce918SMarri Devender Rao                     return;
106237cce918SMarri Devender Rao                 }
106337cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
106437cce918SMarri Devender Rao                 members = nlohmann::json::array();
106537cce918SMarri Devender Rao                 for (const auto &cert : certs)
106637cce918SMarri Devender Rao                 {
106737cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
106837cce918SMarri Devender Rao                     if (id >= 0)
106937cce918SMarri Devender Rao                     {
107037cce918SMarri Devender Rao                         members.push_back(
107137cce918SMarri Devender Rao                             {{"@odata.id", "/redfish/v1/AccountService/"
107237cce918SMarri Devender Rao                                            "LDAP/Certificates/" +
107337cce918SMarri Devender Rao                                                std::to_string(id)}});
107437cce918SMarri Devender Rao                     }
107537cce918SMarri Devender Rao                 }
107637cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
107737cce918SMarri Devender Rao                     members.size();
107837cce918SMarri Devender Rao             },
107937cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
108037cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
108137cce918SMarri Devender Rao     }
108237cce918SMarri Devender Rao 
108337cce918SMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
108437cce918SMarri Devender Rao                 const std::vector<std::string> &params) override
108537cce918SMarri Devender Rao     {
108637cce918SMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
108737cce918SMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
108837cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
108937cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
109037cce918SMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
109137cce918SMarri Devender Rao                 if (ec)
109237cce918SMarri Devender Rao                 {
109337cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
109437cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
109537cce918SMarri Devender Rao                     return;
109637cce918SMarri Devender Rao                 }
109737cce918SMarri Devender Rao                 //// TODO: Issue#84 supporting only 1 certificate
109837cce918SMarri Devender Rao                 long certId = 1;
109937cce918SMarri Devender Rao                 std::string certURL =
110037cce918SMarri Devender Rao                     "/redfish/v1/AccountService/LDAP/Certificates/" +
110137cce918SMarri Devender Rao                     std::to_string(certId);
110237cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::ldapObjectPath) +
110337cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
110437cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
110537cce918SMarri Devender Rao                                          certs::ldapServiceName, certId,
110637cce918SMarri Devender Rao                                          certURL, "LDAP Certificate");
110737cce918SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "LDAP certificate install file="
110837cce918SMarri Devender Rao                                  << certFile->getCertFilePath();
110937cce918SMarri Devender Rao             },
111037cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
111137cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
111237cce918SMarri Devender Rao     }
111337cce918SMarri Devender Rao }; // LDAPCertificateCollection
111437cce918SMarri Devender Rao 
111537cce918SMarri Devender Rao /**
111637cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
111737cce918SMarri Devender Rao  * of a component, account or service.
111837cce918SMarri Devender Rao  */
111937cce918SMarri Devender Rao class LDAPCertificate : public Node
112037cce918SMarri Devender Rao {
112137cce918SMarri Devender Rao   public:
112237cce918SMarri Devender Rao     template <typename CrowApp>
112337cce918SMarri Devender Rao     LDAPCertificate(CrowApp &app) :
112437cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/",
112537cce918SMarri Devender Rao              std::string())
112637cce918SMarri Devender Rao     {
112737cce918SMarri Devender Rao         entityPrivileges = {
112837cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
112937cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
113037cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
113137cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
113237cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
113337cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
113437cce918SMarri Devender Rao     }
113537cce918SMarri Devender Rao 
113637cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
113737cce918SMarri Devender Rao                const std::vector<std::string> &params) override
113837cce918SMarri Devender Rao     {
113937cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
114037cce918SMarri Devender Rao         long id = getIDFromURL(req.url);
114137cce918SMarri Devender Rao         if (id < 0)
114237cce918SMarri Devender Rao         {
114337cce918SMarri Devender Rao             BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
114437cce918SMarri Devender Rao             messages::internalError(asyncResp->res);
114537cce918SMarri Devender Rao             return;
114637cce918SMarri Devender Rao         }
114737cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id);
114837cce918SMarri Devender Rao         std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" +
114937cce918SMarri Devender Rao                               std::to_string(id);
115037cce918SMarri Devender Rao         std::string objectPath = certs::ldapObjectPath;
115137cce918SMarri Devender Rao         objectPath += "/";
115237cce918SMarri Devender Rao         objectPath += std::to_string(id);
115337cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
115437cce918SMarri Devender Rao                                  id, certURL, "LDAP Certificate");
115537cce918SMarri Devender Rao     }
115637cce918SMarri Devender Rao }; // LDAPCertificate
1157*cfcd5f6bSMarri Devender Rao /**
1158*cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1159*cfcd5f6bSMarri Devender Rao  */
1160*cfcd5f6bSMarri Devender Rao class TrustStoreCertificateCollection : public Node
1161*cfcd5f6bSMarri Devender Rao {
1162*cfcd5f6bSMarri Devender Rao   public:
1163*cfcd5f6bSMarri Devender Rao     template <typename CrowApp>
1164*cfcd5f6bSMarri Devender Rao     TrustStoreCertificateCollection(CrowApp &app) :
1165*cfcd5f6bSMarri Devender Rao         Node(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1166*cfcd5f6bSMarri Devender Rao     {
1167*cfcd5f6bSMarri Devender Rao         entityPrivileges = {
1168*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
1169*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
1170*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1171*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1172*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1173*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1174*cfcd5f6bSMarri Devender Rao     }
1175*cfcd5f6bSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
1176*cfcd5f6bSMarri Devender Rao                const std::vector<std::string> &params) override
1177*cfcd5f6bSMarri Devender Rao     {
1178*cfcd5f6bSMarri Devender Rao         res.jsonValue = {
1179*cfcd5f6bSMarri Devender Rao             {"@odata.id", "/redfish/v1/Managers/bmc/Truststore/Certificates/"},
1180*cfcd5f6bSMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
1181*cfcd5f6bSMarri Devender Rao             {"@odata.context",
1182*cfcd5f6bSMarri Devender Rao              "/redfish/v1/"
1183*cfcd5f6bSMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
1184*cfcd5f6bSMarri Devender Rao             {"Name", "TrustStore Certificates Collection"},
1185*cfcd5f6bSMarri Devender Rao             {"Description",
1186*cfcd5f6bSMarri Devender Rao              "A Collection of TrustStore certificate instances"}};
1187*cfcd5f6bSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
1188*cfcd5f6bSMarri Devender Rao         crow::connections::systemBus->async_method_call(
1189*cfcd5f6bSMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
1190*cfcd5f6bSMarri Devender Rao                         const ManagedObjectType &certs) {
1191*cfcd5f6bSMarri Devender Rao                 if (ec)
1192*cfcd5f6bSMarri Devender Rao                 {
1193*cfcd5f6bSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1194*cfcd5f6bSMarri Devender Rao                     messages::internalError(asyncResp->res);
1195*cfcd5f6bSMarri Devender Rao                     return;
1196*cfcd5f6bSMarri Devender Rao                 }
1197*cfcd5f6bSMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
1198*cfcd5f6bSMarri Devender Rao                 members = nlohmann::json::array();
1199*cfcd5f6bSMarri Devender Rao                 for (const auto &cert : certs)
1200*cfcd5f6bSMarri Devender Rao                 {
1201*cfcd5f6bSMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
1202*cfcd5f6bSMarri Devender Rao                     if (id >= 0)
1203*cfcd5f6bSMarri Devender Rao                     {
1204*cfcd5f6bSMarri Devender Rao                         members.push_back(
1205*cfcd5f6bSMarri Devender Rao                             {{"@odata.id", "/redfish/v1/Managers/bmc/"
1206*cfcd5f6bSMarri Devender Rao                                            "Truststore/Certificates/" +
1207*cfcd5f6bSMarri Devender Rao                                                std::to_string(id)}});
1208*cfcd5f6bSMarri Devender Rao                     }
1209*cfcd5f6bSMarri Devender Rao                 }
1210*cfcd5f6bSMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
1211*cfcd5f6bSMarri Devender Rao                     members.size();
1212*cfcd5f6bSMarri Devender Rao             },
1213*cfcd5f6bSMarri Devender Rao             certs::authorityServiceName, certs::authorityObjectPath,
1214*cfcd5f6bSMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
1215*cfcd5f6bSMarri Devender Rao     }
1216*cfcd5f6bSMarri Devender Rao 
1217*cfcd5f6bSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
1218*cfcd5f6bSMarri Devender Rao                 const std::vector<std::string> &params) override
1219*cfcd5f6bSMarri Devender Rao     {
1220*cfcd5f6bSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
1221*cfcd5f6bSMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
1222*cfcd5f6bSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
1223*cfcd5f6bSMarri Devender Rao         crow::connections::systemBus->async_method_call(
1224*cfcd5f6bSMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
1225*cfcd5f6bSMarri Devender Rao                 if (ec)
1226*cfcd5f6bSMarri Devender Rao                 {
1227*cfcd5f6bSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1228*cfcd5f6bSMarri Devender Rao                     messages::internalError(asyncResp->res);
1229*cfcd5f6bSMarri Devender Rao                     return;
1230*cfcd5f6bSMarri Devender Rao                 }
1231*cfcd5f6bSMarri Devender Rao                 //// TODO: Issue#84 supporting only 1 certificate
1232*cfcd5f6bSMarri Devender Rao                 long certId = 1;
1233*cfcd5f6bSMarri Devender Rao                 std::string certURL = "/redfish/v1/Managers/bmc/"
1234*cfcd5f6bSMarri Devender Rao                                       "Truststore/Certificates/" +
1235*cfcd5f6bSMarri Devender Rao                                       std::to_string(certId);
1236*cfcd5f6bSMarri Devender Rao                 std::string objectPath =
1237*cfcd5f6bSMarri Devender Rao                     std::string(certs::authorityObjectPath) + "/" +
1238*cfcd5f6bSMarri Devender Rao                     std::to_string(certId);
1239*cfcd5f6bSMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
1240*cfcd5f6bSMarri Devender Rao                                          certs::authorityServiceName, certId,
1241*cfcd5f6bSMarri Devender Rao                                          certURL, "TrustStore Certificate");
1242*cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
1243*cfcd5f6bSMarri Devender Rao                                  << certFile->getCertFilePath();
1244*cfcd5f6bSMarri Devender Rao             },
1245*cfcd5f6bSMarri Devender Rao             certs::authorityServiceName, certs::authorityObjectPath,
1246*cfcd5f6bSMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
1247*cfcd5f6bSMarri Devender Rao     }
1248*cfcd5f6bSMarri Devender Rao }; // TrustStoreCertificateCollection
1249*cfcd5f6bSMarri Devender Rao 
1250*cfcd5f6bSMarri Devender Rao /**
1251*cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1252*cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1253*cfcd5f6bSMarri Devender Rao  */
1254*cfcd5f6bSMarri Devender Rao class TrustStoreCertificate : public Node
1255*cfcd5f6bSMarri Devender Rao {
1256*cfcd5f6bSMarri Devender Rao   public:
1257*cfcd5f6bSMarri Devender Rao     template <typename CrowApp>
1258*cfcd5f6bSMarri Devender Rao     TrustStoreCertificate(CrowApp &app) :
1259*cfcd5f6bSMarri Devender Rao         Node(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/",
1260*cfcd5f6bSMarri Devender Rao              std::string())
1261*cfcd5f6bSMarri Devender Rao     {
1262*cfcd5f6bSMarri Devender Rao         entityPrivileges = {
1263*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
1264*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
1265*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1266*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1267*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1268*cfcd5f6bSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1269*cfcd5f6bSMarri Devender Rao     }
1270*cfcd5f6bSMarri Devender Rao 
1271*cfcd5f6bSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
1272*cfcd5f6bSMarri Devender Rao                const std::vector<std::string> &params) override
1273*cfcd5f6bSMarri Devender Rao     {
1274*cfcd5f6bSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
1275*cfcd5f6bSMarri Devender Rao         long id = getIDFromURL(req.url);
1276*cfcd5f6bSMarri Devender Rao         if (id < 0)
1277*cfcd5f6bSMarri Devender Rao         {
1278*cfcd5f6bSMarri Devender Rao             BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
1279*cfcd5f6bSMarri Devender Rao             messages::internalError(asyncResp->res);
1280*cfcd5f6bSMarri Devender Rao             return;
1281*cfcd5f6bSMarri Devender Rao         }
1282*cfcd5f6bSMarri Devender Rao         BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID="
1283*cfcd5f6bSMarri Devender Rao                          << std::to_string(id);
1284*cfcd5f6bSMarri Devender Rao         std::string certURL =
1285*cfcd5f6bSMarri Devender Rao             "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1286*cfcd5f6bSMarri Devender Rao             std::to_string(id);
1287*cfcd5f6bSMarri Devender Rao         std::string objectPath = certs::authorityObjectPath;
1288*cfcd5f6bSMarri Devender Rao         objectPath += "/";
1289*cfcd5f6bSMarri Devender Rao         objectPath += std::to_string(id);
1290*cfcd5f6bSMarri Devender Rao         getCertificateProperties(asyncResp, objectPath,
1291*cfcd5f6bSMarri Devender Rao                                  certs::authorityServiceName, id, certURL,
1292*cfcd5f6bSMarri Devender Rao                                  "TrustStore Certificate");
1293*cfcd5f6bSMarri Devender Rao     }
1294*cfcd5f6bSMarri Devender Rao }; // TrustStoreCertificate
12955968caeeSMarri Devender Rao } // namespace redfish
1296