| /* |
| // Copyright (c) 2023 Google |
| / |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| */ |
| #pragma once |
| |
| #include "app.hpp" |
| #include "component_integrity.hpp" |
| #include "dbus_utility.hpp" |
| #include "managed_store.hpp" |
| #include "managed_store_types.hpp" |
| #include "processor.hpp" |
| #include "query.hpp" |
| #include "registries/privilege_registry.hpp" |
| #include "utils/chassis_utils.hpp" |
| #include "utils/system_utils.hpp" |
| #include "utils/collection.hpp" |
| #include "utils/dbus_utils.hpp" |
| #include "utils/json_utils.hpp" |
| #include "utils/system_utils.hpp" |
| |
| #include <boost/container/flat_map.hpp> |
| #include <boost/system/error_code.hpp> |
| #include <boost/url/format.hpp> |
| #include <sdbusplus/asio/property.hpp> |
| #include <sdbusplus/message/native_types.hpp> |
| #include <sdbusplus/unpack_properties.hpp> |
| #include <sdbusplus/utility/dedup_variant.hpp> |
| |
| #include <array> |
| #include <limits> |
| #include <regex> |
| #include <string_view> |
| #include <tuple> |
| #include <variant> |
| #include <vector> |
| |
| #ifdef UNIT_TEST_BUILD |
| #include "test/g3/mock_managed_store.hpp" // NOLINT |
| #endif |
| |
| namespace redfish |
| { |
| // Interfaces which imply a D-Bus object represents a TrustedComponent |
| constexpr std::array<std::string_view, 1> trustedComponentInterfaces = { |
| "xyz.openbmc_project.Inventory.Item.TrustedComponent"}; |
| constexpr char const* discreteAttachType = |
| "xyz.openbmc_project.Inventory.Item.TrustedComponent.ComponentAttachType.Discrete"; |
| constexpr char const* integratedAttachType = |
| "xyz.openbmc_project.Inventory.Item.TrustedComponent.ComponentAttachType.Integrated"; |
| constexpr char const* decoratorAssetIntf = |
| "xyz.openbmc_project.Inventory.Decorator.Asset"; |
| constexpr char const* uuidIntf = |
| "xyz.openbmc_project.Common.UUID"; |
| constexpr char const* trustedComponentIntf = |
| "xyz.openbmc_project.Inventory.Item.TrustedComponent"; |
| |
| /** |
| * Map a given vector of D-Bus object path to an array of Redfish |
| * URI. |
| * |
| * @param[in] property1 Redfish property name. |
| * @param[in] property2 Optional second Redfish property name. |
| * @param[in] nodeList vector of path string. |
| * |
| * @return entities Array of Redfish URI in json. |
| */ |
| inline std::optional<nlohmann::json> |
| mapObjectPathVector(const std::string& property1, |
| const std::string& property2, |
| const std::vector<std::string>& pathList) |
| { |
| nlohmann::json entities = nlohmann::json::array(); |
| |
| for (const std::string& node : pathList) |
| { |
| sdbusplus::message::object_path path(node); |
| std::string entityId = path.filename(); |
| if (entityId.empty()) |
| { |
| BMCWEB_LOG_ERROR << "Invalid object path:" << property1 << " " |
| << property2 << ":" << path.str; |
| return std::nullopt; |
| } |
| |
| nlohmann::json::object_t entity; |
| if (property2.empty()) |
| { |
| entity["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", property1, entityId); |
| } else |
| { |
| entity["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", property1, property2, entityId); |
| } |
| entities.push_back(std::move(entity)); |
| } |
| |
| return {std::move(entities)}; |
| } |
| |
| /** |
| * Find the D-Bus object representing the requested TrustedComponent, and call |
| * the handler with the results. If matching object is not found, add 404 error |
| * to response and don't call the handler. |
| * |
| * @param[in,out] resp Async HTTP response. |
| * @param[in] chassisId Redfish Chassis Id. |
| * @param[in] componentId Redfish TrustedComponent Id. |
| * @param[in] handler Callback to continue processing request upon |
| * successfully finding object. |
| */ |
| template <typename Handler> |
| inline void |
| getTrustedComponentObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, |
| const std::string& chassisId, |
| const std::string& componentId, |
| Handler&& handler) |
| { |
| BMCWEB_LOG_DEBUG << "Get available chassis trusted_component resources."; |
| |
| // GetSubTree on all interfaces which provide info about TrustedComponent |
| constexpr std::array<std::string_view, 1> interfaces = { |
| trustedComponentIntf}; |
| std::string trustedComponentsPath = |
| sdbusplus::message::object_path("/xyz/openbmc_project/Chassis") / |
| chassisId / "TrustedComponents" ; |
| managedStore::ManagedObjectStoreContext context(resp); |
| managedStore::GetManagedObjectStore()->getSubTree( |
| trustedComponentsPath, 0, interfaces, context, |
| [resp, chassisId, componentId, handler]( |
| const boost::system::error_code& ec, |
| const dbus::utility::MapperGetSubTreeResponse& subtree) { |
| if (ec) |
| { |
| BMCWEB_LOG_ERROR << "DBUS response error: " << ec; |
| messages::internalError(resp->res); |
| return; |
| } |
| |
| for (const auto& [objectPath, serviceMap] : subtree) |
| { |
| // Ignore any objects which don't end with our desired component |
| // name |
| if (!objectPath.ends_with(componentId)) |
| { |
| continue; |
| } |
| |
| bool found = false; |
| for (const auto& [serviceName, interfaceList] : serviceMap) |
| { |
| if (std::find_first_of(interfaceList.begin(), |
| interfaceList.end(), |
| trustedComponentInterfaces.begin(), |
| trustedComponentInterfaces.end()) != |
| interfaceList.end()) |
| { |
| found = true; |
| break; |
| } |
| } |
| |
| if (!found) |
| { |
| continue; |
| } |
| |
| // Found something, populate Name and Id before get Interface info |
| resp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", "Chassis", chassisId, "TrustedComponents", |
| componentId); |
| resp->res.jsonValue["Name"] = componentId; |
| resp->res.jsonValue["Id"] = componentId; |
| |
| handler(objectPath, serviceMap); |
| return; |
| } |
| messages::resourceNotFound(resp->res, "TrustedComponent", componentId); |
| }); |
| } |
| |
| inline void getTrustedComponentIntegratedIntoInfo( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& trustedComponentObjPath, |
| const boost::system::error_code& ec, |
| const dbus::utility::MapperEndPoints& integratedIntoObjPaths) |
| { |
| if (ec) |
| { |
| if (ec.value() != EBADR) |
| { |
| BMCWEB_LOG_ERROR << "DBUS response error " << ec; |
| messages::internalError(asyncResp->res); |
| } |
| return; |
| } |
| |
| if (integratedIntoObjPaths.empty()) |
| { |
| return; |
| } |
| |
| managedStore::ManagedObjectStoreContext requestContext(asyncResp); |
| for (const auto& objpath: integratedIntoObjPaths) |
| { |
| sdbusplus::message::object_path integratedIntoObjPath(objpath); |
| const std::string objName = integratedIntoObjPath.filename(); |
| if (objName.empty()) |
| { |
| BMCWEB_LOG_WARNING << "Malformed integratedInto object path " |
| << integratedIntoObjPath.str << " for " |
| << trustedComponentObjPath; |
| continue; |
| } |
| managedStore::GetManagedObjectStore()->getDbusObject( |
| objpath, {}, requestContext, |
| [asyncResp, integratedIntoObjPath, trustedComponentObjPath, |
| requestContext, objName]( |
| const boost::system::error_code& ec2, |
| const dbus::utility::MapperGetObject& object) { |
| if (ec2) |
| { |
| BMCWEB_LOG_ERROR << "DBUS response error"; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| nlohmann::json::object_t integratedPath; |
| |
| // Link can be Chassis or Board, Processor, and NetworkAdapters |
| // handle Chassis or Board case |
| if (redfish::dbus_utils::findInterfacesInServiceMap( |
| object, redfish::chassis_utils::chassisInterfaces)) |
| { |
| integratedPath["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", "Chassis", objName); |
| asyncResp->res.jsonValue["Links"]["IntegratedInto"] = |
| std::move(integratedPath); |
| return; |
| } |
| |
| // handle NetworkAdaptors: parent resource can only be Chassis. |
| if (redfish::dbus_utils::findInterfacesInServiceMap( |
| object, networkAdapterInterfaces)) |
| { |
| const std::string parentObj = |
| integratedIntoObjPath.parent_path().filename(); |
| if (parentObj.empty()) |
| { |
| BMCWEB_LOG_WARNING << "Malformed integratedInto object path " |
| << integratedIntoObjPath.str << " for " |
| << trustedComponentObjPath; |
| return; |
| } |
| |
| integratedPath["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", "Chassis", parentObj, "NetworkAdapters", objName); |
| asyncResp->res.jsonValue["Links"]["IntegratedInto"] = |
| std::move(integratedPath); |
| return; |
| } |
| |
| // handle Processor: parent resource can be Systems or Chassis. |
| if (redfish::dbus_utils::findInterfacesInServiceMap( |
| object, processorsInterfaces)) |
| { |
| std::string parentPath = |
| integratedIntoObjPath.parent_path().str; |
| std::string parentObj = |
| integratedIntoObjPath.parent_path().filename(); |
| // e.g., /xyz/openbmc_project/inventory/system/board/BoardName/system1/chassis/motherboard/cpu0 |
| // filter out chassis|motherboard in object path. |
| while (parentObj == "motherboard" || parentObj == "chassis") { |
| sdbusplus::message::object_path tempObjPath(parentPath); |
| parentPath = tempObjPath.parent_path().str; |
| parentObj = tempObjPath.parent_path().filename(); |
| } |
| if (parentObj.empty()) |
| { |
| BMCWEB_LOG_WARNING << "Malformed integratedInto object path " |
| << integratedIntoObjPath.str << " for " |
| << trustedComponentObjPath; |
| return; |
| } |
| managedStore::GetManagedObjectStore()->getDbusObject( |
| parentPath, {}, requestContext, |
| [asyncResp, objName, |
| parentObj](const boost::system::error_code& ec2, |
| const dbus::utility::MapperGetObject& object) { |
| if (ec2) |
| { |
| BMCWEB_LOG_ERROR << "DBUS response error"; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| nlohmann::json::object_t integratedProcessorPath; |
| std::string parentResourceType; |
| if (redfish::dbus_utils::findInterfacesInServiceMap( |
| object, redfish::chassis_utils::chassisInterfaces)) |
| { |
| parentResourceType = "Chassis"; |
| } else if (redfish::dbus_utils::findInterfacesInServiceMap( |
| object, redfish::system_utils::systemInterfaces)) |
| { |
| parentResourceType = "Systems"; |
| } else |
| { |
| BMCWEB_LOG_ERROR << "Parent resource type not " |
| "supported for Processor resource"; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| integratedProcessorPath["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", parentResourceType, parentObj, |
| "Processors", objName); |
| asyncResp->res.jsonValue["Links"]["IntegratedInto"] = |
| std::move(integratedProcessorPath); |
| return; |
| }); |
| |
| return; |
| } // end of Processor interfaces handling |
| |
| // Unsupported resource type |
| BMCWEB_LOG_ERROR << "Unsupported IntegratedInto resource for " |
| << integratedIntoObjPath.str; |
| messages::internalError(asyncResp->res); |
| return; |
| }); |
| } |
| } |
| |
| /** |
| * @brief Fill out TrustedComponent interface related info by |
| * requesting data from the given D-Bus object. |
| * |
| * @param[in,out] aResp Async HTTP response. |
| * @param[in] service D-Bus service to query. |
| * @param[in] objPath D-Bus object to query. |
| */ |
| inline void |
| getTrustedComponentInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, |
| const std::string& service, |
| const std::string& objPath) |
| { |
| BMCWEB_LOG_DEBUG << "Get TrustedComponent Interface Data"; |
| managedStore::ManagedObjectStoreContext context(aResp); |
| managedStore::GetManagedObjectStore()->getAllProperties( |
| service, objPath, |
| trustedComponentIntf, |
| context, |
| [objPath, aResp{aResp}, context]( |
| const boost::system::error_code& ec, |
| const std::vector<std::pair< |
| std::string, dbus::utility::DbusVariantType>>& properties) { |
| if (ec) |
| { |
| BMCWEB_LOG_ERROR << "DBUS response error"; |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| const std::string* type = nullptr; |
| const std::string* firmwareVersion = nullptr; |
| |
| const bool success = sdbusplus::unpackPropertiesNoThrow( |
| dbus_utils::UnpackErrorPrinter(), properties, "FirmwareVersion", |
| firmwareVersion, "TrustedComponentType", type); |
| |
| if (!success) |
| { |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| if ((firmwareVersion != nullptr) && !firmwareVersion->empty()) |
| { |
| aResp->res.jsonValue["FirmwareVersion"] = *firmwareVersion; |
| } |
| |
| // For Root-of-Trust, it is safe to hardcode it as Embedded. |
| aResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] = |
| "Embedded"; |
| |
| // Get active software image info from associations. |
| std::string activeSoftwarePath = objPath + "/actively_running"; |
| dbus_utils::getAssociationEndPoints( |
| activeSoftwarePath, context, |
| [aResp]( |
| const boost::system::error_code& e, |
| const dbus::utility::MapperEndPoints& nodeActiveSoftwareList) { |
| if (e) |
| { |
| if (e.value() != EBADR) |
| { |
| messages::internalError(aResp->res); |
| return; |
| } |
| // No resource found. |
| return; |
| } |
| |
| // One TrustedComponent object should be associated with one |
| // activeSoftwareImage object |
| if (nodeActiveSoftwareList.size() != 1) |
| { |
| BMCWEB_LOG_ERROR |
| << "Unexpected ActiveSoftwareImage #objs (expecting 1): " |
| << nodeActiveSoftwareList.size(); |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| const std::string& softwareImageURI = |
| nodeActiveSoftwareList.at(0); |
| sdbusplus::message::object_path activeSoftwareImage( |
| softwareImageURI); |
| std::string softwareId = activeSoftwareImage.filename(); |
| |
| nlohmann::json::object_t imagePath; |
| |
| if (softwareId.empty()) |
| { |
| BMCWEB_LOG_ERROR |
| << "TrustedComponent contains invalid activeSoftwareImage:" |
| << activeSoftwareImage.str; |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| imagePath["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", "UpdateService", "FirmwareInventory", |
| softwareId); |
| aResp->res.jsonValue["Links"]["ActiveSoftwareImage"] = |
| std::move(imagePath); |
| }); |
| |
| // Get ComponentIntegrity info from associations. |
| std::string componentIntegrityPath = objPath + "/reported_by"; |
| dbus_utils::getAssociationEndPoints( |
| componentIntegrityPath, context, |
| [aResp](const boost::system::error_code& e, |
| const dbus::utility::MapperEndPoints& |
| nodeComponentIntegrityList) { |
| if (e) |
| { |
| if (e.value() != EBADR) |
| { |
| messages::internalError(aResp->res); |
| return; |
| } |
| // No resource found. |
| return; |
| } |
| |
| if (nodeComponentIntegrityList.empty()) |
| { |
| BMCWEB_LOG_DEBUG << "No ComponentIntegrity objects found!"; |
| return; |
| } |
| |
| std::optional<nlohmann::json> components = mapObjectPathVector( |
| "ComponentIntegrity", "", nodeComponentIntegrityList); |
| if (!components) |
| { |
| BMCWEB_LOG_ERROR << "ComponentIntegrity is invalid."; |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| aResp->res.jsonValue["Links"]["ComponentIntegrity"] = *components; |
| }); |
| |
| // Get protected components info from associations. |
| std::string protectedComponentPath = objPath + "/protecting"; |
| dbus_utils::getAssociationEndPoints( |
| protectedComponentPath, context, |
| std::bind_front(getProtectedComponentsInfo, aResp, |
| objPath)); |
| |
| // Get integratedInto info from associations. |
| std::string integratedInto = objPath + "/integrated_into"; |
| dbus_utils::getAssociationEndPoints( |
| integratedInto, context, |
| std::bind_front(getTrustedComponentIntegratedIntoInfo, aResp, |
| objPath)); |
| |
| // Get software images info from associations. |
| std::string softwareImagesPath = objPath + "/runs"; |
| dbus_utils::getAssociationEndPoints( |
| softwareImagesPath, context, |
| [aResp]( |
| const boost::system::error_code& e, |
| const dbus::utility::MapperEndPoints& nodeSoftwareImagesList) { |
| if (e) |
| { |
| if (e.value() != EBADR) |
| { |
| messages::internalError(aResp->res); |
| return; |
| } |
| // No resource found. |
| return; |
| } |
| |
| // One TrustedComponent object may be associated with one |
| // or more SoftwareImage objects |
| if (nodeSoftwareImagesList.empty()) |
| { |
| BMCWEB_LOG_DEBUG << "No software image objects found!"; |
| return; |
| } |
| |
| std::optional<nlohmann::json> images = |
| mapObjectPathVector("UpdateService", "FirmwareInventory", |
| nodeSoftwareImagesList); |
| if (!images) |
| { |
| BMCWEB_LOG_ERROR << "SoftwareImages is invalid."; |
| messages::internalError(aResp->res); |
| return; |
| } |
| aResp->res.jsonValue["Links"]["SoftwareImages"] = *images; |
| }); |
| |
| if ((type != nullptr) && !type->empty()) |
| { |
| if (*type == discreteAttachType) |
| { |
| aResp->res.jsonValue["TrustedComponentType"] = "Discrete"; |
| } else if (*type == integratedAttachType) |
| { |
| aResp->res.jsonValue["TrustedComponentType"] = "Integrated"; |
| } else |
| { |
| BMCWEB_LOG_ERROR << "Unrecognized ComponentAttachType!"; |
| messages::internalError(aResp->res); |
| return; |
| } |
| } else { |
| BMCWEB_LOG_ERROR << "No ComponentAttachType found!"; |
| messages::internalError(aResp->res); |
| return; |
| } |
| }); |
| } |
| |
| /** |
| * @brief Fill out Inventory.Decorator.Asset interface related info by |
| * requesting data from the given D-Bus object. |
| * |
| * @param[in,out] aResp Async HTTP response. |
| * @param[in] service D-Bus service to query. |
| * @param[in] objPath D-Bus object to query. |
| */ |
| inline void |
| getDecoratorAssetInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, |
| const std::string& service, |
| const std::string& objPath) |
| { |
| BMCWEB_LOG_DEBUG << "Get Decorator.Asset Interface Data"; |
| managedStore::ManagedObjectStoreContext context(aResp); |
| managedStore::GetManagedObjectStore()->getAllProperties( |
| service, objPath, |
| decoratorAssetIntf, |
| context, |
| [objPath, aResp{aResp}, context]( |
| const boost::system::error_code& ec, |
| const std::vector<std::pair< |
| std::string, dbus::utility::DbusVariantType>>& properties) { |
| if (ec) |
| { |
| BMCWEB_LOG_ERROR<< "DBUS response error for DecoratorAssetIntf!"; |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| const std::string* manufacturer = nullptr; |
| const std::string* serialNumber = nullptr; |
| const std::string* sku = nullptr; |
| const std::string* partNumber = nullptr; |
| |
| const bool success = sdbusplus::unpackPropertiesNoThrow( |
| dbus_utils::UnpackErrorPrinter(), properties, |
| "Manufacturer", manufacturer, "SerialNumber", |
| serialNumber, "PartNumber", partNumber, "SKU", sku); |
| |
| if (!success) |
| { |
| BMCWEB_LOG_ERROR<< "Unpacking Inventory.Decorator.Asset failed!"; |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| if ((manufacturer != nullptr) && !manufacturer->empty()) |
| { |
| aResp->res.jsonValue["Manufacturer"] = *manufacturer; |
| } |
| |
| if ((serialNumber != nullptr) && !serialNumber->empty()) |
| { |
| aResp->res.jsonValue["SerialNumber"] = *serialNumber; |
| } |
| |
| if ((sku != nullptr) && !sku->empty()) |
| { |
| aResp->res.jsonValue["SKU"] = *sku; |
| } |
| |
| if ((partNumber != nullptr) && !partNumber->empty()) |
| { |
| aResp->res.jsonValue["PartNumber"] = *partNumber; |
| } |
| }); |
| } |
| |
| /** |
| * @brief Fill out Common.UUID interface related info by |
| * requesting data from the given D-Bus object. |
| * |
| * @param[in,out] aResp Async HTTP response. |
| * @param[in] service D-Bus service to query. |
| * @param[in] objPath D-Bus object to query. |
| */ |
| inline void |
| getCommonUUIDInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, |
| const std::string& service, |
| const std::string& objPath) |
| { |
| BMCWEB_LOG_DEBUG << "Get Common.UUID Interface Data"; |
| managedStore::ManagedObjectStoreContext context(aResp); |
| managedStore::GetManagedObjectStore()->getAllProperties( |
| service, objPath, |
| uuidIntf, |
| context, |
| [objPath, aResp{aResp}, context]( |
| const boost::system::error_code& ec, |
| const std::vector<std::pair< |
| std::string, dbus::utility::DbusVariantType>>& properties) { |
| if (ec) |
| { |
| BMCWEB_LOG_DEBUG << "DBUS response error"; |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| const std::string* uuid = nullptr; |
| |
| const bool success = sdbusplus::unpackPropertiesNoThrow( |
| dbus_utils::UnpackErrorPrinter(), properties, |
| "UUID", uuid); |
| |
| if (!success) |
| { |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| if ((uuid != nullptr) && !uuid->empty()) |
| { |
| aResp->res.jsonValue["UUID"] = *uuid; |
| } |
| }); |
| } |
| |
| inline void |
| getTrustedComponentData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, |
| const std::string& objectPath, |
| const dbus::utility::MapperServiceMap& serviceMap) |
| { |
| for (const auto& [serviceName, interfaceList] : serviceMap) |
| { |
| for (const auto& interface : interfaceList) |
| { |
| if (interface == trustedComponentIntf) |
| { |
| getTrustedComponentInterfaceData(aResp, serviceName, |
| objectPath); |
| } else if (interface == decoratorAssetIntf) |
| { |
| getDecoratorAssetInterfaceData(aResp, serviceName, |
| objectPath); |
| } else if (interface == uuidIntf) |
| { |
| getCommonUUIDInterfaceData(aResp, serviceName, objectPath); |
| } |
| } |
| } |
| } |
| |
| inline void handleTrustedComponentGet( |
| crow::App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& chassisId, |
| const std::string& componentId) |
| { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) |
| { |
| return; |
| } |
| |
| asyncResp->res.addHeader( |
| boost::beast::http::field::link, |
| "</redfish/v1/JsonSchemas/TrustedComponent/TrustedComponent.json>; rel=describedby"); |
| asyncResp->res.jsonValue["@odata.type"] = |
| "#TrustedComponent.v1_0_0.TrustedComponent"; |
| |
| getTrustedComponentObject( |
| asyncResp, chassisId, componentId, |
| std::bind_front(getTrustedComponentData, asyncResp)); |
| } |
| |
| inline void handleTrustedComponentCollectionGet( |
| crow::App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& chassisId) |
| { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) |
| { |
| return; |
| } |
| |
| boost::urls::url url = crow::utility::urlFromPieces( |
| "redfish", "v1", "Chassis", chassisId, "TrustedComponents"); |
| |
| asyncResp->res.jsonValue["@odata.type"] = |
| "#TrustedComponentCollection.TrustedComponentCollection"; |
| asyncResp->res.jsonValue["@odata.id"] = url.buffer(); |
| asyncResp->res.jsonValue["Name"] = "Trusted Component Collection"; |
| asyncResp->res.jsonValue["Description"] = |
| "Collection of Trusted Components"; |
| |
| std::string trustedComponentsPath = |
| sdbusplus::message::object_path("/xyz/openbmc_project/Chassis") / |
| chassisId / "TrustedComponents"; |
| |
| collection_util::getCollectionMembers(asyncResp, url, |
| trustedComponentInterfaces, |
| trustedComponentsPath.c_str()); |
| } |
| |
| inline void requestRoutesTrustedComponent(App& app) |
| { |
| BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/TrustedComponents/<str>/") |
| .privileges(redfish::privileges::getTrustedComponent) |
| .methods(boost::beast::http::verb::get)( |
| std::bind_front(handleTrustedComponentGet, std::ref(app))); |
| } |
| |
| inline void requestRoutesTrustedComponentCollection(App& app) |
| { |
| BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/TrustedComponents/") |
| .privileges(redfish::privileges::getTrustedComponentCollection) |
| .methods(boost::beast::http::verb::get)(std::bind_front( |
| handleTrustedComponentCollectionGet, std::ref(app))); |
| } |
| |
| } // namespace redfish |