blob: 696d22b1db83037330786b1aa5ed387c40b6a0a4 [file]
#include "google/google_service_root.hpp"
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <system_error>
#include <utility>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "absl/functional/any_invocable.h"
#include "boost/beast/http/field.hpp" // NOLINT
#include "boost/beast/http/message.hpp" // NOLINT
#include "boost/beast/http/status.hpp" // NOLINT
#include "boost/beast/http/string_body.hpp" // NOLINT
#include "boost/beast/http/verb.hpp" // NOLINT
#include "boost/system/error_code.hpp" // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "test/redfish-core/lib/snapshot_fixture.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "test/g3/mock_managed_store.hpp"
#include "test/g3/mock_managed_store_test.hpp"
#include "sdbusplus/message/native_types.hpp"
namespace crow::google_api {
namespace {
void validateServiceRootGet(crow::Response& res) {
nlohmann::json& json = res.jsonValue;
EXPECT_EQ(json["@odata.id"], "/google/v1");
EXPECT_EQ(json["@odata.type"], "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot");
EXPECT_EQ(json["@odata.id"], "/google/v1");
EXPECT_EQ(json["Id"], "Google Rest RootService");
EXPECT_EQ(json["Name"], "Google Service Root");
EXPECT_EQ(json["Version"], "1.0.0");
EXPECT_EQ(json["RootOfTrustCollection"]["@odata.id"],
"/google/v1/RootOfTrustCollection");
EXPECT_EQ(json["NVMe"]["@odata.id"], "/google/v1/NVMe");
}
TEST(HandleGoogleV1Get, OnSuccess) {
App app(/*allowSessionEmpty=*/true);
std::error_code ec;
auto asyncResp = std::make_shared<bmcweb::AsyncResp>();
asyncResp->res.setCompleteRequestHandler(validateServiceRootGet);
crow::Request dummyRequest{{boost::beast::http::verb::get, "", 11}, ec};
handleGoogleV1Get(app, dummyRequest, asyncResp);
}
} // namespace
} // namespace crow::google_api
namespace redfish {
namespace {
using ::dbus::utility::DBusPropertiesMap;
using managedStore::KeyType;
using managedStore::ManagedType;
crow::Request CreateJsonRequest(std::string_view body = "") {
boost::beast::http::request<boost::beast::http::string_body> reqIn;
reqIn.set(boost::beast::http::field::content_type, "application/json");
std::error_code ec;
crow::Request req(reqIn, ec);
req.req.body() = body;
return req;
}
TEST_F(SnapshotFixture_Platform11_Config8,
HandleRootOfTrustGetCorrectLocation) {
crow::google_api::handleRootOfTrustGet(app_, CreateRequest(),
share_async_resp_, "Hoth");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"], "/google/v1/RootOfTrustCollection/Hoth");
EXPECT_EQ(json["Location"]["PartLocation"]["LocationType"], "Embedded");
EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "Hoth");
EXPECT_EQ(json["Location"]["PartLocationContext"], "DC_SCM");
}
TEST_F(SnapshotFixture_Platform11_Config8, HandleRootOfTrustGet) {
EXPECT_TRUE(
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(
KeyType(ManagedType::kManagedPropertyMap,
"xyz.openbmc_project.Control.Hoth",
sdbusplus::message::object_path(
"/xyz/openbmc_project/Control/Hoth"),
"xyz.openbmc_project.Control.Hoth.State"),
managedStore::MockManagedStoreTest::CreateValueType(
DBusPropertiesMap({
std::make_pair("BootloaderUpdateFailureCode",
uint32_t{0}),
std::make_pair("FirmwareUpdateFailedMinor", uint32_t{0}),
std::make_pair("FirmwareUpdateFailureCode", uint32_t{4}),
std::make_pair("ResetFlags", uint32_t{0}),
std::make_pair("RoInfoStrikes", uint32_t{0}),
std::make_pair("RwInfoStrikes", uint32_t{0}),
std::make_pair("UpTime", uint64_t{19441701616}),
std::make_pair("HasPersistentPanicInfo", false),
std::make_pair("PayloadConfirmFailureCode", uint32_t{0}),
std::make_pair("PayloadUpdateFailureCode", uint32_t{0}),
std::make_pair("HasValidAuthRecord", false),
std::make_pair("AuthRecordCapabilities", uint64_t{0}),
std::make_pair("SecureBootEnforced", true),
std::make_pair("KeyRotationVersion", uint32_t{1}),
std::make_pair("KeyRotationImageFamily", uint16_t{2}),
std::make_pair("KeyRotationImageFamilyVariant",
uint16_t{3}),
std::make_pair("KeyRotationValidationMethod",
uint32_t{4}),
std::make_pair("KeyRotationValidationKeyData",
uint32_t{5}),
std::make_pair("KeyRotationValidationHashData",
uint32_t{6}),
})))
.ok());
EXPECT_CALL(
*dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore()),
PostDbusCallWithObjectPath(
testing::_,
testing::An<absl::AnyInvocable<void(
const boost::system::error_code&, // NOLINT(misc-include-cleaner)
const std::string&)>&&>(),
"xyz.openbmc_project.securityd.TpmAttestationService",
"/xyz/openbmc_project/securityd/tpm_attestation_service",
"xyz.openbmc_project.securityd.TpmAttestationService",
"ReadPcrValues",
sdbusplus::message::object_path("/xyz/openbmc_project/Control/Hoth")))
.Times(1)
.WillOnce(
managedStore::
SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction<
std::string>::
SimulateSuccessfulAsyncPostDbusCallWithValue(
std::make_shared<std::string>("pcr-values-string")));
crow::google_api::handleRootOfTrustGet(app_, CreateRequest(),
share_async_resp_, "Hoth");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["Status"]["Oem"]["BootloaderUpdateFailureCode"], 0);
EXPECT_EQ(json["Status"]["Oem"]["FirmwareUpdateFailedMinor"], 0);
EXPECT_EQ(json["Status"]["Oem"]["FirmwareUpdateFailureCode"], 4);
EXPECT_EQ(json["Status"]["Oem"]["ResetFlags"], 0);
EXPECT_EQ(json["Status"]["Oem"]["RoInfoStrikes"], 0);
EXPECT_EQ(json["Status"]["Oem"]["RwInfoStrikes"], 0);
EXPECT_EQ(json["Status"]["Oem"]["UpTime"], 19441701616);
EXPECT_EQ(json["Status"]["Oem"]["HasPersistentPanicInfo"], false);
EXPECT_EQ(json["Status"]["Oem"]["Payload"]["ConfirmFailureCode"], 0);
EXPECT_EQ(json["Status"]["Oem"]["Payload"]["UpdateFailureCode"], 0);
EXPECT_EQ(json["Status"]["Oem"]["Authorization"]["Valid"], false);
EXPECT_EQ(json["Status"]["Oem"]["Authorization"]["Capabilities"], 0);
EXPECT_EQ(json["Status"]["Oem"]["SecureBootEnforced"], true);
EXPECT_EQ(json["Status"]["Oem"]["KeyRotation"]["Version"], 1);
EXPECT_EQ(json["Status"]["Oem"]["KeyRotation"]["ImageFamily"], 2);
EXPECT_EQ(json["Status"]["Oem"]["KeyRotation"]["ImageFamilyVariant"], 3);
EXPECT_EQ(json["Status"]["Oem"]["KeyRotation"]["ValidationMethod"], 4);
EXPECT_EQ(json["Status"]["Oem"]["KeyRotation"]["ValidationKeyData"], 5);
EXPECT_EQ(json["Status"]["Oem"]["KeyRotation"]["ValidationHashData"], 6);
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
TEST_F(SnapshotFixture_Platform11_Config8, HandleGetSignedMeasurementsPost) {
nlohmann::json requestJson;
requestJson["Nonce"] = "0123456789ABCDEF";
requestJson["PCRSelection"] = "pcrSelectionBase64";
EXPECT_CALL(
*dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore()),
PostDbusCallWithObjectPathAndTwoStrings(
testing::_,
testing::An<absl::AnyInvocable<void(
const boost::system::error_code&, // NOLINT(misc-include-cleaner)
const std::string&)>&&>(),
"xyz.openbmc_project.securityd.TpmAttestationService",
"/xyz/openbmc_project/securityd/tpm_attestation_service",
"xyz.openbmc_project.securityd.TpmAttestationService", "GetPcrQuote",
sdbusplus::message::object_path("/xyz/openbmc_project/Control/Hoth"),
"pcrSelectionBase64", testing::_))
.Times(1)
.WillOnce(
managedStore::
SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction<
std::string>::
SimulateSuccessfulAsyncPostDbusCallWithValue(
std::make_shared<std::string>("quote-string")));
crow::google_api::handleGetSignedMeasurementsPost(
app_, CreateJsonRequest(requestJson.dump()), share_async_resp_, "Hoth");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["SignedMeasurements"], "quote-string");
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
TEST_F(SnapshotFixture_Platform11_Config8, HandleRootOfTrustCertificatesGet) {
EXPECT_CALL(
*dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore()),
PostDbusCallWithObjectPath(
testing::_,
testing::An<absl::AnyInvocable<void(
const boost::system::error_code&, // NOLINT(misc-include-cleaner)
const std::string&)>&&>(),
"xyz.openbmc_project.securityd.TpmAttestationService",
"/xyz/openbmc_project/securityd/tpm_attestation_service",
"xyz.openbmc_project.securityd.TpmAttestationService",
"GetEkCertChain",
sdbusplus::message::object_path("/xyz/openbmc_project/Control/Hoth")))
.Times(1)
.WillOnce(
managedStore::
SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction<
std::string>::
SimulateSuccessfulAsyncPostDbusCallWithValue(
std::make_shared<std::string>("cert-chain-string")));
crow::google_api::handleRootOfTrustCertificatesGet(app_, CreateRequest(),
share_async_resp_, "Hoth");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.type"], "#Certificate.v1_0_0.Certificate");
EXPECT_EQ(json["@odata.id"],
"/google/v1/RootOfTrustCollection/Hoth/Certificates");
EXPECT_EQ(json["Id"], "Certificates");
EXPECT_EQ(json["Name"], "Root Of Trust Certificates");
EXPECT_EQ(json["CertUsageTypes"], nlohmann::json::array({"Device"}));
EXPECT_EQ(json["CertificateType"], "DICE_FEK");
EXPECT_EQ(json["CertString"], "cert-chain-string");
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
TEST_F(SnapshotFixture_Platform11_Config8,
HandleRootOfTrustCertificatesGetRoTNotFound) {
crow::google_api::handleRootOfTrustCertificatesGet(
app_, CreateRequest(), share_async_resp_, "NonExistentHoth");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::not_found);
}
TEST_F(SnapshotFixture_Platform11_Config8,
HandleGetSignedMeasurementsPostMissingNonce) {
nlohmann::json requestJson;
requestJson["PCRSelection"] = "pcrSelectionBase64";
crow::google_api::handleGetSignedMeasurementsPost(
app_, CreateJsonRequest(requestJson.dump()), share_async_resp_, "Hoth");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::bad_request);
}
TEST_F(SnapshotFixture_Platform11_Config8,
HandleGetSignedMeasurementsPostMissingPCRSelection) {
nlohmann::json requestJson;
requestJson["Nonce"] = "0123456789ABCDEF";
crow::google_api::handleGetSignedMeasurementsPost(
app_, CreateJsonRequest(requestJson.dump()), share_async_resp_, "Hoth");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::bad_request);
}
TEST_F(SnapshotFixture_Platform11_Config8,
HandleGetSignedMeasurementsPostRoTNotFound) {
nlohmann::json requestJson;
requestJson["Nonce"] = "0123456789ABCDEF";
requestJson["PCRSelection"] = "pcrSelectionBase64";
crow::google_api::handleGetSignedMeasurementsPost(
app_, CreateJsonRequest(requestJson.dump()), share_async_resp_,
"NonExistentHoth");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::not_found);
}
} // namespace
} // namespace redfish