/*
// Copyright (c) 2024 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 "dbus_utility.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "parsing.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/chassis_utils.hpp"
#include "utils/collection.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
#include "utils/system_utils.hpp"
#include "http/parsing.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 <ctime>
#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 ComponentIntegrity
constexpr std::array<std::string_view, 3> componentIntegrityInterfaces = {
    "xyz.openbmc_project.Attestation.ComponentIntegrity",
    "xyz.openbmc_project.Attestation.MeasurementSet",
    "xyz.openbmc_project.Attestation.IdentityAuthentication"};
constexpr std::array<std::string_view, 1> networkAdapterInterfaces = {
    "xyz.openbmc_project.Inventory.Item.NetworkAdapter"};
constexpr std::array<std::string_view, 2> processorsInterfaces = {
    "xyz.openbmc_project.Inventory.Item.Cpu",
    "xyz.openbmc_project.Inventory.Item.Accelerator"};

constexpr char const* spdmSecurityTechnologyType =
    "xyz.openbmc_project.Attestation.ComponentIntegrity.SecurityTechnologyType.SPDM";
constexpr char const* tpmSecurityTechnologyType =
    "xyz.openbmc_project.Attestation.ComponentIntegrity.SecurityTechnologyType.TPM";
constexpr char const* oemSecurityTechnologyType =
    "xyz.openbmc_project.Attestation.ComponentIntegrity.SecurityTechnologyType.OEM";
constexpr char const* successVerificationStatus =
    "xyz.openbmc_project.Attestation.IdentityAuthentication.VerificationStatus.Success";
constexpr char const* attestationComponentIntegrityIntf =
    "xyz.openbmc_project.Attestation.ComponentIntegrity";
constexpr char const* attestationIntegrityAuthIntf =
    "xyz.openbmc_project.Attestation.IdentityAuthentication";
constexpr char const* attestationMeasurementSetIntf =
    "xyz.openbmc_project.Attestation.MeasurementSet";

inline std::string getTrustedComponent(const std::string& dbusPath)
{
    std::string chassis;
    std::string component;

    // Map D-Bus object path to the Redfish URI
    // Example targetComponentURI
    //     "/xyz/openbmc_project/Chassis/chassis01/TrustedComponent/tc01"
    // which should maps to
    //     "/redfish/v1/Chassis/chassis01/TrustedComponent/tc01"

    // These regexes derived on the rules here:
    // https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
    const static std::regex validPath(
        "/xyz/openbmc_project/Chassis/([A-Za-z0-9_]+)/TrustedComponents/([A-Za-z0-9_]+)");
    std::smatch matches;

    if (regex_match(dbusPath, matches, validPath))
    {
        chassis = matches[1];
        component = matches[2];
    }
    else
    {
        BMCWEB_LOG_ERROR << "Can't parse TrustedComponent object path:"
                         << dbusPath;
        return "";
    }

    boost::urls::url uri = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassis, "TrustedComponents", component);
    std::string trustedComponent(uri.c_str());

    return trustedComponent;
}

inline std::optional<nlohmann::json> getChassisCert(const std::string& dbusPath)
{
    nlohmann::json::object_t certObj;
    std::string chassis;
    std::string cert;

    // Map D-Bus object to Redfish URI
    // Example chassis cert object path:
    //     "/xyz/openbmc_project/certs/chassis/chassis01/cert01"
    // which should maps to:
    //     "/redfish/v1/Chassis/chassis01/Certificates/cert01"

    // These regexes derived on the rules here:
    // https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
    const static std::regex validPath("/xyz/openbmc_project/certs/chassis/([A-Za-z0-9_]+)/([A-Za-z0-9_]+)");
    std::smatch matches;

    if (regex_match(dbusPath, matches, validPath))
    {
        chassis = matches[1];
        cert = matches[2];
    }
    else
    {
        BMCWEB_LOG_ERROR << "Can't parse DBus certificate object path:"
                         << dbusPath;
        return std::nullopt;
    }

    certObj["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassis, "Certificates", cert);

    return {std::move(certObj)};
}

inline void getProtectedComponentsInfo(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& currentObjPath,
    const boost::system::error_code& ec,
    const dbus::utility::MapperEndPoints& protectedComponentObjPaths)
{
    if (ec)
    {
        if (ec.value() != EBADR)
        {
            BMCWEB_LOG_ERROR << "DBUS response error " << ec;
            messages::internalError(asyncResp->res);
        }
        return;
    }

    if (protectedComponentObjPaths.empty())
    {
        return;
    }

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    for (const auto& objpath: protectedComponentObjPaths)
    {
        sdbusplus::message::object_path protectedComponentObjPath(objpath);
        const std::string objName = protectedComponentObjPath.filename();
        if (objName.empty())
        {
            BMCWEB_LOG_WARNING << "Malformed protected component object path "
                               << protectedComponentObjPath.str << " for "
                               << currentObjPath;
            continue;
        }
        managedStore::GetManagedObjectStore()->getDbusObject(
            objpath, {}, requestContext,
            [asyncResp, protectedComponentObjPath, currentObjPath,
             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& jValue =
                asyncResp->res.jsonValue["Links"]["ComponentsProtected"];

            if (!jValue.is_array())
            {
                // Create the array if it was empty
                jValue = nlohmann::json::array();
            }

            // Link can be Chassis or Board, Processor, and NetworkAdapters
            // handle Chassis or Board case
            if (redfish::dbus_utils::findInterfacesInServiceMap(
                    object, redfish::chassis_utils::chassisInterfaces))
            {
                nlohmann::json link;
                link["@odata.id"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Chassis", objName);
                jValue.push_back(std::move(link));
                return;
            }

            // handle NetworkAdaptors: parent resource can only be Chassis.
            if (redfish::dbus_utils::findInterfacesInServiceMap(
                    object, networkAdapterInterfaces))
            {
                const std::string parentObj =
                    protectedComponentObjPath.parent_path().filename();
                if (parentObj.empty())
                {
                    BMCWEB_LOG_WARNING << "Malformed protectedComponent object path "
                                       << protectedComponentObjPath.str << " for "
                                       << currentObjPath;
                    return;
                }

                nlohmann::json link;
                link["@odata.id"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Chassis", parentObj, "NetworkAdapters", objName);
                jValue.push_back(std::move(link));
                return;
            }

            // handle Processor: parent resource can be Systems or Chassis.
            if (redfish::dbus_utils::findInterfacesInServiceMap(
                    object, processorsInterfaces))
            {
                std::string parentPath =
                    protectedComponentObjPath.parent_path().str;
                std::string parentObj =
                    protectedComponentObjPath.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 protectedComponentObjPath "
                                       << protectedComponentObjPath.str << " for "
                                       << currentObjPath;
                    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& jValue =
                        asyncResp->res.jsonValue["Links"]["ComponentsProtected"];
                    if (!jValue.is_array())
                    {
                        // Create the array if it was empty
                        jValue = nlohmann::json::array();
                    }

                    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;
                    }

                    nlohmann::json link;
                    link["@odata.id"] = crow::utility::urlFromPieces(
                        "redfish", "v1", parentResourceType, parentObj,
                        "Processors", objName);
                    jValue.push_back(std::move(link));
                    return;
                });

                return;
            } // end of Processor interfaces handling

            // Unsupported resource type
            BMCWEB_LOG_ERROR << "Unsupported ComponentsProtected resource for "
                             << protectedComponentObjPath.str;
            messages::internalError(asyncResp->res);
            return;
        });
    }
}


/**
 * @brief Fill out ComponentIntegrity 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 getComponentIntegrityData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                      const std::string& service,
                                      const std::string& objPath)
{
    BMCWEB_LOG_DEBUG << "Get ComponentIntegrity Data";
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        service, objPath,
        attestationComponentIntegrityIntf,
        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 bool* enabled = nullptr;
        const std::string* type = nullptr;
        const std::string* typeVersion = nullptr;
        const std::uint64_t* lastUpdated = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
            "Type", type, "TypeVersion", typeVersion, "LastUpdated",
            lastUpdated);

        if (!success)
        {
            messages::internalError(aResp->res);
            return;
        }

        if (enabled != nullptr)
        {
            if (*enabled)
            {
                aResp->res.jsonValue["ComponentIntegrityEnabled"] = true;
            } else
            {
                aResp->res.jsonValue["ComponentIntegrityEnabled"] = false;
            }
        } else {
            messages::internalError(aResp->res);
            return;
        }

        if ((type != nullptr) && !type->empty())
        {
            if (*type == spdmSecurityTechnologyType)
            {
                aResp->res.jsonValue["ComponentIntegrityType"] = "SPDM";
                aResp->res.jsonValue["Description"] =
                    "SPDM-capable RoT physically attached to a device.";
            } else if (*type == tpmSecurityTechnologyType)
            {
                aResp->res.jsonValue["ComponentIntegrityType"] = "TPM";
                aResp->res.jsonValue["Description"] =
                    "TPM physically attached to a device.";
            } else if (*type == oemSecurityTechnologyType)
            {
                aResp->res.jsonValue["ComponentIntegrityType"] = "OEM";
                aResp->res.jsonValue["Description"] =
                    "OEM-specific RoT physically attached to a device.";
            } else
            {
                messages::internalError(aResp->res);
                return;
            }
        }

        if ((typeVersion != nullptr) && !typeVersion->empty())
        {
            aResp->res.jsonValue["ComponentIntegrityTypeVersion"] =
                *typeVersion;
        }

        if ((lastUpdated != nullptr) && *lastUpdated != 0)
        {
            time_t ts = static_cast<time_t>(*lastUpdated);
            const struct tm* tminfo = localtime(&ts);

            /**
             * The date of component update in ISO 8601 format as
             * YYYYMMDDThhmmssZ. Where 'T' is a literal character to separate
             * date fields from time and 'Z' is a literal character to indicate
             * UTC.
             */
            char iso8601[40]; // NOLINT
            std::strftime(static_cast<char *>(iso8601), sizeof(iso8601), "%Y%m%dT%H%M%SZ", tminfo);
            aResp->res.jsonValue["LastUpdated"] = std::string(static_cast<char *>(iso8601));
        }

        // Get trusted components info from associations.
        std::string targetComponentPath = objPath + "/reporting";
        dbus_utils::getAssociationEndPoints(
            targetComponentPath, context,
            [aResp](const boost::system::error_code& e,
                    const dbus::utility::MapperEndPoints&
                        nodeTrustedComponentList) {
            if (e)
            {
                if (e.value() != EBADR)
                {
                    messages::internalError(aResp->res);
                    return;
                }
                // No resource found.
                return;
            }

            // One ComponentIntegrity object should be associated with one
            // TrustedComponent object
            if (nodeTrustedComponentList.size() == 1)
            {
                const std::string& componentURI =
                    nodeTrustedComponentList.at(0);

                std::string targetComponentURI = getTrustedComponent(componentURI);

                if (!targetComponentURI.empty())
                {
                    aResp->res.jsonValue["TargetComponentURI"] =
                        targetComponentURI;
                } else {
                    BMCWEB_LOG_ERROR
                        << "Can't parse TargetComponentURI : "
                        << componentURI;
                    messages::internalError(aResp->res);
                    return;
                }
            } else {
                BMCWEB_LOG_ERROR
                    << "Unexpected TargetComponent #objs (expecting 1): "
                    << nodeTrustedComponentList.size();
                messages::internalError(aResp->res);
                return;
            }
        });

        // Get protected components info from associations.
        std::string protectedComponentPath = objPath + "/authenticating";
        dbus_utils::getAssociationEndPoints(
            protectedComponentPath, context,
            std::bind_front(getProtectedComponentsInfo, aResp,
            objPath));
    });
}

/**
 * @brief Fill out {ComponentIntegrityId}#/SPDM/IdentityAuthentication
 * 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 getSPDMAuthenticationData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                      const std::string& service,
                                      const std::string& objPath)
{
    BMCWEB_LOG_DEBUG << "Get {ComponentIntegrityId}#/SPDM/IdentyAuthentication Data";
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        service, objPath, attestationIntegrityAuthIntf, 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* respStatus = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties,
            "ResponderVerificationStatus", respStatus);

        if (!success)
        {
            messages::internalError(aResp->res);
            return;
        }

        if (respStatus != nullptr && !respStatus->empty())
        {
            if (*respStatus == successVerificationStatus)
            {
                aResp->res.jsonValue["SPDM"]["IdentityAuthentication"]["ResponderAuthentication"]["VerificationStatus"] = "Success";
            } else
            {
                aResp->res.jsonValue["SPDM"]["IdentityAuthentication"]["ResponderAuthentication"]["VerificationStatus"] = "Failed";
            }
        }

        // Get associated certs objects.
        std::string reqCertPath = objPath + "/requester_identified_by";
        dbus_utils::getAssociationEndPoints(
            reqCertPath, context,
            [aResp](const boost::system::error_code& e,
                    const dbus::utility::MapperEndPoints& nodeReqCertList) {
            if (e)
            {
                if (e.value() != EBADR)
                {
                    messages::internalError(aResp->res);
                    return;
                }
                // No resource found.
                return;
            }

            nlohmann::json& json = aResp->res.jsonValue;

            // One ComponentIntegrity object should be associated with one
            // requester certificate object or none
            if (nodeReqCertList.empty())
            {
                return;
            }

            if (nodeReqCertList.size() > 1)
            {
                BMCWEB_LOG_ERROR << "More than one requester cert provided!";
                messages::internalError(aResp->res);
                return;
            }

            // There is one valid cert, handle it
            const std::string& certPath = nodeReqCertList.at(0);

            std::optional<nlohmann::json> reqCertObj =
                getChassisCert(certPath);

            if (reqCertObj != std::nullopt)
            {
                json["SPDM"]["IdentityAuthentication"]["RequesterAuthentication"]["ProvidedCertificate"] = *reqCertObj;
            } else
            {
                // Requester Cert is not required, no need to report error.
                BMCWEB_LOG_DEBUG << "Unable to parse requester certPath: "
                                 << certPath;
            }
        });

        // Get associated response certs objects.
        std::string respCertPath = objPath + "/responder_identified_by";
        dbus_utils::getAssociationEndPoints(
            respCertPath, context,
            [aResp](const boost::system::error_code& e,
                    const dbus::utility::MapperEndPoints& nodeRespCertList) {
            if (e)
            {
                if (e.value() != EBADR)
                {
                    messages::internalError(aResp->res);
                    return;
                }
                // No resource found.
                return;
            }

            nlohmann::json& json = aResp->res.jsonValue;

            // One ComponentIntegrity object should be associated with one
            // responder certificate object
            if (nodeRespCertList.size() != 1)
            {
                BMCWEB_LOG_ERROR
                    << "Unexpected Responder Cert #objs (expecting 1): "
                    << nodeRespCertList.size();
                messages::internalError(aResp->res);
                return;
            }

            const std::string& certPath = nodeRespCertList.at(0);

            std::optional<nlohmann::json> respCertObj =
                getChassisCert(certPath);

            if (respCertObj != std::nullopt)
            {
                json["SPDM"]["IdentityAuthentication"]["ResponderAuthentication"]["ComponentCertificate"] = *respCertObj;
            } else
            {
                BMCWEB_LOG_ERROR << "Unable to parse responder certPath: "
                                 << certPath;
                messages::internalError(aResp->res);
                return;
            }
        });
    });
}

inline void getComponentData(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 == attestationComponentIntegrityIntf)
            {
                getComponentIntegrityData(aResp, serviceName, objectPath);
            }
            else if (interface == attestationIntegrityAuthIntf)
            {
                getSPDMAuthenticationData(aResp, serviceName, objectPath);
            }
        }
    }
}

inline void addSPDMGetSignedMeasurementsLinks(nlohmann::json& getMeasurement,
                                              const std::string& componentId)
{
    getMeasurement["target"] = crow::utility::urlFromPieces(
        "redfish", "v1", "ComponentIntegrity", componentId, "Actions",
        "ComponentIntegrity.SPDMGetSignedMeasurements");
    getMeasurement["@Redfish.ActionInfo"] = crow::utility::urlFromPieces(
        "redfish", "v1", "ComponentIntegrity", componentId,
        "SPDMGetSignedMeasurementsActionInfo");
}

/**
 * Find the D-Bus object representing the requested ComponentIntegrity,
 * 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]       processorId     Redfish Processor Id.
 * @param[in]       handler         Callback to continue processing request upon
 *                                  successfully finding object.
 */
template <typename Handler>
inline void getComponentObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
                               const std::string& componentId,
                               Handler&& handler)
{
    BMCWEB_LOG_DEBUG << "Get available system component integrity resources.";

    // GetSubTree on all interfaces which provide info about a
    // component_integrity.
    managedStore::ManagedObjectStoreContext context(resp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/ComponentIntegrity/", 0,
        componentIntegrityInterfaces, context,
        [resp, 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
            // componentintegrity name
            if (!objectPath.ends_with(componentId))
            {
                continue;
            }

            bool found = false;
            // Filter out objects that don't have the
            // ComponentIntegrity-specific interfaces to make sure we can return
            // 404 on non-ComponentIntegrity
            for (const auto& [serviceName, interfaceList] : serviceMap)
            {
                if (std::find_first_of(interfaceList.begin(),
                                       interfaceList.end(),
                                       componentIntegrityInterfaces.begin(),
                                       componentIntegrityInterfaces.end()) !=
                    interfaceList.end())
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                continue;
            }

            // Matching component found
            resp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "ComponentIntegrity", componentId);

            resp->res.jsonValue["Name"] = "Component Integrity";
            resp->res.jsonValue["Id"] = componentId;
            resp->res.jsonValue["SPDM"]["Requester"]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc");

            addSPDMGetSignedMeasurementsLinks(
                resp->res.jsonValue["Actions"]["#ComponentIntegrity.SPDMGetSignedMeasurements"],
                componentId);

            handler(objectPath, serviceMap);
            return;
        }
        messages::resourceNotFound(resp->res, "ComponentIntegrity",
                                   componentId);
    });
}

inline void handleComponentIntegrityCollectionGet(
    crow::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"] =
        "#ComponentIntegrityCollection.ComponentIntegrityCollection";
    asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/ComponentIntegrity";
    asyncResp->res.jsonValue["Name"] = "Component Integrity Collection";
    asyncResp->res.jsonValue["Description"] =
        "Collection of Component Integrity";

    collection_util::getCollectionMembers(
        asyncResp, boost::urls::url("/redfish/v1/ComponentIntegrity"),
        componentIntegrityInterfaces,
        "/xyz/openbmc_project/ComponentIntegrity");
}

inline void handleComponentIntegrityGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& componentId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    asyncResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ComponentIntegrity/ComponentIntegrity.json>; rel=describedby");
    asyncResp->res.jsonValue["@odata.type"] =
        "#ComponentIntegrity.v1_2_0.ComponentIntegrity";

    getComponentObject(asyncResp, componentId,
                       std::bind_front(getComponentData, asyncResp));
}

inline void handleSPDMGetSignedMeasurementsActionInfoGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& componentId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    asyncResp->res.jsonValue["@odata.type"] =
        "#ActionInfo.v1_3_0.ActionInfo";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "ComponentIntegrity", componentId,
        "SPDMGetSignedMeasurementsActionInfo");

    asyncResp->res.jsonValue["Name"] = "SPDMGetSignedMeasurements Action Info";
    asyncResp->res.jsonValue["Id"] =
        "SPDMGetSignedMeasurementsActionInfo";

    nlohmann::json::array_t parameters;
    nlohmann::json::object_t indices;
    nlohmann::json::object_t nonce;
    nlohmann::json::object_t slotId;

    indices["Name"] = "MeasurementIndices";
    indices["Required"] = false;
    indices["DataType"] = "NumberArray";

    nonce["Name"] = "Nonce";
    nonce["Required"] = false;
    nonce["DataType"] = "String";

    slotId["Name"] = "SlotId";
    slotId["Required"] = false;
    slotId["DataType"] = "Number";

    parameters.emplace_back(std::move(indices));
    parameters.emplace_back(std::move(nonce));
    parameters.emplace_back(std::move(slotId));
    asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
}

inline void handleComponentIntegritySPDMGetSignedMeasurementsActionPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& componentId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    BMCWEB_LOG_DEBUG << "Post ComponentIntegrity SPDMGetSignedMeasurements.";

    // GetSubTree on interfaces which provide info about certificate.
    constexpr std::array<std::string_view, 1> interfaces = {
        attestationMeasurementSetIntf};

    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/ComponentIntegrity/", 0, interfaces, context,
        [asyncResp, req, componentId](const boost::system::error_code& ec,
                      const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        std::string ciPath =
            std::string("/xyz/openbmc_project/ComponentIntegrity/") +
            componentId;

        nlohmann::json reqJson;
        JsonParseResult ret = parseRequestAsJson(req, reqJson);
        if (ret != JsonParseResult::Success)
        {
            // We did not receive JSON request, proceed as it is RAW data
            BMCWEB_LOG_ERROR << "Parse json request failed!";
            messages::internalError(asyncResp->res);
            return;
        }

        // All fields below are optional by DMTF DSP2046_2022.3.pdf
        // default nonce empty, libspdm will generate one.
        std::optional<std::string> optNonce = "";
        // default 0 indicates using slot 0.
        std::optional<size_t> optSlotId = 0;
        // default 255(0xff) indicates requesting all measurement blocks.
        std::optional<std::vector<size_t>> optMeasurementIndices =
            std::vector<size_t>{255};

        // readJsonPatch will move on when some fields are missing, we only
        // use default value for missing fields.
        if (!json_util::readJsonPatch(req, asyncResp->res, "SlotId", optSlotId,
                                      "MeasurementIndices",
                                      optMeasurementIndices, "Nonce", optNonce))
        {
            BMCWEB_LOG_DEBUG << "Using default only for missing params!";
        }

        for (const auto& [objectPath, serviceMap] : subtree)
        {
            // Ignore any objects which don't match component integrity
            if (objectPath.find(ciPath) == std::string::npos)
            {
                continue;
            }

            // Should only match one service and one object
            for (const auto& [serviceName, interfaceList] : serviceMap)
            {
                // SPDMGetSignedMeasurements Response
                managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
                    asyncResp->strand_,
                    [asyncResp](const boost::system::error_code& e,
                    const sdbusplus::message::object_path& certPath,
                    const std::string& hashAlg,
                    const std::string& pubkey,
                    const std::string& signedMeasurements,
                    const std::string& signAlg,
                    const std::string& version) {
                    if (e)
                    {
                        BMCWEB_LOG_ERROR << "DBUS response error: "
                                         << e.message();
                        messages::internalError(asyncResp->res);
                        return;
                    }

                    asyncResp->res.jsonValue["@odata.type"] =
                        "#ComponentIntegrity.v1_0_0.SPDMGetSignedMeasurementsResponse";
                    asyncResp->res.jsonValue["Version"] = version;
                    asyncResp->res.jsonValue["HashingAlgorithm"] = hashAlg;
                    asyncResp->res.jsonValue["SigningAlgorithm"] = signAlg;
                    asyncResp->res.jsonValue["SignedMeasurements"] =
                        signedMeasurements;
                    asyncResp->res.jsonValue["PublicKey"] = pubkey;

                    // handle Device Certificate
                    std::optional<nlohmann::json> certObj =
                        getChassisCert(certPath);

                    if (certObj != std::nullopt)
                    {
                        asyncResp->res.jsonValue["Certificate"] = *certObj;
                    } else
                    {
                        BMCWEB_LOG_ERROR << "Unable to parse certPath: "
                                         << std::string(certPath);
                        messages::internalError(asyncResp->res);
                        return;
                    }
                },
                    serviceName, ciPath,
                    "xyz.openbmc_project.Attestation.MeasurementSet",
                    "SPDMGetSignedMeasurements", *optMeasurementIndices,
                    *optNonce, *optSlotId);
            }
        }
    });
}

inline void requestRoutesComponentIntegrityCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/ComponentIntegrity/")
        .privileges(redfish::privileges::getComponentIntegrityCollection)
        .methods(boost::beast::http::verb::get)(std::bind_front(
            handleComponentIntegrityCollectionGet, std::ref(app)));
}

inline void requestRoutesComponentIntegrity(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/ComponentIntegrity/<str>/")
        .privileges(redfish::privileges::getComponentIntegrity)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleComponentIntegrityGet, std::ref(app)));
}

inline void requestRoutesComponentIntegritySPDMGetSignedMeasurementsActionInfo(App& app)
{
    BMCWEB_ROUTE(app,
        "/redfish/v1/ComponentIntegrity/<str>/SPDMGetSignedMeasurementsActionInfo")
        .privileges(redfish::privileges::getActionInfo)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleSPDMGetSignedMeasurementsActionInfoGet, std::ref(app)));
}

inline void
    requestRoutesComponentIntegritySPDMGetSignedMeasurementsAction(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/ComponentIntegrity/<str>/Actions/ComponentIntegrity.SPDMGetSignedMeasurements/")
        .privileges(redfish::privileges::getComponentIntegrity)
        .methods(boost::beast::http::verb::post)(std::bind_front(
            handleComponentIntegritySPDMGetSignedMeasurementsActionPost,
            std::ref(app)));
}

} // namespace redfish
