xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 37cce918ede6489ab980712c243b526a30396ca4)
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";
325968caeeSMarri Devender Rao constexpr char const *mapperBusName = "xyz.openbmc_project.ObjectMapper";
335968caeeSMarri Devender Rao constexpr char const *mapperObjectPath = "/xyz/openbmc_project/object_mapper";
345968caeeSMarri Devender Rao constexpr char const *mapperIntf = "xyz.openbmc_project.ObjectMapper";
35*37cce918SMarri Devender Rao constexpr char const *ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
36*37cce918SMarri Devender Rao constexpr char const *httpsServiceName =
37*37cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
38*37cce918SMarri Devender Rao constexpr char const *ldapServiceName =
39*37cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
405968caeeSMarri Devender Rao } // namespace certs
415968caeeSMarri Devender Rao 
425968caeeSMarri Devender Rao /**
435968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
445968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
455968caeeSMarri Devender Rao  * are installed.
465968caeeSMarri Devender Rao  */
475968caeeSMarri Devender Rao class CertificateService : public Node
485968caeeSMarri Devender Rao {
495968caeeSMarri Devender Rao   public:
505968caeeSMarri Devender Rao     CertificateService(CrowApp &app) :
515968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/")
525968caeeSMarri Devender Rao     {
535968caeeSMarri Devender Rao         // TODO: Issue#61 No entries are available for Certificate
545968caeeSMarri Devender Rao         // sevice at https://www.dmtf.org/standards/redfish
555968caeeSMarri Devender Rao         // "redfish standard registries". Need to modify after DMTF
565968caeeSMarri Devender Rao         // publish Privilege details for certificate service
575968caeeSMarri Devender Rao         entityPrivileges = {
585968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
595968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
605968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
615968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
625968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
635968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
645968caeeSMarri Devender Rao     }
655968caeeSMarri Devender Rao 
665968caeeSMarri Devender Rao   private:
675968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
685968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
695968caeeSMarri Devender Rao     {
705968caeeSMarri Devender Rao         res.jsonValue = {
715968caeeSMarri Devender Rao             {"@odata.type", "#CertificateService.v1_0_0.CertificateService"},
725968caeeSMarri Devender Rao             {"@odata.id", "/redfish/v1/CertificateService"},
735968caeeSMarri Devender Rao             {"@odata.context",
745968caeeSMarri Devender Rao              "/redfish/v1/$metadata#CertificateService.CertificateService"},
755968caeeSMarri Devender Rao             {"Id", "CertificateService"},
765968caeeSMarri Devender Rao             {"Name", "Certificate Service"},
775968caeeSMarri Devender Rao             {"Description", "Actions available to manage certificates"}};
785968caeeSMarri Devender Rao         res.jsonValue["CertificateLocations"] = {
795968caeeSMarri Devender Rao             {"@odata.id",
805968caeeSMarri Devender Rao              "/redfish/v1/CertificateService/CertificateLocations"}};
815968caeeSMarri Devender Rao         res.jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
825968caeeSMarri Devender Rao             {"target", "/redfish/v1/CertificateService/Actions/"
835968caeeSMarri Devender Rao                        "CertificateService.ReplaceCertificate"},
845968caeeSMarri Devender Rao             {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
855968caeeSMarri Devender Rao         res.end();
865968caeeSMarri Devender Rao     }
875968caeeSMarri Devender Rao }; // CertificateService
88*37cce918SMarri Devender Rao 
895968caeeSMarri Devender Rao /**
905968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
915968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
925968caeeSMarri Devender Rao  * @param[in] path URL
935968caeeSMarri Devender Rao  * @return -1 on failure and number on success
945968caeeSMarri Devender Rao  */
955968caeeSMarri Devender Rao long getIDFromURL(const std::string_view url)
965968caeeSMarri Devender Rao {
975968caeeSMarri Devender Rao     std::size_t found = url.rfind("/");
985968caeeSMarri Devender Rao     if (found == std::string::npos)
995968caeeSMarri Devender Rao     {
1005968caeeSMarri Devender Rao         return -1;
1015968caeeSMarri Devender Rao     }
1025968caeeSMarri Devender Rao     if ((found + 1) < url.length())
1035968caeeSMarri Devender Rao     {
1045968caeeSMarri Devender Rao         char *endPtr;
1055968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
1065968caeeSMarri Devender Rao         long value = std::strtol(str.data(), &endPtr, 10);
107*37cce918SMarri Devender Rao         if (endPtr != str.end())
1085968caeeSMarri Devender Rao         {
1095968caeeSMarri Devender Rao             return -1;
1105968caeeSMarri Devender Rao         }
1115968caeeSMarri Devender Rao         return value;
1125968caeeSMarri Devender Rao     }
1135968caeeSMarri Devender Rao     return -1;
1145968caeeSMarri Devender Rao }
1155968caeeSMarri Devender Rao 
1165968caeeSMarri Devender Rao /**
1175968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1185968caeeSMarri Devender Rao  */
1195968caeeSMarri Devender Rao class CertificateFile
1205968caeeSMarri Devender Rao {
1215968caeeSMarri Devender Rao   public:
1225968caeeSMarri Devender Rao     CertificateFile() = delete;
1235968caeeSMarri Devender Rao     CertificateFile(const CertificateFile &) = delete;
1245968caeeSMarri Devender Rao     CertificateFile &operator=(const CertificateFile &) = delete;
1255968caeeSMarri Devender Rao     CertificateFile(CertificateFile &&) = delete;
1265968caeeSMarri Devender Rao     CertificateFile &operator=(CertificateFile &&) = delete;
1275968caeeSMarri Devender Rao     CertificateFile(const std::string &certString)
1285968caeeSMarri Devender Rao     {
1295968caeeSMarri Devender Rao         char dirTemplate[] = "/tmp/Certs.XXXXXX";
1305968caeeSMarri Devender Rao         char *tempDirectory = mkdtemp(dirTemplate);
1315968caeeSMarri Devender Rao         if (tempDirectory)
1325968caeeSMarri Devender Rao         {
1335968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1345968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1355968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1365968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1375968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1385968caeeSMarri Devender Rao             out << certString;
1395968caeeSMarri Devender Rao             out.close();
1405968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile;
1415968caeeSMarri Devender Rao         }
1425968caeeSMarri Devender Rao     }
1435968caeeSMarri Devender Rao     ~CertificateFile()
1445968caeeSMarri Devender Rao     {
1455968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1465968caeeSMarri Devender Rao         {
1475968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile;
1485968caeeSMarri Devender Rao             try
1495968caeeSMarri Devender Rao             {
1505968caeeSMarri Devender Rao                 std::filesystem::remove_all(certDirectory);
1515968caeeSMarri Devender Rao             }
1525968caeeSMarri Devender Rao             catch (const std::filesystem::filesystem_error &e)
1535968caeeSMarri Devender Rao             {
1545968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1555968caeeSMarri Devender Rao                                  << certDirectory;
1565968caeeSMarri Devender Rao             }
1575968caeeSMarri Devender Rao         }
1585968caeeSMarri Devender Rao     }
1595968caeeSMarri Devender Rao     std::string getCertFilePath()
1605968caeeSMarri Devender Rao     {
1615968caeeSMarri Devender Rao         return certificateFile;
1625968caeeSMarri Devender Rao     }
1635968caeeSMarri Devender Rao 
1645968caeeSMarri Devender Rao   private:
1655968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1665968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1675968caeeSMarri Devender Rao };
1685968caeeSMarri Devender Rao 
1695968caeeSMarri Devender Rao /**
1705968caeeSMarri Devender Rao  * @brief Parse and update Certficate Issue/Subject property
1715968caeeSMarri Devender Rao  *
1725968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
1735968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
1745968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
1755968caeeSMarri Devender Rao  * @return None
1765968caeeSMarri Devender Rao  */
1775968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json &out,
1785968caeeSMarri Devender Rao                                       const std::string_view value)
1795968caeeSMarri Devender Rao {
1805968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
1815968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
1825968caeeSMarri Devender Rao     while (i != value.end())
1835968caeeSMarri Devender Rao     {
1845968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
1855968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
1865968caeeSMarri Devender Rao         {
1875968caeeSMarri Devender Rao             i++;
1885968caeeSMarri Devender Rao         }
1895968caeeSMarri Devender Rao         if (i == value.end())
1905968caeeSMarri Devender Rao         {
1915968caeeSMarri Devender Rao             break;
1925968caeeSMarri Devender Rao         }
1935968caeeSMarri Devender Rao         const std::string_view key(tokenBegin, i - tokenBegin);
1945968caeeSMarri Devender Rao         i++;
1955968caeeSMarri Devender Rao         tokenBegin = i;
1965968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
1975968caeeSMarri Devender Rao         {
1985968caeeSMarri Devender Rao             i++;
1995968caeeSMarri Devender Rao         }
2005968caeeSMarri Devender Rao         const std::string_view val(tokenBegin, i - tokenBegin);
2015968caeeSMarri Devender Rao         if (key == "L")
2025968caeeSMarri Devender Rao         {
2035968caeeSMarri Devender Rao             out["City"] = val;
2045968caeeSMarri Devender Rao         }
2055968caeeSMarri Devender Rao         else if (key == "CN")
2065968caeeSMarri Devender Rao         {
2075968caeeSMarri Devender Rao             out["CommonName"] = val;
2085968caeeSMarri Devender Rao         }
2095968caeeSMarri Devender Rao         else if (key == "C")
2105968caeeSMarri Devender Rao         {
2115968caeeSMarri Devender Rao             out["Country"] = val;
2125968caeeSMarri Devender Rao         }
2135968caeeSMarri Devender Rao         else if (key == "O")
2145968caeeSMarri Devender Rao         {
2155968caeeSMarri Devender Rao             out["Organization"] = val;
2165968caeeSMarri Devender Rao         }
2175968caeeSMarri Devender Rao         else if (key == "OU")
2185968caeeSMarri Devender Rao         {
2195968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
2205968caeeSMarri Devender Rao         }
2215968caeeSMarri Devender Rao         else if (key == "ST")
2225968caeeSMarri Devender Rao         {
2235968caeeSMarri Devender Rao             out["State"] = val;
2245968caeeSMarri Devender Rao         }
2255968caeeSMarri Devender Rao         // skip comma character
2265968caeeSMarri Devender Rao         if (i != value.end())
2275968caeeSMarri Devender Rao         {
2285968caeeSMarri Devender Rao             i++;
2295968caeeSMarri Devender Rao         }
2305968caeeSMarri Devender Rao     }
2315968caeeSMarri Devender Rao }
2325968caeeSMarri Devender Rao 
2335968caeeSMarri Devender Rao /**
2345968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
2355968caeeSMarri Devender Rao  * message
2365968caeeSMarri Devender Rao  *
2375968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
2385968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
2395968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
2405968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
2415968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
2425968caeeSMarri Devender Rao  * @return None
2435968caeeSMarri Devender Rao  */
2445968caeeSMarri Devender Rao static void getCertificateProperties(
2455968caeeSMarri Devender Rao     const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath,
246*37cce918SMarri Devender Rao     const std::string &service, long certId, const std::string &certURL,
247*37cce918SMarri Devender Rao     const std::string &name)
2485968caeeSMarri Devender Rao {
2495968caeeSMarri Devender Rao     using PropertyType =
2505968caeeSMarri Devender Rao         std::variant<std::string, uint64_t, std::vector<std::string>>;
2515968caeeSMarri Devender Rao     using PropertiesMap = boost::container::flat_map<std::string, PropertyType>;
2525968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
2535968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
2545968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
255*37cce918SMarri Devender Rao         [asyncResp, certURL, certId, name](const boost::system::error_code ec,
2565968caeeSMarri Devender Rao                                            const PropertiesMap &properties) {
2575968caeeSMarri Devender Rao             if (ec)
2585968caeeSMarri Devender Rao             {
2595968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
2605968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
2615968caeeSMarri Devender Rao                 return;
2625968caeeSMarri Devender Rao             }
2635968caeeSMarri Devender Rao             asyncResp->res.jsonValue = {
2645968caeeSMarri Devender Rao                 {"@odata.id", certURL},
2655968caeeSMarri Devender Rao                 {"@odata.type", "#Certificate.v1_0_0.Certificate"},
2665968caeeSMarri Devender Rao                 {"@odata.context",
2675968caeeSMarri Devender Rao                  "/redfish/v1/$metadata#Certificate.Certificate"},
2685968caeeSMarri Devender Rao                 {"Id", std::to_string(certId)},
2695968caeeSMarri Devender Rao                 {"Name", name},
2705968caeeSMarri Devender Rao                 {"Description", name}};
2715968caeeSMarri Devender Rao             for (const auto &property : properties)
2725968caeeSMarri Devender Rao             {
2735968caeeSMarri Devender Rao                 if (property.first == "CertificateString")
2745968caeeSMarri Devender Rao                 {
2755968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = "";
2765968caeeSMarri Devender Rao                     const std::string *value =
2775968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
2785968caeeSMarri Devender Rao                     if (value)
2795968caeeSMarri Devender Rao                     {
280*37cce918SMarri Devender Rao                         asyncResp->res.jsonValue["CertificateString"] = *value;
2815968caeeSMarri Devender Rao                     }
2825968caeeSMarri Devender Rao                 }
2835968caeeSMarri Devender Rao                 else if (property.first == "KeyUsage")
2845968caeeSMarri Devender Rao                 {
2855968caeeSMarri Devender Rao                     nlohmann::json &keyUsage =
2865968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["KeyUsage"];
2875968caeeSMarri Devender Rao                     keyUsage = nlohmann::json::array();
2885968caeeSMarri Devender Rao                     const std::vector<std::string> *value =
289*37cce918SMarri Devender Rao                         std::get_if<std::vector<std::string>>(&property.second);
2905968caeeSMarri Devender Rao                     if (value)
2915968caeeSMarri Devender Rao                     {
2925968caeeSMarri Devender Rao                         for (const std::string &usage : *value)
2935968caeeSMarri Devender Rao                         {
2945968caeeSMarri Devender Rao                             keyUsage.push_back(usage);
2955968caeeSMarri Devender Rao                         }
2965968caeeSMarri Devender Rao                     }
2975968caeeSMarri Devender Rao                 }
2985968caeeSMarri Devender Rao                 else if (property.first == "Issuer")
2995968caeeSMarri Devender Rao                 {
3005968caeeSMarri Devender Rao                     const std::string *value =
3015968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
3025968caeeSMarri Devender Rao                     if (value)
3035968caeeSMarri Devender Rao                     {
3045968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
3055968caeeSMarri Devender Rao                             asyncResp->res.jsonValue["Issuer"], *value);
3065968caeeSMarri Devender Rao                     }
3075968caeeSMarri Devender Rao                 }
3085968caeeSMarri Devender Rao                 else if (property.first == "Subject")
3095968caeeSMarri Devender Rao                 {
3105968caeeSMarri Devender Rao                     const std::string *value =
3115968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
3125968caeeSMarri Devender Rao                     if (value)
3135968caeeSMarri Devender Rao                     {
3145968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
315*37cce918SMarri Devender Rao                             asyncResp->res.jsonValue["Subject"], *value);
3165968caeeSMarri Devender Rao                     }
3175968caeeSMarri Devender Rao                 }
3185968caeeSMarri Devender Rao                 else if (property.first == "ValidNotAfter")
3195968caeeSMarri Devender Rao                 {
3205968caeeSMarri Devender Rao                     const uint64_t *value =
3215968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
3225968caeeSMarri Devender Rao                     if (value)
3235968caeeSMarri Devender Rao                     {
324*37cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
3255968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotAfter"] =
3265968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
3275968caeeSMarri Devender Rao                     }
3285968caeeSMarri Devender Rao                 }
3295968caeeSMarri Devender Rao                 else if (property.first == "ValidNotBefore")
3305968caeeSMarri Devender Rao                 {
3315968caeeSMarri Devender Rao                     const uint64_t *value =
3325968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
3335968caeeSMarri Devender Rao                     if (value)
3345968caeeSMarri Devender Rao                     {
335*37cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
3365968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotBefore"] =
3375968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
3385968caeeSMarri Devender Rao                     }
3395968caeeSMarri Devender Rao                 }
3405968caeeSMarri Devender Rao             }
3415968caeeSMarri Devender Rao             asyncResp->res.addHeader("Location", certURL);
3425968caeeSMarri Devender Rao         },
3435968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
3445968caeeSMarri Devender Rao         certs::certPropIntf);
3455968caeeSMarri Devender Rao }
3465968caeeSMarri Devender Rao 
3475968caeeSMarri Devender Rao using GetObjectType =
3485968caeeSMarri Devender Rao     std::vector<std::pair<std::string, std::vector<std::string>>>;
3495968caeeSMarri Devender Rao 
3505968caeeSMarri Devender Rao /**
3515968caeeSMarri Devender Rao  * Action to replace an existing certificate
3525968caeeSMarri Devender Rao  */
3535968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node
3545968caeeSMarri Devender Rao {
3555968caeeSMarri Devender Rao   public:
3565968caeeSMarri Devender Rao     CertificateActionsReplaceCertificate(CrowApp &app) :
3575968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/Actions/"
3585968caeeSMarri Devender Rao                   "CertificateService.ReplaceCertificate/")
3595968caeeSMarri Devender Rao     {
3605968caeeSMarri Devender Rao         entityPrivileges = {
3615968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
3625968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
3635968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
3645968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
3655968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
3665968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
3675968caeeSMarri Devender Rao     }
3685968caeeSMarri Devender Rao 
3695968caeeSMarri Devender Rao   private:
3705968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
3715968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
3725968caeeSMarri Devender Rao     {
3735968caeeSMarri Devender Rao         std::string certificate;
3745968caeeSMarri Devender Rao         nlohmann::json certificateUri;
3755968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
3765968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
3775968caeeSMarri Devender Rao         if (!json_util::readJson(req, asyncResp->res, "CertificateString",
3785968caeeSMarri Devender Rao                                  certificate, "CertificateUri", certificateUri,
3795968caeeSMarri Devender Rao                                  "CertificateType", certificateType))
3805968caeeSMarri Devender Rao         {
3815968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
3825968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
3835968caeeSMarri Devender Rao             return;
3845968caeeSMarri Devender Rao         }
3855968caeeSMarri Devender Rao 
3865968caeeSMarri Devender Rao         if (!certificateType)
3875968caeeSMarri Devender Rao         {
3885968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
3895968caeeSMarri Devender Rao             return;
3905968caeeSMarri Devender Rao         }
3915968caeeSMarri Devender Rao         if (certificateType != "PEM")
3925968caeeSMarri Devender Rao         {
3935968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
3945968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
3955968caeeSMarri Devender Rao             return;
3965968caeeSMarri Devender Rao         }
3975968caeeSMarri Devender Rao 
3985968caeeSMarri Devender Rao         std::string certURI;
3995968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
4005968caeeSMarri Devender Rao                                           "@odata.id", certURI))
4015968caeeSMarri Devender Rao         {
4025968caeeSMarri Devender Rao             messages::actionParameterMissing(
4035968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
4045968caeeSMarri Devender Rao             return;
4055968caeeSMarri Devender Rao         }
4065968caeeSMarri Devender Rao 
4075968caeeSMarri Devender Rao         BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
4085968caeeSMarri Devender Rao         long id = getIDFromURL(certURI);
4095968caeeSMarri Devender Rao         if (id < 0)
4105968caeeSMarri Devender Rao         {
4115968caeeSMarri Devender Rao             messages::actionParameterValueFormatError(asyncResp->res, certURI,
4125968caeeSMarri Devender Rao                                                       "CertificateUri",
4135968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
4145968caeeSMarri Devender Rao             return;
4155968caeeSMarri Devender Rao         }
4165968caeeSMarri Devender Rao         std::string objectPath;
4175968caeeSMarri Devender Rao         std::string name;
418*37cce918SMarri Devender Rao         std::string service;
4195968caeeSMarri Devender Rao         if (boost::starts_with(
4205968caeeSMarri Devender Rao                 certURI,
4215968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"))
4225968caeeSMarri Devender Rao         {
4235968caeeSMarri Devender Rao             objectPath =
4245968caeeSMarri Devender Rao                 std::string(certs::httpsObjectPath) + "/" + std::to_string(id);
4255968caeeSMarri Devender Rao             name = "HTTPS certificate";
426*37cce918SMarri Devender Rao             service = certs::httpsServiceName;
427*37cce918SMarri Devender Rao         }
428*37cce918SMarri Devender Rao         else if (boost::starts_with(
429*37cce918SMarri Devender Rao                      certURI, "/redfish/v1/AccountService/LDAP/Certificates/"))
430*37cce918SMarri Devender Rao         {
431*37cce918SMarri Devender Rao             objectPath =
432*37cce918SMarri Devender Rao                 std::string(certs::ldapObjectPath) + "/" + std::to_string(id);
433*37cce918SMarri Devender Rao             name = "LDAP certificate";
434*37cce918SMarri Devender Rao             service = certs::ldapServiceName;
4355968caeeSMarri Devender Rao         }
4365968caeeSMarri Devender Rao         else
4375968caeeSMarri Devender Rao         {
4385968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
4395968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
4405968caeeSMarri Devender Rao             return;
4415968caeeSMarri Devender Rao         }
4425968caeeSMarri Devender Rao 
4435968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
4445968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
4455968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
446*37cce918SMarri Devender Rao             [asyncResp, certFile, objectPath, service, certURI, id,
4475968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
4485968caeeSMarri Devender Rao                 if (ec)
4495968caeeSMarri Devender Rao                 {
4505968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
4515968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
4525968caeeSMarri Devender Rao                     return;
4535968caeeSMarri Devender Rao                 }
454*37cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath, service, id,
4555968caeeSMarri Devender Rao                                          certURI, name);
4565968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
4575968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
4585968caeeSMarri Devender Rao             },
4595968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
4605968caeeSMarri Devender Rao             certFile->getCertFilePath());
4615968caeeSMarri Devender Rao     }
4625968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate
4635968caeeSMarri Devender Rao 
4645968caeeSMarri Devender Rao /**
4655968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
4665968caeeSMarri Devender Rao  * of a component, account or service.
4675968caeeSMarri Devender Rao  */
4685968caeeSMarri Devender Rao class HTTPSCertificate : public Node
4695968caeeSMarri Devender Rao {
4705968caeeSMarri Devender Rao   public:
4715968caeeSMarri Devender Rao     template <typename CrowApp>
4725968caeeSMarri Devender Rao     HTTPSCertificate(CrowApp &app) :
4735968caeeSMarri Devender Rao         Node(app,
4745968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
4755968caeeSMarri Devender Rao              "<str>/",
4765968caeeSMarri Devender Rao              std::string())
4775968caeeSMarri Devender Rao     {
4785968caeeSMarri Devender Rao         entityPrivileges = {
4795968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
4805968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
4815968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
4825968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
4835968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
4845968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
4855968caeeSMarri Devender Rao     }
4865968caeeSMarri Devender Rao 
4875968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
4885968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
4895968caeeSMarri Devender Rao     {
4905968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
4915968caeeSMarri Devender Rao         if (params.size() != 1)
4925968caeeSMarri Devender Rao         {
4935968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
4945968caeeSMarri Devender Rao             return;
4955968caeeSMarri Devender Rao         }
4965968caeeSMarri Devender Rao         long id = getIDFromURL(req.url);
4975968caeeSMarri Devender Rao 
4985968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id);
4995968caeeSMarri Devender Rao         std::string certURL =
5005968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
5015968caeeSMarri Devender Rao             std::to_string(id);
5025968caeeSMarri Devender Rao         std::string objectPath = certs::httpsObjectPath;
5035968caeeSMarri Devender Rao         objectPath += "/";
5045968caeeSMarri Devender Rao         objectPath += std::to_string(id);
505*37cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
506*37cce918SMarri Devender Rao                                  id, certURL, "HTTPS Certificate");
5075968caeeSMarri Devender Rao     }
5085968caeeSMarri Devender Rao 
5095968caeeSMarri Devender Rao }; // namespace redfish
5105968caeeSMarri Devender Rao 
5115968caeeSMarri Devender Rao /**
5125968caeeSMarri Devender Rao  * Collection of HTTPS certificates
5135968caeeSMarri Devender Rao  */
5145968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node
5155968caeeSMarri Devender Rao {
5165968caeeSMarri Devender Rao   public:
5175968caeeSMarri Devender Rao     template <typename CrowApp>
5185968caeeSMarri Devender Rao     HTTPSCertificateCollection(CrowApp &app) :
5195968caeeSMarri Devender Rao         Node(app,
5205968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
5215968caeeSMarri Devender Rao     {
5225968caeeSMarri Devender Rao         entityPrivileges = {
5235968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
5245968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
5255968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
5265968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
5275968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
5285968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
5295968caeeSMarri Devender Rao     }
5305968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
5315968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
5325968caeeSMarri Devender Rao     {
5335968caeeSMarri Devender Rao         res.jsonValue = {
5345968caeeSMarri Devender Rao             {"@odata.id",
5355968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
5365968caeeSMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
5375968caeeSMarri Devender Rao             {"@odata.context",
5385968caeeSMarri Devender Rao              "/redfish/v1/"
5395968caeeSMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
5405968caeeSMarri Devender Rao             {"Name", "HTTPS Certificates Collection"},
5415968caeeSMarri Devender Rao             {"Description", "A Collection of HTTPS certificate instances"}};
5425968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
5435968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
5445968caeeSMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
5455968caeeSMarri Devender Rao                         const ManagedObjectType &certs) {
5465968caeeSMarri Devender Rao                 if (ec)
5475968caeeSMarri Devender Rao                 {
5485968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5495968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
5505968caeeSMarri Devender Rao                     return;
5515968caeeSMarri Devender Rao                 }
552*37cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
5535968caeeSMarri Devender Rao                 members = nlohmann::json::array();
5545968caeeSMarri Devender Rao                 for (const auto &cert : certs)
5555968caeeSMarri Devender Rao                 {
5565968caeeSMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
557*37cce918SMarri Devender Rao                     if (id >= 0)
5585968caeeSMarri Devender Rao                     {
5595968caeeSMarri Devender Rao                         members.push_back(
5605968caeeSMarri Devender Rao                             {{"@odata.id",
5615968caeeSMarri Devender Rao                               "/redfish/v1/Managers/bmc/"
5625968caeeSMarri Devender Rao                               "NetworkProtocol/HTTPS/Certificates/" +
5635968caeeSMarri Devender Rao                                   std::to_string(id)}});
5645968caeeSMarri Devender Rao                     }
5655968caeeSMarri Devender Rao                 }
5665968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
5675968caeeSMarri Devender Rao                     members.size();
5685968caeeSMarri Devender Rao             },
569*37cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
570*37cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
5715968caeeSMarri Devender Rao     }
5725968caeeSMarri Devender Rao 
5735968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
5745968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
5755968caeeSMarri Devender Rao     {
5765968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
5775968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
5785968caeeSMarri Devender Rao         asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"},
5795968caeeSMarri Devender Rao                                     {"Description", "HTTPS Certificate"}};
5805968caeeSMarri Devender Rao 
5815968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
5825968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
5835968caeeSMarri Devender Rao 
5845968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
5855968caeeSMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
5865968caeeSMarri Devender Rao                 if (ec)
5875968caeeSMarri Devender Rao                 {
5885968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5895968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
5905968caeeSMarri Devender Rao                     return;
5915968caeeSMarri Devender Rao                 }
5925968caeeSMarri Devender Rao                 // TODO: Issue#84 supporting only 1 certificate
5935968caeeSMarri Devender Rao                 long certId = 1;
5945968caeeSMarri Devender Rao                 std::string certURL =
5955968caeeSMarri Devender Rao                     "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
5965968caeeSMarri Devender Rao                     "Certificates/" +
5975968caeeSMarri Devender Rao                     std::to_string(certId);
598*37cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::httpsObjectPath) +
599*37cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
600*37cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
601*37cce918SMarri Devender Rao                                          certs::httpsServiceName, certId,
6025968caeeSMarri Devender Rao                                          certURL, "HTTPS Certificate");
6035968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
6045968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
6055968caeeSMarri Devender Rao             },
606*37cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
607*37cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
6085968caeeSMarri Devender Rao     }
6095968caeeSMarri Devender Rao }; // HTTPSCertificateCollection
6105968caeeSMarri Devender Rao 
6115968caeeSMarri Devender Rao /**
6125968caeeSMarri Devender Rao  * The certificate location schema defines a resource that an administrator
6135968caeeSMarri Devender Rao  * can use in order to locate all certificates installed on a given service.
6145968caeeSMarri Devender Rao  */
6155968caeeSMarri Devender Rao class CertificateLocations : public Node
6165968caeeSMarri Devender Rao {
6175968caeeSMarri Devender Rao   public:
6185968caeeSMarri Devender Rao     template <typename CrowApp>
6195968caeeSMarri Devender Rao     CertificateLocations(CrowApp &app) :
6205968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/CertificateLocations/")
6215968caeeSMarri Devender Rao     {
6225968caeeSMarri Devender Rao         entityPrivileges = {
6235968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
6245968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
6255968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
6265968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
6275968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
6285968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
6295968caeeSMarri Devender Rao     }
6305968caeeSMarri Devender Rao 
6315968caeeSMarri Devender Rao   private:
6325968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
6335968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
6345968caeeSMarri Devender Rao     {
6355968caeeSMarri Devender Rao         res.jsonValue = {
6365968caeeSMarri Devender Rao             {"@odata.id",
6375968caeeSMarri Devender Rao              "/redfish/v1/CertificateService/CertificateLocations"},
6385968caeeSMarri Devender Rao             {"@odata.type",
6395968caeeSMarri Devender Rao              "#CertificateLocations.v1_0_0.CertificateLocations"},
6405968caeeSMarri Devender Rao             {"@odata.context",
6415968caeeSMarri Devender Rao              "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"},
6425968caeeSMarri Devender Rao             {"Name", "Certificate Locations"},
6435968caeeSMarri Devender Rao             {"Id", "CertificateLocations"},
6445968caeeSMarri Devender Rao             {"Description",
6455968caeeSMarri Devender Rao              "Defines a resource that an administrator can use in order to "
6465968caeeSMarri Devender Rao              "locate all certificates installed on a given service"}};
6475968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
6485968caeeSMarri Devender Rao         nlohmann::json &links =
6495968caeeSMarri Devender Rao             asyncResp->res.jsonValue["Links"]["Certificates"];
6505968caeeSMarri Devender Rao         links = nlohmann::json::array();
6515968caeeSMarri Devender Rao         getCertificateLocations(
6525968caeeSMarri Devender Rao             asyncResp,
6535968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
654*37cce918SMarri Devender Rao             certs::httpsObjectPath, certs::httpsServiceName);
655*37cce918SMarri Devender Rao         getCertificateLocations(asyncResp,
656*37cce918SMarri Devender Rao                                 "/redfish/v1/AccountService/LDAP/Certificates/",
657*37cce918SMarri Devender Rao                                 certs::ldapObjectPath, certs::ldapServiceName);
658*37cce918SMarri Devender Rao     }
659*37cce918SMarri Devender Rao     /**
660*37cce918SMarri Devender Rao      * @brief Retrieve the certificates installed list and append to the
661*37cce918SMarri Devender Rao      * response
662*37cce918SMarri Devender Rao      *
663*37cce918SMarri Devender Rao      * @param[in] asyncResp Shared pointer to the response message
664*37cce918SMarri Devender Rao      * @param[in] certURL  Path of the certificate object
665*37cce918SMarri Devender Rao      * @param[in] path  Path of the D-Bus service object
666*37cce918SMarri Devender Rao      * @return None
667*37cce918SMarri Devender Rao      */
668*37cce918SMarri Devender Rao     void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp,
669*37cce918SMarri Devender Rao                                  const std::string &certURL,
670*37cce918SMarri Devender Rao                                  const std::string &path,
671*37cce918SMarri Devender Rao                                  const std::string &service)
672*37cce918SMarri Devender Rao     {
673*37cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
674*37cce918SMarri Devender Rao                          << " Path=" << path << " service= " << service;
675*37cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
676*37cce918SMarri Devender Rao             [asyncResp, certURL](const boost::system::error_code ec,
677*37cce918SMarri Devender Rao                                  const ManagedObjectType &certs) {
678*37cce918SMarri Devender Rao                 if (ec)
679*37cce918SMarri Devender Rao                 {
680*37cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
681*37cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
682*37cce918SMarri Devender Rao                     return;
683*37cce918SMarri Devender Rao                 }
684*37cce918SMarri Devender Rao                 nlohmann::json &links =
685*37cce918SMarri Devender Rao                     asyncResp->res.jsonValue["Links"]["Certificates"];
686*37cce918SMarri Devender Rao                 for (auto &cert : certs)
687*37cce918SMarri Devender Rao                 {
688*37cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
689*37cce918SMarri Devender Rao                     if (id >= 0)
690*37cce918SMarri Devender Rao                     {
691*37cce918SMarri Devender Rao                         links.push_back(
692*37cce918SMarri Devender Rao                             {{"@odata.id", certURL + std::to_string(id)}});
693*37cce918SMarri Devender Rao                     }
694*37cce918SMarri Devender Rao                 }
695*37cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
696*37cce918SMarri Devender Rao                     links.size();
697*37cce918SMarri Devender Rao             },
698*37cce918SMarri Devender Rao             service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
6995968caeeSMarri Devender Rao     }
7005968caeeSMarri Devender Rao }; // CertificateLocations
701*37cce918SMarri Devender Rao 
702*37cce918SMarri Devender Rao /**
703*37cce918SMarri Devender Rao  * Collection of LDAP certificates
704*37cce918SMarri Devender Rao  */
705*37cce918SMarri Devender Rao class LDAPCertificateCollection : public Node
706*37cce918SMarri Devender Rao {
707*37cce918SMarri Devender Rao   public:
708*37cce918SMarri Devender Rao     template <typename CrowApp>
709*37cce918SMarri Devender Rao     LDAPCertificateCollection(CrowApp &app) :
710*37cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/")
711*37cce918SMarri Devender Rao     {
712*37cce918SMarri Devender Rao         entityPrivileges = {
713*37cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
714*37cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
715*37cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
716*37cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
717*37cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
718*37cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
719*37cce918SMarri Devender Rao     }
720*37cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
721*37cce918SMarri Devender Rao                const std::vector<std::string> &params) override
722*37cce918SMarri Devender Rao     {
723*37cce918SMarri Devender Rao         res.jsonValue = {
724*37cce918SMarri Devender Rao             {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"},
725*37cce918SMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
726*37cce918SMarri Devender Rao             {"@odata.context",
727*37cce918SMarri Devender Rao              "/redfish/v1/"
728*37cce918SMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
729*37cce918SMarri Devender Rao             {"Name", "LDAP Certificates Collection"},
730*37cce918SMarri Devender Rao             {"Description", "A Collection of LDAP certificate instances"}};
731*37cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
732*37cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
733*37cce918SMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
734*37cce918SMarri Devender Rao                         const ManagedObjectType &certs) {
735*37cce918SMarri Devender Rao                 if (ec)
736*37cce918SMarri Devender Rao                 {
737*37cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
738*37cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
739*37cce918SMarri Devender Rao                     return;
740*37cce918SMarri Devender Rao                 }
741*37cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
742*37cce918SMarri Devender Rao                 members = nlohmann::json::array();
743*37cce918SMarri Devender Rao                 for (const auto &cert : certs)
744*37cce918SMarri Devender Rao                 {
745*37cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
746*37cce918SMarri Devender Rao                     if (id >= 0)
747*37cce918SMarri Devender Rao                     {
748*37cce918SMarri Devender Rao                         members.push_back(
749*37cce918SMarri Devender Rao                             {{"@odata.id", "/redfish/v1/AccountService/"
750*37cce918SMarri Devender Rao                                            "LDAP/Certificates/" +
751*37cce918SMarri Devender Rao                                                std::to_string(id)}});
752*37cce918SMarri Devender Rao                     }
753*37cce918SMarri Devender Rao                 }
754*37cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
755*37cce918SMarri Devender Rao                     members.size();
756*37cce918SMarri Devender Rao             },
757*37cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
758*37cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
759*37cce918SMarri Devender Rao     }
760*37cce918SMarri Devender Rao 
761*37cce918SMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
762*37cce918SMarri Devender Rao                 const std::vector<std::string> &params) override
763*37cce918SMarri Devender Rao     {
764*37cce918SMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
765*37cce918SMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
766*37cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
767*37cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
768*37cce918SMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
769*37cce918SMarri Devender Rao                 if (ec)
770*37cce918SMarri Devender Rao                 {
771*37cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
772*37cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
773*37cce918SMarri Devender Rao                     return;
774*37cce918SMarri Devender Rao                 }
775*37cce918SMarri Devender Rao                 //// TODO: Issue#84 supporting only 1 certificate
776*37cce918SMarri Devender Rao                 long certId = 1;
777*37cce918SMarri Devender Rao                 std::string certURL =
778*37cce918SMarri Devender Rao                     "/redfish/v1/AccountService/LDAP/Certificates/" +
779*37cce918SMarri Devender Rao                     std::to_string(certId);
780*37cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::ldapObjectPath) +
781*37cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
782*37cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
783*37cce918SMarri Devender Rao                                          certs::ldapServiceName, certId,
784*37cce918SMarri Devender Rao                                          certURL, "LDAP Certificate");
785*37cce918SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "LDAP certificate install file="
786*37cce918SMarri Devender Rao                                  << certFile->getCertFilePath();
787*37cce918SMarri Devender Rao             },
788*37cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
789*37cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
790*37cce918SMarri Devender Rao     }
791*37cce918SMarri Devender Rao }; // LDAPCertificateCollection
792*37cce918SMarri Devender Rao 
793*37cce918SMarri Devender Rao /**
794*37cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
795*37cce918SMarri Devender Rao  * of a component, account or service.
796*37cce918SMarri Devender Rao  */
797*37cce918SMarri Devender Rao class LDAPCertificate : public Node
798*37cce918SMarri Devender Rao {
799*37cce918SMarri Devender Rao   public:
800*37cce918SMarri Devender Rao     template <typename CrowApp>
801*37cce918SMarri Devender Rao     LDAPCertificate(CrowApp &app) :
802*37cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/",
803*37cce918SMarri Devender Rao              std::string())
804*37cce918SMarri Devender Rao     {
805*37cce918SMarri Devender Rao         entityPrivileges = {
806*37cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
807*37cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
808*37cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
809*37cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
810*37cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
811*37cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
812*37cce918SMarri Devender Rao     }
813*37cce918SMarri Devender Rao 
814*37cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
815*37cce918SMarri Devender Rao                const std::vector<std::string> &params) override
816*37cce918SMarri Devender Rao     {
817*37cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
818*37cce918SMarri Devender Rao         long id = getIDFromURL(req.url);
819*37cce918SMarri Devender Rao         if (id < 0)
820*37cce918SMarri Devender Rao         {
821*37cce918SMarri Devender Rao             BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
822*37cce918SMarri Devender Rao             messages::internalError(asyncResp->res);
823*37cce918SMarri Devender Rao             return;
824*37cce918SMarri Devender Rao         }
825*37cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id);
826*37cce918SMarri Devender Rao         std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" +
827*37cce918SMarri Devender Rao                               std::to_string(id);
828*37cce918SMarri Devender Rao         std::string objectPath = certs::ldapObjectPath;
829*37cce918SMarri Devender Rao         objectPath += "/";
830*37cce918SMarri Devender Rao         objectPath += std::to_string(id);
831*37cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
832*37cce918SMarri Devender Rao                                  id, certURL, "LDAP Certificate");
833*37cce918SMarri Devender Rao     }
834*37cce918SMarri Devender Rao }; // LDAPCertificate
8355968caeeSMarri Devender Rao } // namespace redfish
836