Allow configuring "bmc" and "system"

In the early days of bmcweb, we made two pretty critical assumptions;
First, is that a given platform would only have a single BMC instance
(represented as "bmc") and a single host instance (represented as
"system").
Second we assumed that, given that Redfish suggests against hardcoding
URIs in client implementation and leaves them freeform, clients would
code to the standard.

Our own webui-vue hardcodes Redfish URIs [1], and the documentation is
littered with examples of hardcoded curl examples of hardcoding these
URIs.  That bug was filed in 2020, and the issue has only gotten worse
over time.

This patchset is an attempt to give a target that we can start solving
these issues, without trying to boil the ocean and fix all clients in
parallel.

This commit adds the meson options
redfish-manager-uri-name
and
redfish-system-uri-name

These are used to control the "name" that bmcweb places in the fixed
locations in the ManagerCollection and ComputerSystemCollection schemas.

Note, managers is added, but is not currently testable.  It will be
iterated on over time.

Tested:
Changed the URL options to "edsbmc" and "edssystem" in meson options.

Redfish service validator passes.
URLs appear changed when walking the tree.

[1] https://github.com/openbmc/webui-vue/issues/43

Change-Id: I4b44685067051512bd065da8c2e3db68ae5ce23a
Signed-off-by: Ed Tanous <ed@tanous.net>
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index 6fba827..af35450 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -249,8 +249,8 @@
             if (objPath.parent_path() == certs::httpsObjectPath)
             {
                 certURL = boost::urls::format(
-                    "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}",
-                    certId);
+                    "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
+                    BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
             }
             else if (objPath.parent_path() == certs::ldapObjectPath)
             {
@@ -260,8 +260,8 @@
             else if (objPath.parent_path() == certs::authorityObjectPath)
             {
                 certURL = boost::urls::format(
-                    "/redfish/v1/Managers/bmc/Truststore/Certificates/{}",
-                    certId);
+                    "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
+                    BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
             }
             else
             {
@@ -672,8 +672,9 @@
 
     std::string objectPath;
     std::string service;
-    if (certURI.starts_with(
-            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
+    if (certURI.starts_with(std::format(
+            "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
+            BMCWEB_REDFISH_MANAGER_URI_NAME)))
     {
         objectPath = certs::httpsObjectPath;
         service = certs::httpsServiceName;
@@ -709,8 +710,9 @@
     }
 
     // validate KeyUsage supporting only 1 type based on URL
-    if (certURI.starts_with(
-            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
+    if (certURI.starts_with(std::format(
+            "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
+            BMCWEB_REDFISH_MANAGER_URI_NAME)))
     {
         if (optKeyUsage->empty())
         {
@@ -871,15 +873,23 @@
 
 inline void handleHTTPSCertificateCollectionGet(
     App& app, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& managerId)
 {
     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
     {
         return;
     }
 
-    asyncResp->res.jsonValue["@odata.id"] =
-        "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
+    if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+        return;
+    }
+
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates",
+        BMCWEB_REDFISH_MANAGER_URI_NAME);
     asyncResp->res.jsonValue["@odata.type"] =
         "#CertificateCollection.CertificateCollection";
     asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
@@ -893,12 +903,20 @@
 
 inline void handleHTTPSCertificateCollectionPost(
     App& app, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& managerId)
 {
     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
     {
         return;
     }
+
+    if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+        return;
+    }
+
     BMCWEB_LOG_DEBUG("HTTPSCertificateCollection::doPost");
 
     asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
@@ -929,8 +947,8 @@
         sdbusplus::message::object_path path(objectPath);
         std::string certId = path.filename();
         const boost::urls::url certURL = boost::urls::format(
-            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}",
-            certId);
+            "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
+            BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
         getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
                                  certId, certURL, "HTTPS Certificate");
         BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
@@ -942,39 +960,47 @@
 
 inline void handleHTTPSCertificateGet(
     App& app, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& managerId, const std::string& certId)
 {
     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
     {
         return;
     }
 
-    BMCWEB_LOG_DEBUG("HTTPS Certificate ID={}", id);
+    if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+        return;
+    }
+
+    BMCWEB_LOG_DEBUG("HTTPS Certificate ID={}", certId);
     const boost::urls::url certURL = boost::urls::format(
-        "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}", id);
+        "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
+        BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
     std::string objPath =
-        sdbusplus::message::object_path(certs::httpsObjectPath) / id;
-    getCertificateProperties(asyncResp, objPath, certs::httpsServiceName, id,
-                             certURL, "HTTPS Certificate");
+        sdbusplus::message::object_path(certs::httpsObjectPath) / certId;
+    getCertificateProperties(asyncResp, objPath, certs::httpsServiceName,
+                             certId, certURL, "HTTPS Certificate");
 }
 
 inline void requestRoutesHTTPSCertificate(App& app)
 {
-    BMCWEB_ROUTE(app,
-                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
+    BMCWEB_ROUTE(
+        app, "/redfish/v1/Managers/<str>/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/")
+    BMCWEB_ROUTE(
+        app, "/redfish/v1/Managers/<str>/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>/")
+        "/redfish/v1/Managers/<str>/NetworkProtocol/HTTPS/Certificates/<str>/")
         .privileges(redfish::privileges::getCertificate)
         .methods(boost::beast::http::verb::get)(
             std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
@@ -1104,15 +1130,23 @@
 
 inline void handleTrustStoreCertificateCollectionGet(
     App& app, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& managerId)
 {
     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
     {
         return;
     }
 
+    if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+        return;
+    }
+
     asyncResp->res.jsonValue["@odata.id"] =
-        "/redfish/v1/Managers/bmc/Truststore/Certificates/";
+        boost::urls::format("/redfish/v1/Managers/{}/Truststore/Certificates/",
+                            BMCWEB_REDFISH_MANAGER_URI_NAME);
     asyncResp->res.jsonValue["@odata.type"] =
         "#CertificateCollection.CertificateCollection";
     asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
@@ -1126,12 +1160,20 @@
 
 inline void handleTrustStoreCertificateCollectionPost(
     App& app, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& managerId)
 {
     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
     {
         return;
     }
+
+    if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+        return;
+    }
+
     std::string certHttpBody = getCertificateFromReqBody(asyncResp, req);
 
     if (certHttpBody.empty())
@@ -1156,7 +1198,8 @@
         sdbusplus::message::object_path path(objectPath);
         std::string certId = path.filename();
         const boost::urls::url certURL = boost::urls::format(
-            "/redfish/v1/Managers/bmc/Truststore/Certificates/{}", certId);
+            "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
+            BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
         getCertificateProperties(asyncResp, objectPath,
                                  certs::authorityServiceName, certId, certURL,
                                  "TrustStore Certificate");
@@ -1169,56 +1212,73 @@
 
 inline void handleTrustStoreCertificateGet(
     App& app, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& managerId, const std::string& certId)
 {
     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
     {
         return;
     }
 
-    BMCWEB_LOG_DEBUG("Truststore Certificate ID={}", id);
+    if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+        return;
+    }
+
+    BMCWEB_LOG_DEBUG("Truststore Certificate ID={}", certId);
     const boost::urls::url certURL = boost::urls::format(
-        "/redfish/v1/Managers/bmc/Truststore/Certificates/{}", id);
+        "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
+        BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
     std::string objPath =
-        sdbusplus::message::object_path(certs::authorityObjectPath) / id;
+        sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
     getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
-                             id, certURL, "TrustStore Certificate");
+                             certId, certURL, "TrustStore Certificate");
 }
 
 inline void handleTrustStoreCertificateDelete(
     App& app, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& managerId, const std::string& certId)
 {
     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
     {
         return;
     }
 
-    BMCWEB_LOG_DEBUG("Delete TrustStore Certificate ID={}", id);
+    if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+        return;
+    }
+
+    BMCWEB_LOG_DEBUG("Delete TrustStore Certificate ID={}", certId);
     std::string objPath =
-        sdbusplus::message::object_path(certs::authorityObjectPath) / id;
+        sdbusplus::message::object_path(certs::authorityObjectPath) / certId;
 
     deleteCertificate(asyncResp, certs::authorityServiceName, objPath);
 }
 
 inline void requestRoutesTrustStoreCertificate(App& app)
 {
-    BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
+    BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
         .privileges(redfish::privileges::getCertificate)
         .methods(boost::beast::http::verb::get)(std::bind_front(
             handleTrustStoreCertificateCollectionGet, std::ref(app)));
 
-    BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
+    BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Truststore/Certificates/")
         .privileges(redfish::privileges::postCertificateCollection)
         .methods(boost::beast::http::verb::post)(std::bind_front(
             handleTrustStoreCertificateCollectionPost, std::ref(app)));
 
-    BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
         .privileges(redfish::privileges::getCertificate)
         .methods(boost::beast::http::verb::get)(
             std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));
 
-    BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Managers/<str>/Truststore/Certificates/<str>/")
         .privileges(redfish::privileges::deleteCertificate)
         .methods(boost::beast::http::verb::delete_)(
             std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));