certificate: Replace lambda with inline function

For API endpoints, it is suggested to break out the entire handlers
into a function, and not rely on a lambda at all. This brings more
readability as it reduces indents.

Tested:
Code compiles, and Redfish Service Validator passed.

Change-Id: I5132149c00b6f553931dae562b83bc7aee678105
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@intel.com>
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index ed42b89..796df8d 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -190,14 +190,8 @@
         requestRoutesMessageRegistry(app);
 
         requestRoutesCertificateService(app);
-        requestRoutesCertificateActionGenerateCSR(app);
-        requestRoutesCertificateActionsReplaceCertificate(app);
         requestRoutesHTTPSCertificate(app);
-        requestRoutesHTTPSCertificateCollection(app);
-        requestRoutesCertificateLocations(app);
-        requestRoutesLDAPCertificateCollection(app);
         requestRoutesLDAPCertificate(app);
-        requestRoutesTrustStoreCertificateCollection(app);
         requestRoutesTrustStoreCertificate(app);
 
         requestRoutesSystemPCIeFunctionCollection(app);
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index d3aedd0..8701f59 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -47,50 +47,6 @@
 // "redfish standard registries". Need to modify after DMTF
 // publish Privilege details for certificate service
 
-inline void requestRoutesCertificateService(App& app)
-{
-    BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
-        .privileges(redfish::privileges::getCertificateService)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-
-        asyncResp->res.jsonValue["@odata.type"] =
-            "#CertificateService.v1_0_0.CertificateService";
-        asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/CertificateService";
-        asyncResp->res.jsonValue["Id"] = "CertificateService";
-        asyncResp->res.jsonValue["Name"] = "Certificate Service";
-        asyncResp->res.jsonValue["Description"] =
-            "Actions available to manage certificates";
-        // /redfish/v1/CertificateService/CertificateLocations is something
-        // only ConfigureManager can access then only display when the user
-        // has permissions ConfigureManager
-        Privileges effectiveUserPrivileges =
-            redfish::getUserPrivileges(req.userRole);
-        if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
-                                             effectiveUserPrivileges))
-        {
-            asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
-                "/redfish/v1/CertificateService/CertificateLocations";
-        }
-        nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
-        nlohmann::json& replace =
-            actions["#CertificateService.ReplaceCertificate"];
-        replace["target"] =
-            "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate";
-        nlohmann::json::array_t allowed;
-        allowed.push_back("PEM");
-        replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
-        actions["#CertificateService.GenerateCSR"]["target"] =
-            "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
-        });
-} // requestRoutesCertificateService
-
 inline std::string getCertificateFromReqBody(
     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
     const crow::Request& req)
@@ -180,293 +136,6 @@
     std::filesystem::path certDirectory;
 };
 
-static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
-/**
- * @brief Read data from CSR D-bus object and set to response
- *
- * @param[in] asyncResp Shared pointer to the response message
- * @param[in] certURI Link to certifiate collection URI
- * @param[in] service D-Bus service name
- * @param[in] certObjPath certificate D-Bus object path
- * @param[in] csrObjPath CSR D-Bus object path
- * @return None
- */
-static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& certURI, const std::string& service,
-                   const std::string& certObjPath,
-                   const std::string& csrObjPath)
-{
-    BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
-                     << " CSRObjectPath=" << csrObjPath
-                     << " service=" << service;
-    crow::connections::systemBus->async_method_call(
-        [asyncResp, certURI](const boost::system::error_code ec,
-                             const std::string& csr) {
-        if (ec)
-        {
-            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
-            messages::internalError(asyncResp->res);
-            return;
-        }
-        if (csr.empty())
-        {
-            BMCWEB_LOG_ERROR << "CSR read is empty";
-            messages::internalError(asyncResp->res);
-            return;
-        }
-        asyncResp->res.jsonValue["CSRString"] = csr;
-        asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
-            certURI;
-        },
-        service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
-}
-
-/**
- * Action to Generate CSR
- */
-inline void requestRoutesCertificateActionGenerateCSR(App& app)
-{
-    BMCWEB_ROUTE(
-        app,
-        "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
-        .privileges(redfish::privileges::postCertificateService)
-        .methods(boost::beast::http::verb::post)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        static const int rsaKeyBitLength = 2048;
-
-        // Required parameters
-        std::string city;
-        std::string commonName;
-        std::string country;
-        std::string organization;
-        std::string organizationalUnit;
-        std::string state;
-        nlohmann::json certificateCollection;
-
-        // Optional parameters
-        std::optional<std::vector<std::string>> optAlternativeNames =
-            std::vector<std::string>();
-        std::optional<std::string> optContactPerson = "";
-        std::optional<std::string> optChallengePassword = "";
-        std::optional<std::string> optEmail = "";
-        std::optional<std::string> optGivenName = "";
-        std::optional<std::string> optInitials = "";
-        std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
-        std::optional<std::string> optKeyCurveId = "secp384r1";
-        std::optional<std::string> optKeyPairAlgorithm = "EC";
-        std::optional<std::vector<std::string>> optKeyUsage =
-            std::vector<std::string>();
-        std::optional<std::string> optSurname = "";
-        std::optional<std::string> optUnstructuredName = "";
-        if (!json_util::readJsonAction(
-                req, asyncResp->res, "City", city, "CommonName", commonName,
-                "ContactPerson", optContactPerson, "Country", country,
-                "Organization", organization, "OrganizationalUnit",
-                organizationalUnit, "State", state, "CertificateCollection",
-                certificateCollection, "AlternativeNames", optAlternativeNames,
-                "ChallengePassword", optChallengePassword, "Email", optEmail,
-                "GivenName", optGivenName, "Initials", optInitials,
-                "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
-                "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
-                optKeyUsage, "Surname", optSurname, "UnstructuredName",
-                optUnstructuredName))
-        {
-            return;
-        }
-
-        // bmcweb has no way to store or decode a private key challenge
-        // password, which will likely cause bmcweb to crash on startup
-        // if this is not set on a post so not allowing the user to set
-        // value
-        if (!optChallengePassword->empty())
-        {
-            messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
-                                                  "ChallengePassword");
-            return;
-        }
-
-        std::string certURI;
-        if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
-                                          "@odata.id", certURI))
-        {
-            return;
-        }
-
-        std::string objectPath;
-        std::string service;
-        if (certURI.starts_with(
-                "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
-        {
-            objectPath = certs::httpsObjectPath;
-            service = certs::httpsServiceName;
-        }
-        else if (certURI.starts_with(
-                     "/redfish/v1/AccountService/LDAP/Certificates"))
-        {
-            objectPath = certs::ldapObjectPath;
-            service = certs::ldapServiceName;
-        }
-        else
-        {
-            messages::actionParameterNotSupported(
-                asyncResp->res, "CertificateCollection", "GenerateCSR");
-            return;
-        }
-
-        // supporting only EC and RSA algorithm
-        if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
-        {
-            messages::actionParameterNotSupported(
-                asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
-            return;
-        }
-
-        // supporting only 2048 key bit length for RSA algorithm due to
-        // time consumed in generating private key
-        if (*optKeyPairAlgorithm == "RSA" &&
-            *optKeyBitLength != rsaKeyBitLength)
-        {
-            messages::propertyValueNotInList(asyncResp->res,
-                                             std::to_string(*optKeyBitLength),
-                                             "KeyBitLength");
-            return;
-        }
-
-        // validate KeyUsage supporting only 1 type based on URL
-        if (certURI.starts_with(
-                "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
-        {
-            if (optKeyUsage->empty())
-            {
-                optKeyUsage->push_back("ServerAuthentication");
-            }
-            else if (optKeyUsage->size() == 1)
-            {
-                if ((*optKeyUsage)[0] != "ServerAuthentication")
-                {
-                    messages::propertyValueNotInList(
-                        asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
-                    return;
-                }
-            }
-            else
-            {
-                messages::actionParameterNotSupported(
-                    asyncResp->res, "KeyUsage", "GenerateCSR");
-                return;
-            }
-        }
-        else if (certURI.starts_with(
-                     "/redfish/v1/AccountService/LDAP/Certificates"))
-        {
-            if (optKeyUsage->empty())
-            {
-                optKeyUsage->push_back("ClientAuthentication");
-            }
-            else if (optKeyUsage->size() == 1)
-            {
-                if ((*optKeyUsage)[0] != "ClientAuthentication")
-                {
-                    messages::propertyValueNotInList(
-                        asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
-                    return;
-                }
-            }
-            else
-            {
-                messages::actionParameterNotSupported(
-                    asyncResp->res, "KeyUsage", "GenerateCSR");
-                return;
-            }
-        }
-
-        // Only allow one CSR matcher at a time so setting retry
-        // time-out and timer expiry to 10 seconds for now.
-        static const int timeOut = 10;
-        if (csrMatcher)
-        {
-            messages::serviceTemporarilyUnavailable(asyncResp->res,
-                                                    std::to_string(timeOut));
-            return;
-        }
-
-        // Make this static so it survives outside this method
-        static boost::asio::steady_timer timeout(*req.ioService);
-        timeout.expires_after(std::chrono::seconds(timeOut));
-        timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
-            csrMatcher = nullptr;
-            if (ec)
-            {
-                // operation_aborted is expected if timer is canceled
-                // before completion.
-                if (ec != boost::asio::error::operation_aborted)
-                {
-                    BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
-                }
-                return;
-            }
-            BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
-            messages::internalError(asyncResp->res);
-        });
-
-        // create a matcher to wait on CSR object
-        BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
-        std::string match("type='signal',"
-                          "interface='org.freedesktop.DBus.ObjectManager',"
-                          "path='" +
-                          objectPath +
-                          "',"
-                          "member='InterfacesAdded'");
-        csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
-            *crow::connections::systemBus, match,
-            [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
-            timeout.cancel();
-            if (m.is_method_error())
-            {
-                BMCWEB_LOG_ERROR << "Dbus method error!!!";
-                messages::internalError(asyncResp->res);
-                return;
-            }
-
-            dbus::utility::DBusInteracesMap interfacesProperties;
-
-            sdbusplus::message::object_path csrObjectPath;
-            m.read(csrObjectPath, interfacesProperties);
-            BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
-            for (const auto& interface : interfacesProperties)
-            {
-                if (interface.first == "xyz.openbmc_project.Certs.CSR")
-                {
-                    getCSR(asyncResp, certURI, service, objectPath,
-                           csrObjectPath.str);
-                    break;
-                }
-            }
-            });
-        crow::connections::systemBus->async_method_call(
-            [asyncResp](const boost::system::error_code ec,
-                        const std::string&) {
-            if (ec)
-            {
-                BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
-                messages::internalError(asyncResp->res);
-                return;
-            }
-            },
-            service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
-            "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
-            commonName, *optContactPerson, country, *optEmail, *optGivenName,
-            *optInitials, *optKeyBitLength, *optKeyCurveId,
-            *optKeyPairAlgorithm, *optKeyUsage, organization,
-            organizationalUnit, state, *optSurname, *optUnstructuredName);
-        });
-} // requestRoutesCertificateActionGenerateCSR
-
 /**
  * @brief Parse and update Certificate Issue/Subject property
  *
@@ -707,512 +376,827 @@
         });
 }
 
-/**
- * Action to replace an existing certificate
- */
-inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
+inline void handleCertificateServiceGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
 {
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#CertificateService.v1_0_0.CertificateService";
+    asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService";
+    asyncResp->res.jsonValue["Id"] = "CertificateService";
+    asyncResp->res.jsonValue["Name"] = "Certificate Service";
+    asyncResp->res.jsonValue["Description"] =
+        "Actions available to manage certificates";
+    // /redfish/v1/CertificateService/CertificateLocations is something
+    // only ConfigureManager can access then only display when the user
+    // has permissions ConfigureManager
+    Privileges effectiveUserPrivileges =
+        redfish::getUserPrivileges(req.userRole);
+    if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
+                                         effectiveUserPrivileges))
+    {
+        asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
+            "/redfish/v1/CertificateService/CertificateLocations";
+    }
+    nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
+    nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"];
+    replace["target"] =
+        "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate";
+    nlohmann::json::array_t allowed;
+    allowed.push_back("PEM");
+    replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
+    actions["#CertificateService.GenerateCSR"]["target"] =
+        "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
+}
+
+inline void handleCertificateLocationsGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    asyncResp->res.jsonValue["@odata.id"] =
+        "/redfish/v1/CertificateService/CertificateLocations";
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#CertificateLocations.v1_0_0.CertificateLocations";
+    asyncResp->res.jsonValue["Name"] = "Certificate Locations";
+    asyncResp->res.jsonValue["Id"] = "CertificateLocations";
+    asyncResp->res.jsonValue["Description"] =
+        "Defines a resource that an administrator can use in order to "
+        "locate all certificates installed on a given service";
+
+    getCertificateList(asyncResp, certs::baseObjectPath,
+                       "/Links/Certificates"_json_pointer,
+                       "/Links/Certificates@odata.count"_json_pointer);
+}
+
+inline void handleReplaceCertificateAction(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    std::string certificate;
+    nlohmann::json certificateUri;
+    std::optional<std::string> certificateType = "PEM";
+
+    if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
+                                   certificate, "CertificateUri",
+                                   certificateUri, "CertificateType",
+                                   certificateType))
+    {
+        BMCWEB_LOG_ERROR << "Required parameters are missing";
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    if (!certificateType)
+    {
+        // should never happen, but it never hurts to be paranoid.
+        return;
+    }
+    if (certificateType != "PEM")
+    {
+        messages::actionParameterNotSupported(asyncResp->res, "CertificateType",
+                                              "ReplaceCertificate");
+        return;
+    }
+
+    std::string certURI;
+    if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
+                                      "@odata.id", certURI))
+    {
+        messages::actionParameterMissing(asyncResp->res, "ReplaceCertificate",
+                                         "CertificateUri");
+        return;
+    }
+    BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI;
+
+    boost::urls::result<boost::urls::url_view> parsedUrl =
+        boost::urls::parse_relative_ref(certURI);
+    if (!parsedUrl)
+    {
+        messages::actionParameterValueFormatError(
+            asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate");
+        return;
+    }
+
+    std::string id;
+    sdbusplus::message::object_path objectPath;
+    std::string name;
+    std::string service;
+    if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers",
+                                       "bmc", "NetworkProtocol", "HTTPS",
+                                       "Certificates", std::ref(id)))
+    {
+        objectPath =
+            sdbusplus::message::object_path(certs::httpsObjectPath) / id;
+        name = "HTTPS certificate";
+        service = certs::httpsServiceName;
+    }
+    else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
+                                            "AccountService", "LDAP",
+                                            "Certificates", std::ref(id)))
+    {
+        objectPath =
+            sdbusplus::message::object_path(certs::ldapObjectPath) / id;
+        name = "LDAP certificate";
+        service = certs::ldapServiceName;
+    }
+    else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
+                                            "Managers", "bmc", "Truststore",
+                                            "Certificates", std::ref(id)))
+    {
+        objectPath =
+            sdbusplus::message::object_path(certs::authorityObjectPath) / id;
+        name = "TrustStore certificate";
+        service = certs::authorityServiceName;
+    }
+    else
+    {
+        messages::actionParameterNotSupported(asyncResp->res, "CertificateUri",
+                                              "ReplaceCertificate");
+        return;
+    }
+
+    std::shared_ptr<CertificateFile> certFile =
+        std::make_shared<CertificateFile>(certificate);
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
+         name](const boost::system::error_code ec) {
+        if (ec)
+        {
+            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+            if (ec.value() ==
+                boost::system::linux_error::bad_request_descriptor)
+            {
+                messages::resourceNotFound(asyncResp->res, "Certificate", id);
+                return;
+            }
+            messages::internalError(asyncResp->res);
+            return;
+        }
+        getCertificateProperties(asyncResp, objectPath, service, id, url, name);
+        BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
+                         << certFile->getCertFilePath();
+        },
+        service, objectPath, certs::certReplaceIntf, "Replace",
+        certFile->getCertFilePath());
+}
+
+static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
+/**
+ * @brief Read data from CSR D-bus object and set to response
+ *
+ * @param[in] asyncResp Shared pointer to the response message
+ * @param[in] certURI Link to certifiate collection URI
+ * @param[in] service D-Bus service name
+ * @param[in] certObjPath certificate D-Bus object path
+ * @param[in] csrObjPath CSR D-Bus object path
+ * @return None
+ */
+static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                   const std::string& certURI, const std::string& service,
+                   const std::string& certObjPath,
+                   const std::string& csrObjPath)
+{
+    BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
+                     << " CSRObjectPath=" << csrObjPath
+                     << " service=" << service;
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, certURI](const boost::system::error_code ec,
+                             const std::string& csr) {
+        if (ec)
+        {
+            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+            messages::internalError(asyncResp->res);
+            return;
+        }
+        if (csr.empty())
+        {
+            BMCWEB_LOG_ERROR << "CSR read is empty";
+            messages::internalError(asyncResp->res);
+            return;
+        }
+        asyncResp->res.jsonValue["CSRString"] = csr;
+        asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
+            certURI;
+        },
+        service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
+}
+
+inline void
+    handleGenerateCSRAction(App& app, const crow::Request& req,
+                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    static const int rsaKeyBitLength = 2048;
+
+    // Required parameters
+    std::string city;
+    std::string commonName;
+    std::string country;
+    std::string organization;
+    std::string organizationalUnit;
+    std::string state;
+    nlohmann::json certificateCollection;
+
+    // Optional parameters
+    std::optional<std::vector<std::string>> optAlternativeNames =
+        std::vector<std::string>();
+    std::optional<std::string> optContactPerson = "";
+    std::optional<std::string> optChallengePassword = "";
+    std::optional<std::string> optEmail = "";
+    std::optional<std::string> optGivenName = "";
+    std::optional<std::string> optInitials = "";
+    std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
+    std::optional<std::string> optKeyCurveId = "secp384r1";
+    std::optional<std::string> optKeyPairAlgorithm = "EC";
+    std::optional<std::vector<std::string>> optKeyUsage =
+        std::vector<std::string>();
+    std::optional<std::string> optSurname = "";
+    std::optional<std::string> optUnstructuredName = "";
+    if (!json_util::readJsonAction(
+            req, asyncResp->res, "City", city, "CommonName", commonName,
+            "ContactPerson", optContactPerson, "Country", country,
+            "Organization", organization, "OrganizationalUnit",
+            organizationalUnit, "State", state, "CertificateCollection",
+            certificateCollection, "AlternativeNames", optAlternativeNames,
+            "ChallengePassword", optChallengePassword, "Email", optEmail,
+            "GivenName", optGivenName, "Initials", optInitials, "KeyBitLength",
+            optKeyBitLength, "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm",
+            optKeyPairAlgorithm, "KeyUsage", optKeyUsage, "Surname", optSurname,
+            "UnstructuredName", optUnstructuredName))
+    {
+        return;
+    }
+
+    // bmcweb has no way to store or decode a private key challenge
+    // password, which will likely cause bmcweb to crash on startup
+    // if this is not set on a post so not allowing the user to set
+    // value
+    if (!optChallengePassword->empty())
+    {
+        messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
+                                              "ChallengePassword");
+        return;
+    }
+
+    std::string certURI;
+    if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
+                                      "@odata.id", certURI))
+    {
+        return;
+    }
+
+    std::string objectPath;
+    std::string service;
+    if (certURI.starts_with(
+            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
+    {
+        objectPath = certs::httpsObjectPath;
+        service = certs::httpsServiceName;
+    }
+    else if (certURI.starts_with(
+                 "/redfish/v1/AccountService/LDAP/Certificates"))
+    {
+        objectPath = certs::ldapObjectPath;
+        service = certs::ldapServiceName;
+    }
+    else
+    {
+        messages::actionParameterNotSupported(
+            asyncResp->res, "CertificateCollection", "GenerateCSR");
+        return;
+    }
+
+    // supporting only EC and RSA algorithm
+    if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
+    {
+        messages::actionParameterNotSupported(
+            asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
+        return;
+    }
+
+    // supporting only 2048 key bit length for RSA algorithm due to
+    // time consumed in generating private key
+    if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength)
+    {
+        messages::propertyValueNotInList(
+            asyncResp->res, std::to_string(*optKeyBitLength), "KeyBitLength");
+        return;
+    }
+
+    // validate KeyUsage supporting only 1 type based on URL
+    if (certURI.starts_with(
+            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
+    {
+        if (optKeyUsage->empty())
+        {
+            optKeyUsage->push_back("ServerAuthentication");
+        }
+        else if (optKeyUsage->size() == 1)
+        {
+            if ((*optKeyUsage)[0] != "ServerAuthentication")
+            {
+                messages::propertyValueNotInList(asyncResp->res,
+                                                 (*optKeyUsage)[0], "KeyUsage");
+                return;
+            }
+        }
+        else
+        {
+            messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
+                                                  "GenerateCSR");
+            return;
+        }
+    }
+    else if (certURI.starts_with(
+                 "/redfish/v1/AccountService/LDAP/Certificates"))
+    {
+        if (optKeyUsage->empty())
+        {
+            optKeyUsage->push_back("ClientAuthentication");
+        }
+        else if (optKeyUsage->size() == 1)
+        {
+            if ((*optKeyUsage)[0] != "ClientAuthentication")
+            {
+                messages::propertyValueNotInList(asyncResp->res,
+                                                 (*optKeyUsage)[0], "KeyUsage");
+                return;
+            }
+        }
+        else
+        {
+            messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
+                                                  "GenerateCSR");
+            return;
+        }
+    }
+
+    // Only allow one CSR matcher at a time so setting retry
+    // time-out and timer expiry to 10 seconds for now.
+    static const int timeOut = 10;
+    if (csrMatcher)
+    {
+        messages::serviceTemporarilyUnavailable(asyncResp->res,
+                                                std::to_string(timeOut));
+        return;
+    }
+
+    // Make this static so it survives outside this method
+    static boost::asio::steady_timer timeout(*req.ioService);
+    timeout.expires_after(std::chrono::seconds(timeOut));
+    timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
+        csrMatcher = nullptr;
+        if (ec)
+        {
+            // operation_aborted is expected if timer is canceled
+            // before completion.
+            if (ec != boost::asio::error::operation_aborted)
+            {
+                BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
+            }
+            return;
+        }
+        BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
+        messages::internalError(asyncResp->res);
+    });
+
+    // create a matcher to wait on CSR object
+    BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
+    std::string match("type='signal',"
+                      "interface='org.freedesktop.DBus.ObjectManager',"
+                      "path='" +
+                      objectPath +
+                      "',"
+                      "member='InterfacesAdded'");
+    csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
+        *crow::connections::systemBus, match,
+        [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
+        timeout.cancel();
+        if (m.is_method_error())
+        {
+            BMCWEB_LOG_ERROR << "Dbus method error!!!";
+            messages::internalError(asyncResp->res);
+            return;
+        }
+
+        dbus::utility::DBusInteracesMap interfacesProperties;
+
+        sdbusplus::message::object_path csrObjectPath;
+        m.read(csrObjectPath, interfacesProperties);
+        BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
+        for (const auto& interface : interfacesProperties)
+        {
+            if (interface.first == "xyz.openbmc_project.Certs.CSR")
+            {
+                getCSR(asyncResp, certURI, service, objectPath,
+                       csrObjectPath.str);
+                break;
+            }
+        }
+        });
+    crow::connections::systemBus->async_method_call(
+        [asyncResp](const boost::system::error_code ec, const std::string&) {
+        if (ec)
+        {
+            BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
+            messages::internalError(asyncResp->res);
+            return;
+        }
+        },
+        service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
+        "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
+        commonName, *optContactPerson, country, *optEmail, *optGivenName,
+        *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm,
+        *optKeyUsage, organization, organizationalUnit, state, *optSurname,
+        *optUnstructuredName);
+}
+
+inline void requestRoutesCertificateService(App& app)
+{
+    BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
+        .privileges(redfish::privileges::getCertificateService)
+        .methods(boost::beast::http::verb::get)(
+            std::bind_front(handleCertificateServiceGet, std::ref(app)));
+
+    BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
+        .privileges(redfish::privileges::getCertificateLocations)
+        .methods(boost::beast::http::verb::get)(
+            std::bind_front(handleCertificateLocationsGet, std::ref(app)));
+
     BMCWEB_ROUTE(
         app,
         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
         .privileges(redfish::privileges::postCertificateService)
         .methods(boost::beast::http::verb::post)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        std::string certificate;
-        nlohmann::json certificateUri;
-        std::optional<std::string> certificateType = "PEM";
+            std::bind_front(handleReplaceCertificateAction, std::ref(app)));
 
-        if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
-                                       certificate, "CertificateUri",
-                                       certificateUri, "CertificateType",
-                                       certificateType))
+    BMCWEB_ROUTE(
+        app,
+        "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
+        .privileges(redfish::privileges::postCertificateService)
+        .methods(boost::beast::http::verb::post)(
+            std::bind_front(handleGenerateCSRAction, std::ref(app)));
+} // requestRoutesCertificateService
+
+inline void handleHTTPSCertificateCollectionGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    asyncResp->res.jsonValue["@odata.id"] =
+        "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#CertificateCollection.CertificateCollection";
+    asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
+    asyncResp->res.jsonValue["Description"] =
+        "A Collection of HTTPS certificate instances";
+
+    getCertificateList(asyncResp, certs::httpsObjectPath,
+                       "/Members"_json_pointer,
+                       "/Members@odata.count"_json_pointer);
+}
+
+inline void handleHTTPSCertificateCollectionPost(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
+
+    asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
+    asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
+
+    std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+
+    if (certFileBody.empty())
+    {
+        BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
+        messages::unrecognizedRequestBody(asyncResp->res);
+        return;
+    }
+
+    std::shared_ptr<CertificateFile> certFile =
+        std::make_shared<CertificateFile>(certFileBody);
+
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, certFile](const boost::system::error_code ec,
+                              const std::string& objectPath) {
+        if (ec)
         {
-            BMCWEB_LOG_ERROR << "Required parameters are missing";
+            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
             messages::internalError(asyncResp->res);
             return;
         }
 
-        if (!certificateType)
-        {
-            // should never happen, but it never hurts to be paranoid.
-            return;
-        }
-        if (certificateType != "PEM")
-        {
-            messages::actionParameterNotSupported(
-                asyncResp->res, "CertificateType", "ReplaceCertificate");
-            return;
-        }
+        sdbusplus::message::object_path path(objectPath);
+        std::string certId = path.filename();
+        const boost::urls::url certURL = crow::utility::urlFromPieces(
+            "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
+            "Certificates", certId);
+        getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
+                                 certId, certURL, "HTTPS Certificate");
+        BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
+                         << certFile->getCertFilePath();
+        },
+        certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
+        "Install", certFile->getCertFilePath());
+}
 
-        std::string certURI;
-        if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
-                                          "@odata.id", certURI))
-        {
-            messages::actionParameterMissing(
-                asyncResp->res, "ReplaceCertificate", "CertificateUri");
-            return;
-        }
-        BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI;
+inline void handleHTTPSCertificateGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
 
-        boost::urls::result<boost::urls::url_view> parsedUrl =
-            boost::urls::parse_relative_ref(certURI);
-        if (!parsedUrl)
-        {
-            messages::actionParameterValueFormatError(asyncResp->res, certURI,
-                                                      "CertificateUri",
-                                                      "ReplaceCertificate");
-            return;
-        }
-
-        std::string id;
-        sdbusplus::message::object_path objectPath;
-        std::string name;
-        std::string service;
-        if (crow::utility::readUrlSegments(
-                *parsedUrl, "redfish", "v1", "Managers", "bmc",
-                "NetworkProtocol", "HTTPS", "Certificates", std::ref(id)))
-        {
-            objectPath =
-                sdbusplus::message::object_path(certs::httpsObjectPath) / id;
-            name = "HTTPS certificate";
-            service = certs::httpsServiceName;
-        }
-        else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
-                                                "AccountService", "LDAP",
-                                                "Certificates", std::ref(id)))
-        {
-            objectPath =
-                sdbusplus::message::object_path(certs::ldapObjectPath) / id;
-            name = "LDAP certificate";
-            service = certs::ldapServiceName;
-        }
-        else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
-                                                "Managers", "bmc", "Truststore",
-                                                "Certificates", std::ref(id)))
-        {
-            objectPath =
-                sdbusplus::message::object_path(certs::authorityObjectPath) /
-                id;
-            name = "TrustStore certificate";
-            service = certs::authorityServiceName;
-        }
-        else
-        {
-            messages::actionParameterNotSupported(
-                asyncResp->res, "CertificateUri", "ReplaceCertificate");
-            return;
-        }
-
-        std::shared_ptr<CertificateFile> certFile =
-            std::make_shared<CertificateFile>(certificate);
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
-             name](const boost::system::error_code ec) {
-            if (ec)
-            {
-                BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
-                if (ec.value() ==
-                    boost::system::linux_error::bad_request_descriptor)
-                {
-                    messages::resourceNotFound(asyncResp->res, "Certificate",
-                                               id);
-                    return;
-                }
-                messages::internalError(asyncResp->res);
-                return;
-            }
-            getCertificateProperties(asyncResp, objectPath, service, id, url,
-                                     name);
-            BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
-                             << certFile->getCertFilePath();
-            },
-            service, objectPath, certs::certReplaceIntf, "Replace",
-            certFile->getCertFilePath());
-        });
-} // requestRoutesCertificateActionsReplaceCertificate
-
-/**
- * Certificate resource describes a certificate used to prove the identity
- * of a component, account or service.
- */
+    BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
+    const boost::urls::url certURL = crow::utility::urlFromPieces(
+        "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
+        "Certificates", id);
+    std::string objPath =
+        sdbusplus::message::object_path(certs::httpsObjectPath) / id;
+    getCertificateProperties(asyncResp, objPath, certs::httpsServiceName, id,
+                             certURL, "HTTPS Certificate");
+}
 
 inline void requestRoutesHTTPSCertificate(App& app)
 {
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
+        .privileges(redfish::privileges::getCertificateCollection)
+        .methods(boost::beast::http::verb::get)(std::bind_front(
+            handleHTTPSCertificateCollectionGet, std::ref(app)));
+
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
+        .privileges(redfish::privileges::postCertificateCollection)
+        .methods(boost::beast::http::verb::post)(std::bind_front(
+            handleHTTPSCertificateCollectionPost, std::ref(app)));
+
     BMCWEB_ROUTE(
         app,
         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
         .privileges(redfish::privileges::getCertificate)
         .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& id) -> void {
-                if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-                {
-                    return;
-                }
-
-                BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
-                const boost::urls::url certURL = crow::utility::urlFromPieces(
-                    "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
-                    "HTTPS", "Certificates", id);
-                std::string objPath =
-                    sdbusplus::message::object_path(certs::httpsObjectPath) /
-                    id;
-                getCertificateProperties(asyncResp, objPath,
-                                         certs::httpsServiceName, id, certURL,
-                                         "HTTPS Certificate");
-            });
+            std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
 }
 
-/**
- * Collection of HTTPS certificates
- */
-inline void requestRoutesHTTPSCertificateCollection(App& app)
+inline void handleLDAPCertificateCollectionGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
 {
-    BMCWEB_ROUTE(app,
-                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
-        .privileges(redfish::privileges::getCertificateCollection)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
 
-        asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
-        asyncResp->res.jsonValue["@odata.type"] =
-            "#CertificateCollection.CertificateCollection";
-        asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
-        asyncResp->res.jsonValue["Description"] =
-            "A Collection of HTTPS certificate instances";
+    asyncResp->res.jsonValue["@odata.id"] =
+        "/redfish/v1/AccountService/LDAP/Certificates";
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#CertificateCollection.CertificateCollection";
+    asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
+    asyncResp->res.jsonValue["Description"] =
+        "A Collection of LDAP certificate instances";
 
-        getCertificateList(asyncResp, certs::httpsObjectPath,
-                           "/Members"_json_pointer,
-                           "/Members@odata.count"_json_pointer);
-        });
-
-    BMCWEB_ROUTE(app,
-                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
-        .privileges(redfish::privileges::postCertificateCollection)
-        .methods(boost::beast::http::verb::post)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
-
-        asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
-        asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
-
-        std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
-
-        if (certFileBody.empty())
-        {
-            BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
-            messages::unrecognizedRequestBody(asyncResp->res);
-            return;
-        }
-
-        std::shared_ptr<CertificateFile> certFile =
-            std::make_shared<CertificateFile>(certFileBody);
-
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, certFile](const boost::system::error_code ec,
-                                  const std::string& objectPath) {
-            if (ec)
-            {
-                BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
-                messages::internalError(asyncResp->res);
-                return;
-            }
-
-            sdbusplus::message::object_path path(objectPath);
-            std::string certId = path.filename();
-            const boost::urls::url certURL = crow::utility::urlFromPieces(
-                "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
-                "Certificates", certId);
-            getCertificateProperties(asyncResp, objectPath,
-                                     certs::httpsServiceName, certId, certURL,
-                                     "HTTPS Certificate");
-            BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
-                             << certFile->getCertFilePath();
-            },
-            certs::httpsServiceName, certs::httpsObjectPath,
-            certs::certInstallIntf, "Install", certFile->getCertFilePath());
-        });
-} // requestRoutesHTTPSCertificateCollection
-
-/**
- * The certificate location schema defines a resource that an administrator
- * can use in order to locate all certificates installed on a given service.
- */
-inline void requestRoutesCertificateLocations(App& app)
-{
-    BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
-        .privileges(redfish::privileges::getCertificateLocations)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/CertificateService/CertificateLocations";
-        asyncResp->res.jsonValue["@odata.type"] =
-            "#CertificateLocations.v1_0_0.CertificateLocations";
-        asyncResp->res.jsonValue["Name"] = "Certificate Locations";
-        asyncResp->res.jsonValue["Id"] = "CertificateLocations";
-        asyncResp->res.jsonValue["Description"] =
-            "Defines a resource that an administrator can use in order to "
-            "locate all certificates installed on a given service";
-
-        getCertificateList(asyncResp, certs::baseObjectPath,
-                           "/Links/Certificates"_json_pointer,
-                           "/Links/Certificates@odata.count"_json_pointer);
-        });
+    getCertificateList(asyncResp, certs::ldapObjectPath,
+                       "/Members"_json_pointer,
+                       "/Members@odata.count"_json_pointer);
 }
-// requestRoutesCertificateLocations
 
-/**
- * Collection of LDAP certificates
- */
-inline void requestRoutesLDAPCertificateCollection(App& app)
+inline void handleLDAPCertificateCollectionPost(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
 {
-    BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
-        .privileges(redfish::privileges::getCertificateCollection)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+
+    if (certFileBody.empty())
+    {
+        BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
+        messages::unrecognizedRequestBody(asyncResp->res);
+        return;
+    }
+
+    std::shared_ptr<CertificateFile> certFile =
+        std::make_shared<CertificateFile>(certFileBody);
+
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, certFile](const boost::system::error_code ec,
+                              const std::string& objectPath) {
+        if (ec)
         {
+            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+            messages::internalError(asyncResp->res);
             return;
         }
 
-        asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/AccountService/LDAP/Certificates";
-        asyncResp->res.jsonValue["@odata.type"] =
-            "#CertificateCollection.CertificateCollection";
-        asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
-        asyncResp->res.jsonValue["Description"] =
-            "A Collection of LDAP certificate instances";
+        sdbusplus::message::object_path path(objectPath);
+        std::string certId = path.filename();
+        const boost::urls::url certURL = crow::utility::urlFromPieces(
+            "redfish", "v1", "AccountService", "LDAP", "Certificates", certId);
+        getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
+                                 certId, certURL, "LDAP Certificate");
+        BMCWEB_LOG_DEBUG << "LDAP certificate install file="
+                         << certFile->getCertFilePath();
+        },
+        certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
+        "Install", certFile->getCertFilePath());
+}
 
-        getCertificateList(asyncResp, certs::ldapObjectPath,
-                           "/Members"_json_pointer,
-                           "/Members@odata.count"_json_pointer);
-        });
+inline void handleLDAPCertificateGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
 
-    BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
-        .privileges(redfish::privileges::postCertificateCollection)
-        .methods(boost::beast::http::verb::post)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+    BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
+    const boost::urls::url certURL = crow::utility::urlFromPieces(
+        "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
+    std::string objPath =
+        sdbusplus::message::object_path(certs::ldapObjectPath) / id;
+    getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
+                             certURL, "LDAP Certificate");
+}
 
-        if (certFileBody.empty())
-        {
-            BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
-            messages::unrecognizedRequestBody(asyncResp->res);
-            return;
-        }
-
-        std::shared_ptr<CertificateFile> certFile =
-            std::make_shared<CertificateFile>(certFileBody);
-
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, certFile](const boost::system::error_code ec,
-                                  const std::string& objectPath) {
-            if (ec)
-            {
-                BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
-                messages::internalError(asyncResp->res);
-                return;
-            }
-
-            sdbusplus::message::object_path path(objectPath);
-            std::string certId = path.filename();
-            const boost::urls::url certURL =
-                crow::utility::urlFromPieces("redfish", "v1", "AccountService",
-                                             "LDAP", "Certificates", certId);
-            getCertificateProperties(asyncResp, objectPath,
-                                     certs::ldapServiceName, certId, certURL,
-                                     "LDAP Certificate");
-            BMCWEB_LOG_DEBUG << "LDAP certificate install file="
-                             << certFile->getCertFilePath();
-            },
-            certs::ldapServiceName, certs::ldapObjectPath,
-            certs::certInstallIntf, "Install", certFile->getCertFilePath());
-        });
-} // requestRoutesLDAPCertificateCollection
-
-/**
- * Certificate resource describes a certificate used to prove the identity
- * of a component, account or service.
- */
 inline void requestRoutesLDAPCertificate(App& app)
 {
+    BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
+        .privileges(redfish::privileges::getCertificateCollection)
+        .methods(boost::beast::http::verb::get)(
+            std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app)));
+
+    BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
+        .privileges(redfish::privileges::postCertificateCollection)
+        .methods(boost::beast::http::verb::post)(std::bind_front(
+            handleLDAPCertificateCollectionPost, std::ref(app)));
+
     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
         .privileges(redfish::privileges::getCertificate)
         .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& id) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+            std::bind_front(handleLDAPCertificateGet, std::ref(app)));
+} // requestRoutesLDAPCertificate
+
+inline void handleTrustStoreCertificateCollectionGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    asyncResp->res.jsonValue["@odata.id"] =
+        "/redfish/v1/Managers/bmc/Truststore/Certificates/";
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#CertificateCollection.CertificateCollection";
+    asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
+    asyncResp->res.jsonValue["Description"] =
+        "A Collection of TrustStore certificate instances";
+
+    getCertificateList(asyncResp, certs::authorityObjectPath,
+                       "/Members"_json_pointer,
+                       "/Members@odata.count"_json_pointer);
+}
+
+inline void handleTrustStoreCertificateCollectionPost(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+
+    if (certFileBody.empty())
+    {
+        BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
+        messages::unrecognizedRequestBody(asyncResp->res);
+        return;
+    }
+
+    std::shared_ptr<CertificateFile> certFile =
+        std::make_shared<CertificateFile>(certFileBody);
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, certFile](const boost::system::error_code ec,
+                              const std::string& objectPath) {
+        if (ec)
         {
+            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+            messages::internalError(asyncResp->res);
             return;
         }
 
-        BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
-        const boost::urls::url certURL = crow::utility::urlFromPieces(
-            "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
-        std::string objPath =
-            sdbusplus::message::object_path(certs::ldapObjectPath) / id;
-        getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
-                                 certURL, "LDAP Certificate");
-        });
-} // requestRoutesLDAPCertificate
-/**
- * Collection of TrustStoreCertificate certificates
- */
-inline void requestRoutesTrustStoreCertificateCollection(App& app)
+        sdbusplus::message::object_path path(objectPath);
+        std::string certId = path.filename();
+        const boost::urls::url certURL =
+            crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
+                                         "Truststore", "Certificates", certId);
+        getCertificateProperties(asyncResp, objectPath,
+                                 certs::authorityServiceName, certId, certURL,
+                                 "TrustStore Certificate");
+        BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
+                         << certFile->getCertFilePath();
+        },
+        certs::authorityServiceName, certs::authorityObjectPath,
+        certs::certInstallIntf, "Install", certFile->getCertFilePath());
+}
+
+inline void handleTrustStoreCertificateGet(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
+    const boost::urls::url certURL = crow::utility::urlFromPieces(
+        "redfish", "v1", "Managers", "bmc", "Truststore", "Certificates", id);
+    std::string objPath =
+        sdbusplus::message::object_path(certs::authorityObjectPath) / id;
+    getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
+                             id, certURL, "TrustStore Certificate");
+}
+
+inline void handleTrustStoreCertificateDelete(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id;
+    std::string objPath =
+        sdbusplus::message::object_path(certs::authorityObjectPath) / id;
+
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, id](const boost::system::error_code ec) {
+        if (ec)
+        {
+            messages::resourceNotFound(asyncResp->res, "Certificate", id);
+            return;
+        }
+        BMCWEB_LOG_INFO << "Certificate deleted";
+        asyncResp->res.result(boost::beast::http::status::no_content);
+        },
+        certs::authorityServiceName, objPath, certs::objDeleteIntf, "Delete");
+}
+
+inline void requestRoutesTrustStoreCertificate(App& app)
 {
     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
         .privileges(redfish::privileges::getCertificate)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-
-        asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/Managers/bmc/Truststore/Certificates/";
-        asyncResp->res.jsonValue["@odata.type"] =
-            "#CertificateCollection.CertificateCollection";
-        asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
-        asyncResp->res.jsonValue["Description"] =
-            "A Collection of TrustStore certificate instances";
-
-        getCertificateList(asyncResp, certs::authorityObjectPath,
-                           "/Members"_json_pointer,
-                           "/Members@odata.count"_json_pointer);
-        });
+        .methods(boost::beast::http::verb::get)(std::bind_front(
+            handleTrustStoreCertificateCollectionGet, std::ref(app)));
 
     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
         .privileges(redfish::privileges::postCertificateCollection)
-        .methods(boost::beast::http::verb::post)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+        .methods(boost::beast::http::verb::post)(std::bind_front(
+            handleTrustStoreCertificateCollectionPost, std::ref(app)));
 
-        if (certFileBody.empty())
-        {
-            BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
-            messages::unrecognizedRequestBody(asyncResp->res);
-            return;
-        }
-
-        std::shared_ptr<CertificateFile> certFile =
-            std::make_shared<CertificateFile>(certFileBody);
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, certFile](const boost::system::error_code ec,
-                                  const std::string& objectPath) {
-            if (ec)
-            {
-                BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
-                messages::internalError(asyncResp->res);
-                return;
-            }
-
-            sdbusplus::message::object_path path(objectPath);
-            std::string certId = path.filename();
-            const boost::urls::url certURL = crow::utility::urlFromPieces(
-                "redfish", "v1", "Managers", "bmc", "Truststore",
-                "Certificates", certId);
-            getCertificateProperties(asyncResp, objectPath,
-                                     certs::authorityServiceName, certId,
-                                     certURL, "TrustStore Certificate");
-            BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
-                             << certFile->getCertFilePath();
-            },
-            certs::authorityServiceName, certs::authorityObjectPath,
-            certs::certInstallIntf, "Install", certFile->getCertFilePath());
-        });
-} // requestRoutesTrustStoreCertificateCollection
-
-/**
- * Certificate resource describes a certificate used to prove the identity
- * of a component, account or service.
- */
-inline void requestRoutesTrustStoreCertificate(App& app)
-{
     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
         .privileges(redfish::privileges::getCertificate)
         .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& id) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-
-        BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
-        const boost::urls::url certURL =
-            crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
-                                         "Truststore", "Certificates", id);
-        std::string objPath =
-            sdbusplus::message::object_path(certs::authorityObjectPath) / id;
-        getCertificateProperties(asyncResp, objPath,
-                                 certs::authorityServiceName, id, certURL,
-                                 "TrustStore Certificate");
-        });
+            std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));
 
     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
         .privileges(redfish::privileges::deleteCertificate)
         .methods(boost::beast::http::verb::delete_)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& id) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-
-        BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id;
-        std::string objPath =
-            sdbusplus::message::object_path(certs::authorityObjectPath) / id;
-
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, id](const boost::system::error_code ec) {
-            if (ec)
-            {
-                messages::resourceNotFound(asyncResp->res, "Certificate", id);
-                return;
-            }
-            BMCWEB_LOG_INFO << "Certificate deleted";
-            asyncResp->res.result(boost::beast::http::status::no_content);
-            },
-            certs::authorityServiceName, objPath, certs::objDeleteIntf,
-            "Delete");
-        });
+            std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));
 } // requestRoutesTrustStoreCertificate
 } // namespace redfish