xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 8aae75ad51881046f2fab9ca64c7addfb004e06b)
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";
3537cce918SMarri Devender Rao constexpr char const *ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
3637cce918SMarri Devender Rao constexpr char const *httpsServiceName =
3737cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
3837cce918SMarri Devender Rao constexpr char const *ldapServiceName =
3937cce918SMarri 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
8837cce918SMarri Devender Rao 
895968caeeSMarri Devender Rao /**
905968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
915968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
925968caeeSMarri Devender Rao  * @param[in] path URL
935968caeeSMarri Devender Rao  * @return -1 on failure and number on success
945968caeeSMarri Devender Rao  */
955968caeeSMarri Devender Rao long getIDFromURL(const std::string_view url)
965968caeeSMarri Devender Rao {
975968caeeSMarri Devender Rao     std::size_t found = url.rfind("/");
985968caeeSMarri Devender Rao     if (found == std::string::npos)
995968caeeSMarri Devender Rao     {
1005968caeeSMarri Devender Rao         return -1;
1015968caeeSMarri Devender Rao     }
1025968caeeSMarri Devender Rao     if ((found + 1) < url.length())
1035968caeeSMarri Devender Rao     {
1045968caeeSMarri Devender Rao         char *endPtr;
1055968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
1065968caeeSMarri Devender Rao         long value = std::strtol(str.data(), &endPtr, 10);
10737cce918SMarri Devender Rao         if (endPtr != str.end())
1085968caeeSMarri Devender Rao         {
1095968caeeSMarri Devender Rao             return -1;
1105968caeeSMarri Devender Rao         }
1115968caeeSMarri Devender Rao         return value;
1125968caeeSMarri Devender Rao     }
1135968caeeSMarri Devender Rao     return -1;
1145968caeeSMarri Devender Rao }
1155968caeeSMarri Devender Rao 
1165968caeeSMarri Devender Rao /**
1175968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1185968caeeSMarri Devender Rao  */
1195968caeeSMarri Devender Rao class CertificateFile
1205968caeeSMarri Devender Rao {
1215968caeeSMarri Devender Rao   public:
1225968caeeSMarri Devender Rao     CertificateFile() = delete;
1235968caeeSMarri Devender Rao     CertificateFile(const CertificateFile &) = delete;
1245968caeeSMarri Devender Rao     CertificateFile &operator=(const CertificateFile &) = delete;
1255968caeeSMarri Devender Rao     CertificateFile(CertificateFile &&) = delete;
1265968caeeSMarri Devender Rao     CertificateFile &operator=(CertificateFile &&) = delete;
1275968caeeSMarri Devender Rao     CertificateFile(const std::string &certString)
1285968caeeSMarri Devender Rao     {
1295968caeeSMarri Devender Rao         char dirTemplate[] = "/tmp/Certs.XXXXXX";
1305968caeeSMarri Devender Rao         char *tempDirectory = mkdtemp(dirTemplate);
1315968caeeSMarri Devender Rao         if (tempDirectory)
1325968caeeSMarri Devender Rao         {
1335968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1345968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1355968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1365968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1375968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1385968caeeSMarri Devender Rao             out << certString;
1395968caeeSMarri Devender Rao             out.close();
1405968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile;
1415968caeeSMarri Devender Rao         }
1425968caeeSMarri Devender Rao     }
1435968caeeSMarri Devender Rao     ~CertificateFile()
1445968caeeSMarri Devender Rao     {
1455968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1465968caeeSMarri Devender Rao         {
1475968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile;
1485968caeeSMarri Devender Rao             try
1495968caeeSMarri Devender Rao             {
1505968caeeSMarri Devender Rao                 std::filesystem::remove_all(certDirectory);
1515968caeeSMarri Devender Rao             }
1525968caeeSMarri Devender Rao             catch (const std::filesystem::filesystem_error &e)
1535968caeeSMarri Devender Rao             {
1545968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1555968caeeSMarri Devender Rao                                  << certDirectory;
1565968caeeSMarri Devender Rao             }
1575968caeeSMarri Devender Rao         }
1585968caeeSMarri Devender Rao     }
1595968caeeSMarri Devender Rao     std::string getCertFilePath()
1605968caeeSMarri Devender Rao     {
1615968caeeSMarri Devender Rao         return certificateFile;
1625968caeeSMarri Devender Rao     }
1635968caeeSMarri Devender Rao 
1645968caeeSMarri Devender Rao   private:
1655968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1665968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1675968caeeSMarri Devender Rao };
1685968caeeSMarri Devender Rao 
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,
24637cce918SMarri Devender Rao     const std::string &service, long certId, const std::string &certURL,
24737cce918SMarri 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(
25537cce918SMarri 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;
260*8aae75adSMarri Devender Rao                 messages::resourceNotFound(asyncResp->res, name,
261*8aae75adSMarri Devender Rao                                            std::to_string(certId));
2625968caeeSMarri Devender Rao                 return;
2635968caeeSMarri Devender Rao             }
2645968caeeSMarri Devender Rao             asyncResp->res.jsonValue = {
2655968caeeSMarri Devender Rao                 {"@odata.id", certURL},
2665968caeeSMarri Devender Rao                 {"@odata.type", "#Certificate.v1_0_0.Certificate"},
2675968caeeSMarri Devender Rao                 {"@odata.context",
2685968caeeSMarri Devender Rao                  "/redfish/v1/$metadata#Certificate.Certificate"},
2695968caeeSMarri Devender Rao                 {"Id", std::to_string(certId)},
2705968caeeSMarri Devender Rao                 {"Name", name},
2715968caeeSMarri Devender Rao                 {"Description", name}};
2725968caeeSMarri Devender Rao             for (const auto &property : properties)
2735968caeeSMarri Devender Rao             {
2745968caeeSMarri Devender Rao                 if (property.first == "CertificateString")
2755968caeeSMarri Devender Rao                 {
2765968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = "";
2775968caeeSMarri Devender Rao                     const std::string *value =
2785968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
2795968caeeSMarri Devender Rao                     if (value)
2805968caeeSMarri Devender Rao                     {
28137cce918SMarri Devender Rao                         asyncResp->res.jsonValue["CertificateString"] = *value;
2825968caeeSMarri Devender Rao                     }
2835968caeeSMarri Devender Rao                 }
2845968caeeSMarri Devender Rao                 else if (property.first == "KeyUsage")
2855968caeeSMarri Devender Rao                 {
2865968caeeSMarri Devender Rao                     nlohmann::json &keyUsage =
2875968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["KeyUsage"];
2885968caeeSMarri Devender Rao                     keyUsage = nlohmann::json::array();
2895968caeeSMarri Devender Rao                     const std::vector<std::string> *value =
29037cce918SMarri Devender Rao                         std::get_if<std::vector<std::string>>(&property.second);
2915968caeeSMarri Devender Rao                     if (value)
2925968caeeSMarri Devender Rao                     {
2935968caeeSMarri Devender Rao                         for (const std::string &usage : *value)
2945968caeeSMarri Devender Rao                         {
2955968caeeSMarri Devender Rao                             keyUsage.push_back(usage);
2965968caeeSMarri Devender Rao                         }
2975968caeeSMarri Devender Rao                     }
2985968caeeSMarri Devender Rao                 }
2995968caeeSMarri Devender Rao                 else if (property.first == "Issuer")
3005968caeeSMarri Devender Rao                 {
3015968caeeSMarri Devender Rao                     const std::string *value =
3025968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
3035968caeeSMarri Devender Rao                     if (value)
3045968caeeSMarri Devender Rao                     {
3055968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
3065968caeeSMarri Devender Rao                             asyncResp->res.jsonValue["Issuer"], *value);
3075968caeeSMarri Devender Rao                     }
3085968caeeSMarri Devender Rao                 }
3095968caeeSMarri Devender Rao                 else if (property.first == "Subject")
3105968caeeSMarri Devender Rao                 {
3115968caeeSMarri Devender Rao                     const std::string *value =
3125968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
3135968caeeSMarri Devender Rao                     if (value)
3145968caeeSMarri Devender Rao                     {
3155968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
31637cce918SMarri Devender Rao                             asyncResp->res.jsonValue["Subject"], *value);
3175968caeeSMarri Devender Rao                     }
3185968caeeSMarri Devender Rao                 }
3195968caeeSMarri Devender Rao                 else if (property.first == "ValidNotAfter")
3205968caeeSMarri Devender Rao                 {
3215968caeeSMarri Devender Rao                     const uint64_t *value =
3225968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
3235968caeeSMarri Devender Rao                     if (value)
3245968caeeSMarri Devender Rao                     {
32537cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
3265968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotAfter"] =
3275968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
3285968caeeSMarri Devender Rao                     }
3295968caeeSMarri Devender Rao                 }
3305968caeeSMarri Devender Rao                 else if (property.first == "ValidNotBefore")
3315968caeeSMarri Devender Rao                 {
3325968caeeSMarri Devender Rao                     const uint64_t *value =
3335968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
3345968caeeSMarri Devender Rao                     if (value)
3355968caeeSMarri Devender Rao                     {
33637cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
3375968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotBefore"] =
3385968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
3395968caeeSMarri Devender Rao                     }
3405968caeeSMarri Devender Rao                 }
3415968caeeSMarri Devender Rao             }
3425968caeeSMarri Devender Rao             asyncResp->res.addHeader("Location", certURL);
3435968caeeSMarri Devender Rao         },
3445968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
3455968caeeSMarri Devender Rao         certs::certPropIntf);
3465968caeeSMarri Devender Rao }
3475968caeeSMarri Devender Rao 
3485968caeeSMarri Devender Rao using GetObjectType =
3495968caeeSMarri Devender Rao     std::vector<std::pair<std::string, std::vector<std::string>>>;
3505968caeeSMarri Devender Rao 
3515968caeeSMarri Devender Rao /**
3525968caeeSMarri Devender Rao  * Action to replace an existing certificate
3535968caeeSMarri Devender Rao  */
3545968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node
3555968caeeSMarri Devender Rao {
3565968caeeSMarri Devender Rao   public:
3575968caeeSMarri Devender Rao     CertificateActionsReplaceCertificate(CrowApp &app) :
3585968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/Actions/"
3595968caeeSMarri Devender Rao                   "CertificateService.ReplaceCertificate/")
3605968caeeSMarri Devender Rao     {
3615968caeeSMarri Devender Rao         entityPrivileges = {
3625968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
3635968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
3645968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
3655968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
3665968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
3675968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
3685968caeeSMarri Devender Rao     }
3695968caeeSMarri Devender Rao 
3705968caeeSMarri Devender Rao   private:
3715968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
3725968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
3735968caeeSMarri Devender Rao     {
3745968caeeSMarri Devender Rao         std::string certificate;
3755968caeeSMarri Devender Rao         nlohmann::json certificateUri;
3765968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
3775968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
3785968caeeSMarri Devender Rao         if (!json_util::readJson(req, asyncResp->res, "CertificateString",
3795968caeeSMarri Devender Rao                                  certificate, "CertificateUri", certificateUri,
3805968caeeSMarri Devender Rao                                  "CertificateType", certificateType))
3815968caeeSMarri Devender Rao         {
3825968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
3835968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
3845968caeeSMarri Devender Rao             return;
3855968caeeSMarri Devender Rao         }
3865968caeeSMarri Devender Rao 
3875968caeeSMarri Devender Rao         if (!certificateType)
3885968caeeSMarri Devender Rao         {
3895968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
3905968caeeSMarri Devender Rao             return;
3915968caeeSMarri Devender Rao         }
3925968caeeSMarri Devender Rao         if (certificateType != "PEM")
3935968caeeSMarri Devender Rao         {
3945968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
3955968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
3965968caeeSMarri Devender Rao             return;
3975968caeeSMarri Devender Rao         }
3985968caeeSMarri Devender Rao 
3995968caeeSMarri Devender Rao         std::string certURI;
4005968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
4015968caeeSMarri Devender Rao                                           "@odata.id", certURI))
4025968caeeSMarri Devender Rao         {
4035968caeeSMarri Devender Rao             messages::actionParameterMissing(
4045968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
4055968caeeSMarri Devender Rao             return;
4065968caeeSMarri Devender Rao         }
4075968caeeSMarri Devender Rao 
4085968caeeSMarri Devender Rao         BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
4095968caeeSMarri Devender Rao         long id = getIDFromURL(certURI);
4105968caeeSMarri Devender Rao         if (id < 0)
4115968caeeSMarri Devender Rao         {
4125968caeeSMarri Devender Rao             messages::actionParameterValueFormatError(asyncResp->res, certURI,
4135968caeeSMarri Devender Rao                                                       "CertificateUri",
4145968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
4155968caeeSMarri Devender Rao             return;
4165968caeeSMarri Devender Rao         }
4175968caeeSMarri Devender Rao         std::string objectPath;
4185968caeeSMarri Devender Rao         std::string name;
41937cce918SMarri Devender Rao         std::string service;
4205968caeeSMarri Devender Rao         if (boost::starts_with(
4215968caeeSMarri Devender Rao                 certURI,
4225968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"))
4235968caeeSMarri Devender Rao         {
4245968caeeSMarri Devender Rao             objectPath =
4255968caeeSMarri Devender Rao                 std::string(certs::httpsObjectPath) + "/" + std::to_string(id);
4265968caeeSMarri Devender Rao             name = "HTTPS certificate";
42737cce918SMarri Devender Rao             service = certs::httpsServiceName;
42837cce918SMarri Devender Rao         }
42937cce918SMarri Devender Rao         else if (boost::starts_with(
43037cce918SMarri Devender Rao                      certURI, "/redfish/v1/AccountService/LDAP/Certificates/"))
43137cce918SMarri Devender Rao         {
43237cce918SMarri Devender Rao             objectPath =
43337cce918SMarri Devender Rao                 std::string(certs::ldapObjectPath) + "/" + std::to_string(id);
43437cce918SMarri Devender Rao             name = "LDAP certificate";
43537cce918SMarri Devender Rao             service = certs::ldapServiceName;
4365968caeeSMarri Devender Rao         }
4375968caeeSMarri Devender Rao         else
4385968caeeSMarri Devender Rao         {
4395968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
4405968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
4415968caeeSMarri Devender Rao             return;
4425968caeeSMarri Devender Rao         }
4435968caeeSMarri Devender Rao 
4445968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
4455968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
4465968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
44737cce918SMarri Devender Rao             [asyncResp, certFile, objectPath, service, certURI, id,
4485968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
4495968caeeSMarri Devender Rao                 if (ec)
4505968caeeSMarri Devender Rao                 {
4515968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
452*8aae75adSMarri Devender Rao                     messages::resourceNotFound(asyncResp->res, name,
453*8aae75adSMarri Devender Rao                                                std::to_string(id));
4545968caeeSMarri Devender Rao                     return;
4555968caeeSMarri Devender Rao                 }
45637cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath, service, id,
4575968caeeSMarri Devender Rao                                          certURI, name);
4585968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
4595968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
4605968caeeSMarri Devender Rao             },
4615968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
4625968caeeSMarri Devender Rao             certFile->getCertFilePath());
4635968caeeSMarri Devender Rao     }
4645968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate
4655968caeeSMarri Devender Rao 
4665968caeeSMarri Devender Rao /**
4675968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
4685968caeeSMarri Devender Rao  * of a component, account or service.
4695968caeeSMarri Devender Rao  */
4705968caeeSMarri Devender Rao class HTTPSCertificate : public Node
4715968caeeSMarri Devender Rao {
4725968caeeSMarri Devender Rao   public:
4735968caeeSMarri Devender Rao     template <typename CrowApp>
4745968caeeSMarri Devender Rao     HTTPSCertificate(CrowApp &app) :
4755968caeeSMarri Devender Rao         Node(app,
4765968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
4775968caeeSMarri Devender Rao              "<str>/",
4785968caeeSMarri Devender Rao              std::string())
4795968caeeSMarri Devender Rao     {
4805968caeeSMarri Devender Rao         entityPrivileges = {
4815968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
4825968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
4835968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
4845968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
4855968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
4865968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
4875968caeeSMarri Devender Rao     }
4885968caeeSMarri Devender Rao 
4895968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
4905968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
4915968caeeSMarri Devender Rao     {
4925968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
4935968caeeSMarri Devender Rao         if (params.size() != 1)
4945968caeeSMarri Devender Rao         {
4955968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
4965968caeeSMarri Devender Rao             return;
4975968caeeSMarri Devender Rao         }
4985968caeeSMarri Devender Rao         long id = getIDFromURL(req.url);
4995968caeeSMarri Devender Rao 
5005968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id);
5015968caeeSMarri Devender Rao         std::string certURL =
5025968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
5035968caeeSMarri Devender Rao             std::to_string(id);
5045968caeeSMarri Devender Rao         std::string objectPath = certs::httpsObjectPath;
5055968caeeSMarri Devender Rao         objectPath += "/";
5065968caeeSMarri Devender Rao         objectPath += std::to_string(id);
50737cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
50837cce918SMarri Devender Rao                                  id, certURL, "HTTPS Certificate");
5095968caeeSMarri Devender Rao     }
5105968caeeSMarri Devender Rao 
5115968caeeSMarri Devender Rao }; // namespace redfish
5125968caeeSMarri Devender Rao 
5135968caeeSMarri Devender Rao /**
5145968caeeSMarri Devender Rao  * Collection of HTTPS certificates
5155968caeeSMarri Devender Rao  */
5165968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node
5175968caeeSMarri Devender Rao {
5185968caeeSMarri Devender Rao   public:
5195968caeeSMarri Devender Rao     template <typename CrowApp>
5205968caeeSMarri Devender Rao     HTTPSCertificateCollection(CrowApp &app) :
5215968caeeSMarri Devender Rao         Node(app,
5225968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
5235968caeeSMarri Devender Rao     {
5245968caeeSMarri Devender Rao         entityPrivileges = {
5255968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
5265968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
5275968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
5285968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
5295968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
5305968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
5315968caeeSMarri Devender Rao     }
5325968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
5335968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
5345968caeeSMarri Devender Rao     {
5355968caeeSMarri Devender Rao         res.jsonValue = {
5365968caeeSMarri Devender Rao             {"@odata.id",
5375968caeeSMarri Devender Rao              "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
5385968caeeSMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
5395968caeeSMarri Devender Rao             {"@odata.context",
5405968caeeSMarri Devender Rao              "/redfish/v1/"
5415968caeeSMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
5425968caeeSMarri Devender Rao             {"Name", "HTTPS Certificates Collection"},
5435968caeeSMarri Devender Rao             {"Description", "A Collection of HTTPS certificate instances"}};
5445968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
5455968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
5465968caeeSMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
5475968caeeSMarri Devender Rao                         const ManagedObjectType &certs) {
5485968caeeSMarri Devender Rao                 if (ec)
5495968caeeSMarri Devender Rao                 {
5505968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5515968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
5525968caeeSMarri Devender Rao                     return;
5535968caeeSMarri Devender Rao                 }
55437cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
5555968caeeSMarri Devender Rao                 members = nlohmann::json::array();
5565968caeeSMarri Devender Rao                 for (const auto &cert : certs)
5575968caeeSMarri Devender Rao                 {
5585968caeeSMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
55937cce918SMarri Devender Rao                     if (id >= 0)
5605968caeeSMarri Devender Rao                     {
5615968caeeSMarri Devender Rao                         members.push_back(
5625968caeeSMarri Devender Rao                             {{"@odata.id",
5635968caeeSMarri Devender Rao                               "/redfish/v1/Managers/bmc/"
5645968caeeSMarri Devender Rao                               "NetworkProtocol/HTTPS/Certificates/" +
5655968caeeSMarri Devender Rao                                   std::to_string(id)}});
5665968caeeSMarri Devender Rao                     }
5675968caeeSMarri Devender Rao                 }
5685968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
5695968caeeSMarri Devender Rao                     members.size();
5705968caeeSMarri Devender Rao             },
57137cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
57237cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
5735968caeeSMarri Devender Rao     }
5745968caeeSMarri Devender Rao 
5755968caeeSMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
5765968caeeSMarri Devender Rao                 const std::vector<std::string> &params) override
5775968caeeSMarri Devender Rao     {
5785968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
5795968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
5805968caeeSMarri Devender Rao         asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"},
5815968caeeSMarri Devender Rao                                     {"Description", "HTTPS Certificate"}};
5825968caeeSMarri Devender Rao 
5835968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
5845968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
5855968caeeSMarri Devender Rao 
5865968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
5875968caeeSMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
5885968caeeSMarri Devender Rao                 if (ec)
5895968caeeSMarri Devender Rao                 {
5905968caeeSMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5915968caeeSMarri Devender Rao                     messages::internalError(asyncResp->res);
5925968caeeSMarri Devender Rao                     return;
5935968caeeSMarri Devender Rao                 }
5945968caeeSMarri Devender Rao                 // TODO: Issue#84 supporting only 1 certificate
5955968caeeSMarri Devender Rao                 long certId = 1;
5965968caeeSMarri Devender Rao                 std::string certURL =
5975968caeeSMarri Devender Rao                     "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
5985968caeeSMarri Devender Rao                     "Certificates/" +
5995968caeeSMarri Devender Rao                     std::to_string(certId);
60037cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::httpsObjectPath) +
60137cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
60237cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
60337cce918SMarri Devender Rao                                          certs::httpsServiceName, certId,
6045968caeeSMarri Devender Rao                                          certURL, "HTTPS Certificate");
6055968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
6065968caeeSMarri Devender Rao                                  << certFile->getCertFilePath();
6075968caeeSMarri Devender Rao             },
60837cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
60937cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
6105968caeeSMarri Devender Rao     }
6115968caeeSMarri Devender Rao }; // HTTPSCertificateCollection
6125968caeeSMarri Devender Rao 
6135968caeeSMarri Devender Rao /**
6145968caeeSMarri Devender Rao  * The certificate location schema defines a resource that an administrator
6155968caeeSMarri Devender Rao  * can use in order to locate all certificates installed on a given service.
6165968caeeSMarri Devender Rao  */
6175968caeeSMarri Devender Rao class CertificateLocations : public Node
6185968caeeSMarri Devender Rao {
6195968caeeSMarri Devender Rao   public:
6205968caeeSMarri Devender Rao     template <typename CrowApp>
6215968caeeSMarri Devender Rao     CertificateLocations(CrowApp &app) :
6225968caeeSMarri Devender Rao         Node(app, "/redfish/v1/CertificateService/CertificateLocations/")
6235968caeeSMarri Devender Rao     {
6245968caeeSMarri Devender Rao         entityPrivileges = {
6255968caeeSMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
6265968caeeSMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
6275968caeeSMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
6285968caeeSMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
6295968caeeSMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
6305968caeeSMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
6315968caeeSMarri Devender Rao     }
6325968caeeSMarri Devender Rao 
6335968caeeSMarri Devender Rao   private:
6345968caeeSMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
6355968caeeSMarri Devender Rao                const std::vector<std::string> &params) override
6365968caeeSMarri Devender Rao     {
6375968caeeSMarri Devender Rao         res.jsonValue = {
6385968caeeSMarri Devender Rao             {"@odata.id",
6395968caeeSMarri Devender Rao              "/redfish/v1/CertificateService/CertificateLocations"},
6405968caeeSMarri Devender Rao             {"@odata.type",
6415968caeeSMarri Devender Rao              "#CertificateLocations.v1_0_0.CertificateLocations"},
6425968caeeSMarri Devender Rao             {"@odata.context",
6435968caeeSMarri Devender Rao              "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"},
6445968caeeSMarri Devender Rao             {"Name", "Certificate Locations"},
6455968caeeSMarri Devender Rao             {"Id", "CertificateLocations"},
6465968caeeSMarri Devender Rao             {"Description",
6475968caeeSMarri Devender Rao              "Defines a resource that an administrator can use in order to "
6485968caeeSMarri Devender Rao              "locate all certificates installed on a given service"}};
6495968caeeSMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
6505968caeeSMarri Devender Rao         nlohmann::json &links =
6515968caeeSMarri Devender Rao             asyncResp->res.jsonValue["Links"]["Certificates"];
6525968caeeSMarri Devender Rao         links = nlohmann::json::array();
6535968caeeSMarri Devender Rao         getCertificateLocations(
6545968caeeSMarri Devender Rao             asyncResp,
6555968caeeSMarri Devender Rao             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
65637cce918SMarri Devender Rao             certs::httpsObjectPath, certs::httpsServiceName);
65737cce918SMarri Devender Rao         getCertificateLocations(asyncResp,
65837cce918SMarri Devender Rao                                 "/redfish/v1/AccountService/LDAP/Certificates/",
65937cce918SMarri Devender Rao                                 certs::ldapObjectPath, certs::ldapServiceName);
66037cce918SMarri Devender Rao     }
66137cce918SMarri Devender Rao     /**
66237cce918SMarri Devender Rao      * @brief Retrieve the certificates installed list and append to the
66337cce918SMarri Devender Rao      * response
66437cce918SMarri Devender Rao      *
66537cce918SMarri Devender Rao      * @param[in] asyncResp Shared pointer to the response message
66637cce918SMarri Devender Rao      * @param[in] certURL  Path of the certificate object
66737cce918SMarri Devender Rao      * @param[in] path  Path of the D-Bus service object
66837cce918SMarri Devender Rao      * @return None
66937cce918SMarri Devender Rao      */
67037cce918SMarri Devender Rao     void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp,
67137cce918SMarri Devender Rao                                  const std::string &certURL,
67237cce918SMarri Devender Rao                                  const std::string &path,
67337cce918SMarri Devender Rao                                  const std::string &service)
67437cce918SMarri Devender Rao     {
67537cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
67637cce918SMarri Devender Rao                          << " Path=" << path << " service= " << service;
67737cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
67837cce918SMarri Devender Rao             [asyncResp, certURL](const boost::system::error_code ec,
67937cce918SMarri Devender Rao                                  const ManagedObjectType &certs) {
68037cce918SMarri Devender Rao                 if (ec)
68137cce918SMarri Devender Rao                 {
68237cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
68337cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
68437cce918SMarri Devender Rao                     return;
68537cce918SMarri Devender Rao                 }
68637cce918SMarri Devender Rao                 nlohmann::json &links =
68737cce918SMarri Devender Rao                     asyncResp->res.jsonValue["Links"]["Certificates"];
68837cce918SMarri Devender Rao                 for (auto &cert : certs)
68937cce918SMarri Devender Rao                 {
69037cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
69137cce918SMarri Devender Rao                     if (id >= 0)
69237cce918SMarri Devender Rao                     {
69337cce918SMarri Devender Rao                         links.push_back(
69437cce918SMarri Devender Rao                             {{"@odata.id", certURL + std::to_string(id)}});
69537cce918SMarri Devender Rao                     }
69637cce918SMarri Devender Rao                 }
69737cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
69837cce918SMarri Devender Rao                     links.size();
69937cce918SMarri Devender Rao             },
70037cce918SMarri Devender Rao             service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
7015968caeeSMarri Devender Rao     }
7025968caeeSMarri Devender Rao }; // CertificateLocations
70337cce918SMarri Devender Rao 
70437cce918SMarri Devender Rao /**
70537cce918SMarri Devender Rao  * Collection of LDAP certificates
70637cce918SMarri Devender Rao  */
70737cce918SMarri Devender Rao class LDAPCertificateCollection : public Node
70837cce918SMarri Devender Rao {
70937cce918SMarri Devender Rao   public:
71037cce918SMarri Devender Rao     template <typename CrowApp>
71137cce918SMarri Devender Rao     LDAPCertificateCollection(CrowApp &app) :
71237cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/")
71337cce918SMarri Devender Rao     {
71437cce918SMarri Devender Rao         entityPrivileges = {
71537cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
71637cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
71737cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
71837cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
71937cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
72037cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
72137cce918SMarri Devender Rao     }
72237cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
72337cce918SMarri Devender Rao                const std::vector<std::string> &params) override
72437cce918SMarri Devender Rao     {
72537cce918SMarri Devender Rao         res.jsonValue = {
72637cce918SMarri Devender Rao             {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"},
72737cce918SMarri Devender Rao             {"@odata.type", "#CertificateCollection.CertificateCollection"},
72837cce918SMarri Devender Rao             {"@odata.context",
72937cce918SMarri Devender Rao              "/redfish/v1/"
73037cce918SMarri Devender Rao              "$metadata#CertificateCollection.CertificateCollection"},
73137cce918SMarri Devender Rao             {"Name", "LDAP Certificates Collection"},
73237cce918SMarri Devender Rao             {"Description", "A Collection of LDAP certificate instances"}};
73337cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
73437cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
73537cce918SMarri Devender Rao             [asyncResp](const boost::system::error_code ec,
73637cce918SMarri Devender Rao                         const ManagedObjectType &certs) {
73737cce918SMarri Devender Rao                 if (ec)
73837cce918SMarri Devender Rao                 {
73937cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
74037cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
74137cce918SMarri Devender Rao                     return;
74237cce918SMarri Devender Rao                 }
74337cce918SMarri Devender Rao                 nlohmann::json &members = asyncResp->res.jsonValue["Members"];
74437cce918SMarri Devender Rao                 members = nlohmann::json::array();
74537cce918SMarri Devender Rao                 for (const auto &cert : certs)
74637cce918SMarri Devender Rao                 {
74737cce918SMarri Devender Rao                     long id = getIDFromURL(cert.first.str);
74837cce918SMarri Devender Rao                     if (id >= 0)
74937cce918SMarri Devender Rao                     {
75037cce918SMarri Devender Rao                         members.push_back(
75137cce918SMarri Devender Rao                             {{"@odata.id", "/redfish/v1/AccountService/"
75237cce918SMarri Devender Rao                                            "LDAP/Certificates/" +
75337cce918SMarri Devender Rao                                                std::to_string(id)}});
75437cce918SMarri Devender Rao                     }
75537cce918SMarri Devender Rao                 }
75637cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Members@odata.count"] =
75737cce918SMarri Devender Rao                     members.size();
75837cce918SMarri Devender Rao             },
75937cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
76037cce918SMarri Devender Rao             certs::dbusObjManagerIntf, "GetManagedObjects");
76137cce918SMarri Devender Rao     }
76237cce918SMarri Devender Rao 
76337cce918SMarri Devender Rao     void doPost(crow::Response &res, const crow::Request &req,
76437cce918SMarri Devender Rao                 const std::vector<std::string> &params) override
76537cce918SMarri Devender Rao     {
76637cce918SMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
76737cce918SMarri Devender Rao             std::make_shared<CertificateFile>(req.body);
76837cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
76937cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
77037cce918SMarri Devender Rao             [asyncResp, certFile](const boost::system::error_code ec) {
77137cce918SMarri Devender Rao                 if (ec)
77237cce918SMarri Devender Rao                 {
77337cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
77437cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
77537cce918SMarri Devender Rao                     return;
77637cce918SMarri Devender Rao                 }
77737cce918SMarri Devender Rao                 //// TODO: Issue#84 supporting only 1 certificate
77837cce918SMarri Devender Rao                 long certId = 1;
77937cce918SMarri Devender Rao                 std::string certURL =
78037cce918SMarri Devender Rao                     "/redfish/v1/AccountService/LDAP/Certificates/" +
78137cce918SMarri Devender Rao                     std::to_string(certId);
78237cce918SMarri Devender Rao                 std::string objectPath = std::string(certs::ldapObjectPath) +
78337cce918SMarri Devender Rao                                          "/" + std::to_string(certId);
78437cce918SMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
78537cce918SMarri Devender Rao                                          certs::ldapServiceName, certId,
78637cce918SMarri Devender Rao                                          certURL, "LDAP Certificate");
78737cce918SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "LDAP certificate install file="
78837cce918SMarri Devender Rao                                  << certFile->getCertFilePath();
78937cce918SMarri Devender Rao             },
79037cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
79137cce918SMarri Devender Rao             certs::certInstallIntf, "Install", certFile->getCertFilePath());
79237cce918SMarri Devender Rao     }
79337cce918SMarri Devender Rao }; // LDAPCertificateCollection
79437cce918SMarri Devender Rao 
79537cce918SMarri Devender Rao /**
79637cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
79737cce918SMarri Devender Rao  * of a component, account or service.
79837cce918SMarri Devender Rao  */
79937cce918SMarri Devender Rao class LDAPCertificate : public Node
80037cce918SMarri Devender Rao {
80137cce918SMarri Devender Rao   public:
80237cce918SMarri Devender Rao     template <typename CrowApp>
80337cce918SMarri Devender Rao     LDAPCertificate(CrowApp &app) :
80437cce918SMarri Devender Rao         Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/",
80537cce918SMarri Devender Rao              std::string())
80637cce918SMarri Devender Rao     {
80737cce918SMarri Devender Rao         entityPrivileges = {
80837cce918SMarri Devender Rao             {boost::beast::http::verb::get, {{"Login"}}},
80937cce918SMarri Devender Rao             {boost::beast::http::verb::head, {{"Login"}}},
81037cce918SMarri Devender Rao             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
81137cce918SMarri Devender Rao             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
81237cce918SMarri Devender Rao             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
81337cce918SMarri Devender Rao             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
81437cce918SMarri Devender Rao     }
81537cce918SMarri Devender Rao 
81637cce918SMarri Devender Rao     void doGet(crow::Response &res, const crow::Request &req,
81737cce918SMarri Devender Rao                const std::vector<std::string> &params) override
81837cce918SMarri Devender Rao     {
81937cce918SMarri Devender Rao         auto asyncResp = std::make_shared<AsyncResp>(res);
82037cce918SMarri Devender Rao         long id = getIDFromURL(req.url);
82137cce918SMarri Devender Rao         if (id < 0)
82237cce918SMarri Devender Rao         {
82337cce918SMarri Devender Rao             BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
82437cce918SMarri Devender Rao             messages::internalError(asyncResp->res);
82537cce918SMarri Devender Rao             return;
82637cce918SMarri Devender Rao         }
82737cce918SMarri Devender Rao         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id);
82837cce918SMarri Devender Rao         std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" +
82937cce918SMarri Devender Rao                               std::to_string(id);
83037cce918SMarri Devender Rao         std::string objectPath = certs::ldapObjectPath;
83137cce918SMarri Devender Rao         objectPath += "/";
83237cce918SMarri Devender Rao         objectPath += std::to_string(id);
83337cce918SMarri Devender Rao         getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
83437cce918SMarri Devender Rao                                  id, certURL, "LDAP Certificate");
83537cce918SMarri Devender Rao     }
83637cce918SMarri Devender Rao }; // LDAPCertificate
8375968caeeSMarri Devender Rao } // namespace redfish
838