chromium/components/policy/core/common/cloud/cloud_policy_client_unittest.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "components/policy/core/common/cloud/cloud_policy_client.h"

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <set>
#include <utility>

#include "base/compiler_specific.h"
#include "base/containers/map_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/policy/core/common/cloud/client_data_delegate.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/cloud_policy_util.h"
#include "components/policy/core/common/cloud/dm_auth.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/policy/core/common/cloud/mock_device_management_service.h"
#include "components/policy/core/common/cloud/mock_signing_service.h"
#include "components/policy/core/common/cloud/realtime_reporting_job_configuration.h"
#include "components/policy/core/common/cloud/reporting_job_configuration_base.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "components/version_info/version_info.h"
#include "google_apis/gaia/gaia_urls.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ash/components/system/fake_statistics_provider.h"
#endif

_;
Contains;
DoAll;
ElementsAre;
Invoke;
Key;
Mock;
Not;
Pair;
Return;
SaveArg;
StrictMock;
WithArg;

// Matcher for std::optional. Can be combined with Not().
MATCHER(HasValue, "Has value") {}

em;

// An enum for PSM execution result values.
PsmExecutionResult;

namespace policy {

namespace {

constexpr char kClientID[] =;
constexpr char kMachineID[] =;
constexpr char kMachineModel[] =;
constexpr char kBrandCode[] =;
constexpr char kAttestedDeviceId[] =;
constexpr CloudPolicyClient::MacAddress kEthernetMacAddress =;
constexpr char kEthernetMacAddressStr[] =;
constexpr CloudPolicyClient::MacAddress kDockMacAddress =;
constexpr char kDockMacAddressStr[] =;
constexpr char kManufactureDate[] =;
constexpr char kOAuthToken[] =;
constexpr char kDMToken[] =;
constexpr char kDeviceDMToken[] =;
constexpr char kMachineCertificate[] =;
constexpr char kEnrollmentCertificate[] =;
constexpr char kEnrollmentId[] =;
constexpr char kOsName[] =;

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
constexpr char kIdToken[] =;
constexpr char kOidcState[] =;
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || \
    (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
constexpr char kBrowserEnrollmentToken[] =;
#endif

constexpr char kFlexEnrollmentToken[] =;

constexpr char kRequisition[] =;
constexpr char kStateKey[] =;
constexpr char kPayload[] =;
constexpr char kResultPayload[] =;
constexpr char kAssetId[] =;
constexpr char kLocation[] =;
constexpr char kGcmID[] =;
constexpr char kPolicyToken[] =;
constexpr char kPolicyName[] =;
constexpr char kValueValidationMessage[] =;
constexpr char kRobotAuthCode[] =;
constexpr char kApiAuthScope[] =;

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
constexpr base::TimeDelta kDefaultOidcRegistrationTimeout =;
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

constexpr int64_t kAgeOfCommand =;
constexpr int64_t kLastCommandId =;
constexpr int64_t kTimestamp =;

constexpr em::PolicyFetchRequest::SignatureType
    kRemoteCommandsFetchSignatureType =;

constexpr PolicyFetchReason kReason =;
constexpr auto kProtoReason =;

MATCHER_P(MatchProto, expected, "matches protobuf") {}

// A mock class to allow us to set expectations on result callbacks.
struct MockResultCallbackObserver {};

// A mock class to allow us to set expectations on status callbacks.
struct MockStatusCallbackObserver {};

// A mock class to allow us to set expectations on remote command fetch
// callbacks.
struct MockRemoteCommandsObserver {};

struct MockDeviceDMTokenCallbackObserver {};

struct MockRobotAuthCodeCallbackObserver {};

struct MockResponseCallbackObserver {};

class FakeClientDataDelegate : public ClientDataDelegate {};

std::string CreatePolicyData(const std::string& policy_value) {}

em::DeviceManagementRequest GetPolicyRequest() {}

em::DeviceManagementResponse GetPolicyResponse() {}

em::DeviceManagementRequest GetRegistrationRequest() {}

em::DeviceManagementResponse GetRegistrationResponse() {}

em::DeviceManagementResponse GetTokenBasedRegistrationResponse() {}

em::DeviceManagementRequest GetReregistrationRequest() {}

em::DeviceManagementRequest GetTokenBasedDeviceRegistrationRequest() {}

// Constructs the DeviceManagementRequest with
// CertificateBasedDeviceRegistrationData.
// Also, if |psm_execution_result| or |psm_determination_timestamp| has a value,
// then populate its corresponding PSM field in DeviceRegisterRequest.
em::DeviceManagementRequest GetCertBasedRegistrationRequest(
    FakeSigningService* fake_signing_service,
    std::optional<PsmExecutionResult> psm_execution_result,
    std::optional<int64_t> psm_determination_timestamp,
    const std::optional<em::DemoModeDimensions>& demo_mode_dimensions) {}

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || \
    (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
em::DeviceManagementRequest GetEnrollmentRequest() {}
#endif

em::DeviceManagementRequest GetUploadMachineCertificateRequest() {}

em::DeviceManagementRequest GetUploadEnrollmentCertificateRequest() {}

em::DeviceManagementResponse GetUploadCertificateResponse() {}

em::DeviceManagementRequest GetUploadStatusRequest() {}

em::DeviceManagementRequest GetRemoteCommandRequest(
    em::PolicyFetchRequest::SignatureType signature_type) {}

em::DeviceManagementRequest GetRobotAuthCodeFetchRequest() {}

em::DeviceManagementResponse GetRobotAuthCodeFetchResponse() {}

em::DeviceManagementResponse GetFmRegistrationTokenUploadResponse() {}

em::DeviceManagementResponse GetEmptyResponse() {}

em::DemoModeDimensions GetDemoModeDimensions() {}

}  // namespace

class CloudPolicyClientTest : public testing::Test {};

// CloudPolicyClient tests that need multiple threads.
class CloudPolicyClientMultipleThreadsTest : public CloudPolicyClientTest {};

TEST_F(CloudPolicyClientTest, Init) {}

TEST_F(CloudPolicyClientTest, SetupRegistrationAndPolicyFetch) {}

class CloudPolicyClientWithFetchReasonTest
    : public CloudPolicyClientTest,
      public testing::WithParamInterface<
          std::tuple<PolicyFetchReason,
                     enterprise_management::DevicePolicyRequest_Reason>> {};

TEST_P(CloudPolicyClientWithFetchReasonTest, FetchReason) {}

INSTANTIATE_TEST_SUITE_P();

class CloudPolicyClientFetchPolicyCriticalTest
    : public CloudPolicyClientTest,
      public testing::WithParamInterface<std::tuple<PolicyFetchReason, bool>> {};

TEST_P(CloudPolicyClientFetchPolicyCriticalTest, FetchReasonIsCritical) {}

// As of today, only policy fetches during device enrollment are considered
// critical (that was the initial purpose of the parameter). We might consider
// more fetch reasons critical in the future, but it would be odd to make all
// policy fetches critical.
INSTANTIATE_TEST_SUITE_P();

TEST_F(CloudPolicyClientTest, SetupRegistrationAndPolicyFetchWithOAuthToken) {}

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || \
    (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
TEST_F(CloudPolicyClientTest, BrowserRegistrationWithTokenAndPolicyFetch) {}

TEST_F(CloudPolicyClientTest, BrowserRegistrationWithTokenTestTimeout) {}
#endif

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
TEST_F(CloudPolicyClientTest, RegistrationWithOidcAndPolicyFetch) {}

TEST_F(CloudPolicyClientTest, RegistrationWithOidcAndPolicyFetchWithOidcState) {}

TEST_F(CloudPolicyClientTest, OidcRegistrationFailure) {}
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

TEST_F(CloudPolicyClientTest, RegistrationAndPolicyFetch) {}

TEST_F(CloudPolicyClientTest, RegistrationAndPolicyFetchWithOAuthToken) {}

TEST_F(CloudPolicyClientTest, RegistrationWithCertificateAndPolicyFetch) {}

TEST_F(CloudPolicyClientTest,
       FlexDeviceRegistrationWithEnrollmentTokenAndPolicyFetch) {}

// TODO(b/329271128): Add tests or modify this one to test specific errors
// returned for token-based (Flex) enrollment.
TEST_F(CloudPolicyClientTest,
       FlexDeviceRegistrationWithEnrollmentTokenFailure) {}

TEST_F(CloudPolicyClientTest, DemoModeRegistration) {}

TEST_F(CloudPolicyClientTest, RegistrationWithCertificateFailToSignRequest) {}

TEST_F(CloudPolicyClientTest, RegistrationParametersPassedThrough) {}

TEST_F(CloudPolicyClientTest, RegistrationNoDMTokenInResponse) {}

TEST_F(CloudPolicyClientTest, RegistrationFailure) {}

TEST_F(CloudPolicyClientTest, RetryRegistration) {}

TEST_F(CloudPolicyClientTest, PolicyUpdate) {}

TEST_F(CloudPolicyClientTest, PolicyFetchSHA256) {}

TEST_F(CloudPolicyClientTest, PolicyFetchDisabledSHA256) {}

TEST_F(CloudPolicyClientTest, PolicyFetchWithMetaData) {}

TEST_F(CloudPolicyClientTest, PolicyFetchWithInvalidation) {}

TEST_F(CloudPolicyClientTest, PolicyFetchWithInvalidationNoPayload) {}

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
TEST_F(CloudPolicyClientMultipleThreadsTest,
       PolicyFetchWithBrowserDeviceIdentifier) {}
#endif

// Tests that previous OAuth token is no longer sent in policy fetch after its
// value was cleared.
TEST_F(CloudPolicyClientTest, PolicyFetchClearOAuthToken) {}

TEST_F(CloudPolicyClientTest, BadPolicyResponse) {}

TEST_F(CloudPolicyClientTest, PolicyRequestFailure) {}

TEST_F(CloudPolicyClientTest, PolicyFetchWithExtensionPolicy) {}

TEST_F(CloudPolicyClientTest, UploadEnterpriseMachineCertificate) {}

TEST_F(CloudPolicyClientTest, UploadEnterpriseEnrollmentCertificate) {}

TEST_F(CloudPolicyClientTest, UploadEnterpriseMachineCertificateEmpty) {}

TEST_F(CloudPolicyClientTest, UploadEnterpriseMachineCertificateNotRegistered) {}

TEST_F(CloudPolicyClientTest, UploadEnterpriseEnrollmentCertificateEmpty) {}

TEST_F(CloudPolicyClientTest, UploadCertificateFailure) {}

TEST_F(CloudPolicyClientTest, UploadEnterpriseEnrollmentId) {}

TEST_F(CloudPolicyClientTest, UploadStatus) {}

TEST_F(CloudPolicyClientTest, UploadStatusNotRegistered) {}

TEST_F(CloudPolicyClientTest, UploadStatusWithOAuthToken) {}

TEST_F(CloudPolicyClientTest, UploadStatusWhilePolicyFetchActive) {}

TEST_F(CloudPolicyClientTest, UploadPolicyValidationReport) {}

TEST_F(CloudPolicyClientTest, UploadChromeDesktopReport) {}

TEST_F(CloudPolicyClientTest, UploadChromeDesktopReportNotRegistered) {}

TEST_F(CloudPolicyClientTest, UploadChromeOsUserReport) {}

TEST_F(CloudPolicyClientTest, UploadChromeOsUserReportNotRegistered) {}

TEST_F(CloudPolicyClientTest, UploadChromeProfile) {}

TEST_F(CloudPolicyClientTest, UploadChromeProfileNotRegistered) {}

// A helper class to test all em::DeviceRegisterRequest::PsmExecutionResult enum
// values.
class CloudPolicyClientRegisterWithPsmParamsTest
    : public CloudPolicyClientTest,
      public testing::WithParamInterface<PsmExecutionResult> {};

TEST_P(CloudPolicyClientRegisterWithPsmParamsTest,
       RegistrationWithCertificateAndPsmResult) {}

INSTANTIATE_TEST_SUITE_P();

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
    BUILDFLAG(IS_CHROMEOS)

class CloudPolicyClientUploadSecurityEventTest
    : public CloudPolicyClientTest,
      public testing::WithParamInterface<bool> {};

INSTANTIATE_TEST_SUITE_P();

TEST_F(CloudPolicyClientTest, UploadSecurityEventReportNotRegistered) {}

TEST_P(CloudPolicyClientUploadSecurityEventTest, Test) {}

TEST_F(CloudPolicyClientTest, RealtimeReportMerge) {}

TEST_F(CloudPolicyClientTest, UploadAppInstallReportNotRegistered) {}

TEST_F(CloudPolicyClientTest, UploadAppInstallReport) {}

TEST_F(CloudPolicyClientTest, CancelUploadAppInstallReport) {}

TEST_F(CloudPolicyClientTest, UploadAppInstallReportSupersedesPending) {}

#endif

TEST_F(CloudPolicyClientTest, MultipleActiveRequests) {}

TEST_F(CloudPolicyClientTest, UploadStatusFailure) {}

TEST_F(CloudPolicyClientTest, ShouldRejectUnsignedCommands) {}

TEST_F(CloudPolicyClientTest,
       ShouldIgnoreSignedCommandsIfUnsignedCommandsArePresent) {}

TEST_F(CloudPolicyClientTest, ShouldNotFailIfRemoteCommandResponseIsEmpty) {}

TEST_F(CloudPolicyClientTest, FetchSecureRemoteCommands) {}

TEST_F(CloudPolicyClientTest,
       RequestDeviceAttributeUpdatePermissionWithOAuthToken) {}

TEST_F(CloudPolicyClientTest,
       RequestDeviceAttributeUpdatePermissionWithDMToken) {}

TEST_F(CloudPolicyClientTest,
       RequestDeviceAttributeUpdatePermissionMissingResponse) {}

TEST_F(CloudPolicyClientTest, RequestDeviceAttributeUpdate) {}

TEST_F(CloudPolicyClientTest, RequestGcmIdUpdate) {}

TEST_F(CloudPolicyClientTest, PolicyReregistration) {}

TEST_F(CloudPolicyClientTest, PolicyReregistrationFailsWithNonMatchingDMToken) {}

#if !BUILDFLAG(IS_CHROMEOS)
TEST_F(CloudPolicyClientTest, PolicyReregistrationAfterDMTokenDeletion) {}
#endif  // !BUILDFLAG(IS_CHROMEOS)

TEST_F(CloudPolicyClientTest, RequestFetchRobotAuthCodes) {}

TEST_F(CloudPolicyClientTest,
       RequestFetchRobotAuthCodesNotInterruptedByPolicyFetch) {}

TEST_F(CloudPolicyClientTest, UploadFmRegistrationTokenRequest) {}

struct MockClientCertProvisioningRequestCallbackObserver {};

// Tests for CloudPolicyClient::ClientCertProvisioningRequest. The test
// parameter is a device DMToken (which can be empty).
class CloudPolicyClientCertProvisioningRequestTest
    : public CloudPolicyClientTest,
      public ::testing::WithParamInterface<std::string> {};

// Tests that a ClientCertificateProvisioningRequest succeeds.
TEST_P(CloudPolicyClientCertProvisioningRequestTest, Success) {}

// Tests that a ClientCertificateProvisioningRequest fails because the response
// can't be decoded. Specifically, it doesn't contain a
// client_certificate_provisioning_response field.
TEST_P(CloudPolicyClientCertProvisioningRequestTest, FailureDecodingError) {}

// Tests that a ClientCertificateProvisioningRequest fails because the response
// DeviceManagementStatus is not DM_STATUS_SUCCESS.
TEST_P(CloudPolicyClientCertProvisioningRequestTest, NonSuccessStatus) {}

INSTANTIATE_TEST_SUITE_P();

}  // namespace policy