blob: 2c8142fb2c06d029288a8abb0afe00c0ddfa1818 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/enterprise/connectors/connectors_service.h"
#include "base/json/json_reader.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/enterprise/connectors/common.h"
#include "chrome/browser/policy/dm_token_utils.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/policy/core/common/policy_types.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace enterprise_connectors {
namespace {
constexpr char kEmptySettingsPref[] = "[]";
constexpr char kNormalAnalysisSettingsPref[] = R"([
{
"service_provider": "google",
"enable": [
{"url_list": ["*"], "tags": ["dlp", "malware"]}
],
"disable": [
{"url_list": ["no.dlp.com", "no.dlp.or.malware.ca"], "tags": ["dlp"]},
{"url_list": ["no.malware.com", "no.dlp.or.malware.ca"],
"tags": ["malware"]}
],
"block_until_verdict": 1,
"block_password_protected": true,
"block_large_files": true,
"block_unsupported_file_types": true
}
])";
constexpr char kNormalReportingSettingsPref[] = R"([
{
"service_provider": "google"
}
])";
constexpr char kNormalSendDownloadToCloudPref[] = R"([
{
"service_provider": "box",
"enterprise_id": "1234567890",
"enable": [
{
"url_list": ["*"],
"mime_types": ["text/plain", "image/png", "application/zip"]
}
],
"disable": [
{
"url_list": ["no.text.com", "no.text.no.image.com"],
"mime_types": ["text/plain"]
},
{
"url_list": ["no.image.com", "no.text.no.image.com"],
"mime_types": ["image/png"]
}
]
}
])";
constexpr char kDlpAndMalwareUrl[] = "https://foo.com";
constexpr char kOnlyDlpUrl[] = "https://no.malware.com";
constexpr char kOnlyMalwareUrl[] = "https://no.dlp.com";
constexpr char kNoTagsUrl[] = "https://no.dlp.or.malware.ca";
} // namespace
class ConnectorsServiceTest : public testing::Test {
public:
ConnectorsServiceTest()
: profile_manager_(TestingBrowserProcess::GetGlobal()) {
EXPECT_TRUE(profile_manager_.SetUp());
profile_ = profile_manager_.CreateTestingProfile("test-user");
policy::SetDMTokenForTesting(
policy::DMToken::CreateValidTokenForTesting("fake-token"));
}
protected:
content::BrowserTaskEnvironment task_environment_;
base::test::ScopedFeatureList scoped_feature_list_;
TestingProfileManager profile_manager_;
TestingProfile* profile_;
};
class ConnectorsServiceAnalysisNoFeatureTest
: public ConnectorsServiceTest,
public testing::WithParamInterface<AnalysisConnector> {
public:
ConnectorsServiceAnalysisNoFeatureTest() {
scoped_feature_list_.InitWithFeatures({}, {kEnterpriseConnectorsEnabled});
}
AnalysisConnector connector() { return GetParam(); }
};
TEST_P(ConnectorsServiceAnalysisNoFeatureTest, AnalysisConnectors) {
profile_->GetPrefs()->Set(
ConnectorPref(connector()),
*base::JSONReader::Read(kNormalAnalysisSettingsPref));
auto* service = ConnectorsServiceFactory::GetForBrowserContext(profile_);
for (const char* url :
{kDlpAndMalwareUrl, kOnlyDlpUrl, kOnlyMalwareUrl, kNoTagsUrl}) {
// Only base::nullopt should be returned when the feature is disabled,
// regardless of what Connector or URL is used.
auto settings = service->GetAnalysisSettings(GURL(url), connector());
ASSERT_FALSE(settings.has_value());
}
// No cached settings imply the connector value was never read.
ASSERT_TRUE(service->ConnectorsManagerForTesting()
->GetAnalysisConnectorsSettingsForTesting()
.empty());
}
INSTANTIATE_TEST_CASE_P(,
ConnectorsServiceAnalysisNoFeatureTest,
testing::Values(FILE_ATTACHED,
FILE_DOWNLOADED,
BULK_DATA_ENTRY));
// Tests to make sure getting reporting settings work with both the feature flag
// and the OnSecurityEventEnterpriseConnector policy. The parameter for these
// tests is a tuple of:
//
// enum class ReportingConnector[]: array of all reporting connectors.
// bool: enable feature flag.
// int: policy value. 0: don't set, 1: set to normal, 2: set to empty.
class ConnectorsServiceReportingFeatureTest
: public ConnectorsServiceTest,
public testing::WithParamInterface<
std::tuple<ReportingConnector, bool, int>> {
public:
ConnectorsServiceReportingFeatureTest() {
if (enable_feature_flag()) {
scoped_feature_list_.InitWithFeatures({kEnterpriseConnectorsEnabled}, {});
} else {
scoped_feature_list_.InitWithFeatures({}, {kEnterpriseConnectorsEnabled});
}
}
ReportingConnector connector() const { return std::get<0>(GetParam()); }
bool enable_feature_flag() const { return std::get<1>(GetParam()); }
int policy_value() const { return std::get<2>(GetParam()); }
const char* pref() const { return ConnectorPref(connector()); }
const char* scope_pref() const { return ConnectorScopePref(connector()); }
const char* pref_value() const {
switch (policy_value()) {
case 1:
return kNormalReportingSettingsPref;
case 2:
return kEmptySettingsPref;
}
NOTREACHED();
return nullptr;
}
bool reporting_enabled() const {
return enable_feature_flag() && policy_value() == 1;
}
void ValidateSettings(const ReportingSettings& settings) {
// For now, the URL is the same for both legacy and new policies, so
// checking the specific URL here. When service providers become
// configurable this will change.
ASSERT_EQ(GURL("https://chromereporting-pa.googleapis.com/v1/events"),
settings.reporting_url);
}
};
TEST_P(ConnectorsServiceReportingFeatureTest, Test) {
if (policy_value() != 0) {
profile_->GetPrefs()->Set(pref(), *base::JSONReader::Read(pref_value()));
profile_->GetPrefs()->SetInteger(scope_pref(),
policy::POLICY_SCOPE_MACHINE);
}
auto settings = ConnectorsServiceFactory::GetForBrowserContext(profile_)
->GetReportingSettings(connector());
EXPECT_EQ(reporting_enabled(), settings.has_value());
if (settings.has_value())
ValidateSettings(settings.value());
EXPECT_EQ(enable_feature_flag() && policy_value() == 1,
!ConnectorsServiceFactory::GetForBrowserContext(profile_)
->ConnectorsManagerForTesting()
->GetReportingConnectorsSettingsForTesting()
.empty());
}
INSTANTIATE_TEST_CASE_P(
,
ConnectorsServiceReportingFeatureTest,
testing::Combine(testing::Values(ReportingConnector::SECURITY_EVENT),
testing::Bool(),
testing::ValuesIn({0, 1, 2})));
// Tests to make sure file system settings work with both the feature flag
// and the policy. The parameter for these tests is a tuple of:
//
// enum class FileSystemConnector[]: array of all file system connectors.
// bool: enable feature flag.
// int: policy value. 0: don't set, 1: set to normal, 2: set to empty.
class ConnectorsServiceFileSystemFeatureTest
: public ConnectorsServiceTest,
public testing::WithParamInterface<
std::tuple<FileSystemConnector, bool, int>> {
public:
ConnectorsServiceFileSystemFeatureTest() {
if (enable_feature_flag()) {
scoped_feature_list_.InitWithFeatures({kEnterpriseConnectorsEnabled}, {});
} else {
scoped_feature_list_.InitWithFeatures({}, {kEnterpriseConnectorsEnabled});
}
}
FileSystemConnector connector() const { return std::get<0>(GetParam()); }
bool enable_feature_flag() const { return std::get<1>(GetParam()); }
int policy_value() const { return std::get<2>(GetParam()); }
const char* pref() const { return ConnectorPref(connector()); }
const char* pref_value() const {
switch (policy_value()) {
case 1:
return kNormalSendDownloadToCloudPref;
case 2:
return kEmptySettingsPref;
}
NOTREACHED();
return nullptr;
}
bool file_system_enabled() const {
return enable_feature_flag() && policy_value() == 1;
}
void ValidateSettings(const FileSystemSettings& settings) {
// Mime types are the only setting affect by the policy, the rest are
// just copied from the service provider comfig. So only need to validate
// this in tests.
ASSERT_EQ(settings.mime_types, expected_mime_types_);
}
void set_expected_mime_types(std::set<std::string> expected_mime_types) {
expected_mime_types_ = std::move(expected_mime_types);
}
private:
std::set<std::string> expected_mime_types_;
};
TEST_P(ConnectorsServiceFileSystemFeatureTest, Test) {
if (policy_value() != 0) {
profile_->GetPrefs()->Set(pref(), *base::JSONReader::Read(pref_value()));
}
auto settings =
ConnectorsServiceFactory::GetForBrowserContext(profile_)
->GetFileSystemSettings(GURL("https://any.com"), connector());
EXPECT_EQ(file_system_enabled(), settings.has_value());
if (settings.has_value()) {
set_expected_mime_types({"text/plain", "image/png", "application/zip"});
ValidateSettings(settings.value());
}
EXPECT_EQ(enable_feature_flag() && policy_value() == 1,
!ConnectorsServiceFactory::GetForBrowserContext(profile_)
->ConnectorsManagerForTesting()
->GetFileSystemConnectorsSettingsForTesting()
.empty());
}
INSTANTIATE_TEST_CASE_P(
,
ConnectorsServiceFileSystemFeatureTest,
testing::Combine(
testing::Values(FileSystemConnector::SEND_DOWNLOAD_TO_CLOUD),
testing::Bool(),
testing::ValuesIn({0, 1, 2})));
TEST_F(ConnectorsServiceTest, RealtimeURLCheck) {
profile_->GetPrefs()->SetInteger(
prefs::kSafeBrowsingEnterpriseRealTimeUrlCheckMode,
safe_browsing::REAL_TIME_CHECK_FOR_MAINFRAME_ENABLED);
profile_->GetPrefs()->SetInteger(
prefs::kSafeBrowsingEnterpriseRealTimeUrlCheckScope,
policy::POLICY_SCOPE_MACHINE);
auto maybe_dm_token = ConnectorsServiceFactory::GetForBrowserContext(profile_)
->GetDMTokenForRealTimeUrlCheck();
EXPECT_TRUE(maybe_dm_token.has_value());
EXPECT_EQ("fake-token", maybe_dm_token.value());
policy::SetDMTokenForTesting(policy::DMToken::CreateEmptyTokenForTesting());
maybe_dm_token = ConnectorsServiceFactory::GetForBrowserContext(profile_)
->GetDMTokenForRealTimeUrlCheck();
EXPECT_FALSE(maybe_dm_token.has_value());
}
} // namespace enterprise_connectors