blob: ef74be10c47cf2419636e87937e3db6f99ed25fa [file] [log] [blame]
// Copyright 2017 The Chromium OS 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 <unordered_set>
#include <base/strings/string_util.h>
#include <components/policy/core/common/registry_dict.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "authpolicy/policy/device_policy_encoder.h"
#include "authpolicy/policy/policy_encoder_test_base.h"
#include "bindings/chrome_device_policy.pb.h"
#include "bindings/policy_constants.h"
namespace em = enterprise_management;
namespace policy {
namespace {
// Converts a repeated string field to a vector.
std::vector<std::string> ToVector(
const google::protobuf::RepeatedPtrField<std::string>& repeated_field) {
return std::vector<std::string>(repeated_field.begin(), repeated_field.end());
}
// Converts a repeated int field to a vector.
std::vector<int> ToVector(
const google::protobuf::RepeatedField<int>& repeated_field) {
return std::vector<int>(repeated_field.begin(), repeated_field.end());
}
} // namespace
// Checks whether all device policies are properly encoded from RegistryDict
// into em::ChromeDeviceSettingsProto. Makes sure no device policy is missing.
class DevicePolicyEncoderTest
: public PolicyEncoderTestBase<em::ChromeDeviceSettingsProto> {
public:
DevicePolicyEncoderTest() {}
~DevicePolicyEncoderTest() override {}
protected:
void EncodeDict(em::ChromeDeviceSettingsProto* policy,
const RegistryDict* dict) override {
DevicePolicyEncoder encoder(dict);
*policy = em::ChromeDeviceSettingsProto();
encoder.EncodePolicy(policy);
}
void MarkHandled(const char* key) override {
handled_policy_keys_.insert(key);
}
// Returns a vector of all policy keys that were not encoded.
std::vector<std::string> GetUnhandledPolicyKeys() const {
std::vector<std::string> unhandled_policy_keys;
for (const char** key = kDevicePolicyKeys; *key; ++key) {
if (handled_policy_keys_.find(*key) == handled_policy_keys_.end())
unhandled_policy_keys.push_back(*key);
}
return unhandled_policy_keys;
}
private:
// Keeps track of handled device policies. Used to detect device policies that
// device_policy_encoder forgets to encode.
std::unordered_set<std::string> handled_policy_keys_;
DISALLOW_COPY_AND_ASSIGN(DevicePolicyEncoderTest);
};
TEST_F(DevicePolicyEncoderTest, TestEncoding) {
// Note that kStringList can't be constexpr, so we put them all here.
const bool kBool = true;
const int kInt = 123;
const std::string kString = "val1";
const std::vector<std::string> kStringList = {"val1", "val2", "val3"};
em::ChromeDeviceSettingsProto policy;
//
// Login policies.
//
EncodeBoolean(&policy, key::kDeviceGuestModeEnabled, kBool);
EXPECT_EQ(kBool, policy.guest_mode_enabled().guest_mode_enabled());
EncodeBoolean(&policy, key::kDeviceRebootOnShutdown, kBool);
EXPECT_EQ(kBool, policy.reboot_on_shutdown().reboot_on_shutdown());
EncodeBoolean(&policy, key::kDeviceShowUserNamesOnSignin, kBool);
EXPECT_EQ(kBool, policy.show_user_names().show_user_names());
EncodeBoolean(&policy, key::kDeviceAllowNewUsers, kBool);
EXPECT_EQ(kBool, policy.allow_new_users().allow_new_users());
EncodeStringList(&policy, key::kDeviceUserWhitelist, kStringList);
EXPECT_EQ(kStringList, ToVector(policy.user_whitelist().user_whitelist()));
EncodeBoolean(&policy, key::kDeviceEphemeralUsersEnabled, kBool);
EXPECT_EQ(kBool, policy.ephemeral_users_enabled().ephemeral_users_enabled());
EncodeBoolean(&policy, key::kDeviceAllowBluetooth, kBool);
EXPECT_EQ(kBool, policy.allow_bluetooth().allow_bluetooth());
EncodeStringList(&policy, key::kDeviceLoginScreenAppInstallList, kStringList);
EXPECT_EQ(kStringList, ToVector(policy.device_login_screen_app_install_list()
.device_login_screen_app_install_list()));
EncodeString(&policy, key::kDeviceLoginScreenDomainAutoComplete, kString);
EXPECT_EQ(kString, policy.login_screen_domain_auto_complete()
.login_screen_domain_auto_complete());
EncodeStringList(&policy, key::kDeviceLoginScreenLocales, kStringList);
EXPECT_EQ(kStringList,
ToVector(policy.login_screen_locales().login_screen_locales()));
EncodeStringList(&policy, key::kDeviceLoginScreenInputMethods, kStringList);
EXPECT_EQ(
kStringList,
ToVector(
policy.login_screen_input_methods().login_screen_input_methods()));
EncodeStringList(&policy, key::kDeviceLoginScreenAutoSelectCertificateForUrls,
kStringList);
EXPECT_EQ(
kStringList,
ToVector(policy.device_login_screen_auto_select_certificate_for_urls()
.login_screen_auto_select_certificate_rules()));
//
// Network policies.
//
EncodeBoolean(&policy, key::kDeviceDataRoamingEnabled, kBool);
EXPECT_EQ(kBool, policy.data_roaming_enabled().data_roaming_enabled());
EncodeString(&policy, key::kDeviceOpenNetworkConfiguration, kString);
EXPECT_EQ(kString,
policy.open_network_configuration().open_network_configuration());
EncodeString(&policy, key::kDeviceHostnameTemplate, kString);
EXPECT_EQ(kString, policy.network_hostname().device_hostname_template());
// The encoder of this policy converts ints to
// DeviceKerberosEncryptionTypes::Types enums.
EncodeInteger(&policy, key::kDeviceKerberosEncryptionTypes,
em::DeviceKerberosEncryptionTypesProto::ENC_TYPES_ALL);
EXPECT_EQ(em::DeviceKerberosEncryptionTypesProto::ENC_TYPES_ALL,
policy.device_kerberos_encryption_types().types());
//
// Auto update policies.
//
EncodeString(&policy, key::kChromeOsReleaseChannel, kString);
EXPECT_EQ(kString, policy.release_channel().release_channel());
EncodeBoolean(&policy, key::kChromeOsReleaseChannelDelegated, kBool);
EXPECT_EQ(kBool, policy.release_channel().release_channel_delegated());
EncodeBoolean(&policy, key::kDeviceAutoUpdateDisabled, kBool);
EXPECT_EQ(kBool, policy.auto_update_settings().update_disabled());
EncodeString(&policy, key::kDeviceTargetVersionPrefix, kString);
EXPECT_EQ(kString, policy.auto_update_settings().target_version_prefix());
// The encoder of this policy converts ints to RollbackToTargetVersion enums.
EncodeInteger(&policy, key::kDeviceRollbackToTargetVersion,
em::AutoUpdateSettingsProto::ROLLBACK_WITH_FULL_POWERWASH);
EXPECT_EQ(em::AutoUpdateSettingsProto::ROLLBACK_WITH_FULL_POWERWASH,
policy.auto_update_settings().rollback_to_target_version());
EncodeInteger(&policy, key::kDeviceRollbackAllowedMilestones, kInt);
EXPECT_EQ(kInt, policy.auto_update_settings().rollback_allowed_milestones());
EncodeInteger(&policy, key::kDeviceUpdateScatterFactor, kInt);
EXPECT_EQ(kInt, policy.auto_update_settings().scatter_factor_in_seconds());
// The encoder of this policy converts connection type strings to enums.
std::vector<std::string> str_types;
std::vector<int> enum_types;
for (size_t n = 0; n < kConnectionTypesSize; ++n) {
str_types.push_back(kConnectionTypes[n].first);
enum_types.push_back(kConnectionTypes[n].second);
}
EncodeStringList(&policy, key::kDeviceUpdateAllowedConnectionTypes,
str_types);
EXPECT_EQ(enum_types,
ToVector(policy.auto_update_settings().allowed_connection_types()));
EncodeBoolean(&policy, key::kDeviceUpdateHttpDownloadsEnabled, kBool);
EXPECT_EQ(kBool, policy.auto_update_settings().http_downloads_enabled());
EncodeBoolean(&policy, key::kRebootAfterUpdate, kBool);
EXPECT_EQ(kBool, policy.auto_update_settings().reboot_after_update());
EncodeBoolean(&policy, key::kDeviceAutoUpdateP2PEnabled, kBool);
EXPECT_EQ(kBool, policy.auto_update_settings().p2p_enabled());
EncodeString(&policy, key::kDeviceAutoUpdateTimeRestrictions, kString);
EXPECT_EQ(kString, policy.auto_update_settings().disallowed_time_intervals());
// key::kDeviceUpdateStagingPercentOfFleetPerWeek is an int list (which we
// don't support right now), but it's going to change to a string. Ignore for
// now.
MarkHandled(key::kDeviceUpdateStagingPercentOfFleetPerWeek);
//
// Accessibility policies.
//
EncodeBoolean(&policy, key::kDeviceLoginScreenDefaultLargeCursorEnabled,
kBool);
EXPECT_EQ(kBool, policy.accessibility_settings()
.login_screen_default_large_cursor_enabled());
EncodeBoolean(&policy, key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled,
kBool);
EXPECT_EQ(kBool, policy.accessibility_settings()
.login_screen_default_spoken_feedback_enabled());
EncodeBoolean(&policy, key::kDeviceLoginScreenDefaultHighContrastEnabled,
kBool);
EXPECT_EQ(kBool, policy.accessibility_settings()
.login_screen_default_high_contrast_enabled());
// The encoder of this policy converts ints to ScreenMagnifierType enums.
EncodeInteger(&policy, key::kDeviceLoginScreenDefaultScreenMagnifierType,
em::AccessibilitySettingsProto::SCREEN_MAGNIFIER_TYPE_FULL);
EXPECT_EQ(em::AccessibilitySettingsProto::SCREEN_MAGNIFIER_TYPE_FULL,
policy.accessibility_settings()
.login_screen_default_screen_magnifier_type());
EncodeBoolean(&policy, key::kDeviceLoginScreenDefaultVirtualKeyboardEnabled,
kBool);
EXPECT_EQ(kBool, policy.accessibility_settings()
.login_screen_default_virtual_keyboard_enabled());
//
// Generic policies.
//
EncodeInteger(&policy, key::kDevicePolicyRefreshRate, kInt);
EXPECT_EQ(kInt,
policy.device_policy_refresh_rate().device_policy_refresh_rate());
EncodeBoolean(&policy, key::kDeviceMetricsReportingEnabled, kBool);
EXPECT_EQ(kBool, policy.metrics_enabled().metrics_enabled());
EncodeString(&policy, key::kSystemTimezone, kString);
EXPECT_EQ(kString, policy.system_timezone().timezone());
// The encoder of this policy converts ints to AutomaticTimezoneDetectionType
// enums.
EncodeInteger(&policy, key::kSystemTimezoneAutomaticDetection,
em::SystemTimezoneProto::IP_ONLY);
EXPECT_EQ(em::SystemTimezoneProto::IP_ONLY,
policy.system_timezone().timezone_detection_type());
EncodeBoolean(&policy, key::kSystemUse24HourClock, kBool);
EXPECT_EQ(kBool, policy.use_24hour_clock().use_24hour_clock());
EncodeBoolean(&policy, key::kDeviceAllowRedeemChromeOsRegistrationOffers,
kBool);
EXPECT_EQ(kBool, policy.allow_redeem_offers().allow_redeem_offers());
EncodeString(&policy, key::kDeviceVariationsRestrictParameter, kString);
EXPECT_EQ(kString, policy.variations_parameter().parameter());
EncodeString(&policy, key::kDeviceLoginScreenPowerManagement, kString);
EXPECT_EQ(
kString,
policy.login_screen_power_management().login_screen_power_management());
EncodeBoolean(&policy, key::kDeviceBlockDevmode, kBool);
EXPECT_EQ(kBool, policy.system_settings().block_devmode());
// The encoder of this policy converts ints to Rotation enums.
EncodeInteger(&policy, key::kDisplayRotationDefault,
em::DisplayRotationDefaultProto::ROTATE_180);
EXPECT_EQ(em::DisplayRotationDefaultProto::ROTATE_180,
policy.display_rotation_default().display_rotation_default());
// The encoder of this policy converts a JSON string to separate values.
EncodeStringList(&policy, key::kUsbDetachableWhitelist,
{"{\"vendor_id\":123, \"product_id\":234}",
"{\"vendor_id\":345, \"product_id\":456}"});
const auto& whitelist_proto = policy.usb_detachable_whitelist();
EXPECT_EQ(123, whitelist_proto.id().Get(0).vendor_id());
EXPECT_EQ(234, whitelist_proto.id().Get(0).product_id());
EXPECT_EQ(345, whitelist_proto.id().Get(1).vendor_id());
EXPECT_EQ(456, whitelist_proto.id().Get(1).product_id());
EncodeBoolean(&policy, key::kDeviceQuirksDownloadEnabled, kBool);
EXPECT_EQ(kBool, policy.quirks_download_enabled().quirks_download_enabled());
EncodeString(&policy, key::kDeviceWallpaperImage, kString);
EXPECT_EQ(kString, policy.device_wallpaper_image().device_wallpaper_image());
EncodeString(&policy, key::kDeviceOffHours,
R"!!!(
{
"intervals":
[
{
"start": {
"day_of_week": "MONDAY",
"time": 12840000
},
"end": {
"day_of_week": "MONDAY",
"time": 21720000
}
},
{
"start": {
"day_of_week": "FRIDAY",
"time": 38640000
},
"end": {
"day_of_week": "FRIDAY",
"time": 57600000
}
}
],
"timezone": "GMT",
"ignored_policy_proto_tags": [3, 8]
})!!!");
const auto& device_off_hours_proto = policy.device_off_hours();
EXPECT_EQ(2, device_off_hours_proto.intervals_size());
{
const auto& interval1 = device_off_hours_proto.intervals().Get(0);
const auto& interval2 = device_off_hours_proto.intervals().Get(1);
EXPECT_EQ(em::WeeklyTimeProto::MONDAY, interval1.start().day_of_week());
EXPECT_EQ(em::WeeklyTimeProto::MONDAY, interval1.end().day_of_week());
EXPECT_EQ(12840000, interval1.start().time());
EXPECT_EQ(21720000, interval1.end().time());
EXPECT_EQ(em::WeeklyTimeProto::FRIDAY, interval2.start().day_of_week());
EXPECT_EQ(em::WeeklyTimeProto::FRIDAY, interval2.end().day_of_week());
EXPECT_EQ(38640000, interval2.start().time());
EXPECT_EQ(57600000, interval2.end().time());
}
EXPECT_EQ("GMT", device_off_hours_proto.timezone());
EXPECT_EQ(2, device_off_hours_proto.ignored_policy_proto_tags_size());
EXPECT_EQ(3, device_off_hours_proto.ignored_policy_proto_tags().Get(0));
EXPECT_EQ(8, device_off_hours_proto.ignored_policy_proto_tags().Get(1));
EncodeString(&policy, key::kCastReceiverName, kString);
EXPECT_EQ(kString, policy.cast_receiver_name().name());
// The encoder of this policy converts ints to AccessMode enums.
EncodeString(&policy, key::kDeviceNativePrinters, kString);
EXPECT_EQ(kString, policy.native_device_printers().external_policy());
EncodeInteger(&policy, key::kDeviceNativePrintersAccessMode,
em::DeviceNativePrintersAccessModeProto::ACCESS_MODE_WHITELIST);
EXPECT_EQ(em::DeviceNativePrintersAccessModeProto::ACCESS_MODE_WHITELIST,
policy.native_device_printers_access_mode().access_mode());
EncodeStringList(&policy, key::kDeviceNativePrintersWhitelist, kStringList);
EXPECT_EQ(kStringList,
ToVector(policy.native_device_printers_whitelist().whitelist()));
EncodeStringList(&policy, key::kDeviceNativePrintersBlacklist, kStringList);
EXPECT_EQ(kStringList,
ToVector(policy.native_device_printers_blacklist().blacklist()));
EncodeString(&policy, key::kTPMFirmwareUpdateSettings,
"{\"allow-user-initiated-powerwash\":true,"
" \"allow-user-initiated-preserve-device-state\":true}");
EXPECT_EQ(
true,
policy.tpm_firmware_update_settings().allow_user_initiated_powerwash());
EXPECT_EQ(true, policy.tpm_firmware_update_settings()
.allow_user_initiated_preserve_device_state());
EncodeString(&policy, key::kMinimumRequiredChromeVersion, kString);
EXPECT_EQ(kString, policy.minimum_required_version().chrome_version());
EncodeBoolean(&policy, key::kUnaffiliatedArcAllowed, kBool);
EXPECT_EQ(kBool,
policy.unaffiliated_arc_allowed().unaffiliated_arc_allowed());
// The encoder of this policy converts ints to
// DeviceUserPolicyLoopbackProcessingModeProto::Mode enums.
EncodeInteger(
&policy, key::kDeviceUserPolicyLoopbackProcessingMode,
em::DeviceUserPolicyLoopbackProcessingModeProto::USER_POLICY_MODE_MERGE);
EXPECT_EQ(
em::DeviceUserPolicyLoopbackProcessingModeProto::USER_POLICY_MODE_MERGE,
policy.device_user_policy_loopback_processing_mode().mode());
EncodeString(&policy, key::kDeviceLoginScreenIsolateOrigins, kString);
EXPECT_EQ(kString,
policy.device_login_screen_isolate_origins().isolate_origins());
EncodeBoolean(&policy, key::kDeviceLoginScreenSitePerProcess, kBool);
EXPECT_EQ(kBool,
policy.device_login_screen_site_per_process().site_per_process());
EncodeBoolean(&policy, key::kVirtualMachinesAllowed, kBool);
EXPECT_EQ(kBool,
policy.virtual_machines_allowed().virtual_machines_allowed());
EncodeInteger(&policy, key::kDeviceMachinePasswordChangeRate, kInt);
EXPECT_EQ(kInt, policy.device_machine_password_change_rate().rate_days());
// The encoder of this policy converts ints to
// SamlLoginAuthenticationTypeProto::Type enums.
EncodeInteger(&policy, key::kDeviceSamlLoginAuthenticationType,
em::SamlLoginAuthenticationTypeProto::TYPE_CLIENT_CERTIFICATE);
EXPECT_EQ(
em::SamlLoginAuthenticationTypeProto::TYPE_CLIENT_CERTIFICATE,
policy.saml_login_authentication_type().saml_login_authentication_type());
//
// Check whether all device policies have been handled.
//
std::vector<std::string> unhandled_policy_keys = GetUnhandledPolicyKeys();
EXPECT_TRUE(unhandled_policy_keys.empty())
<< "Unhandled policy detected.\n"
<< "Please handle the following policies in "
<< "device_policy_encoder.cc and device_policy_encoder_unittest.cc:\n"
<< " " << base::JoinString(unhandled_policy_keys, "\n ");
}
} // namespace policy