diff options
author | Sen Jiang <senj@google.com> | 2018-08-09 16:52:23 -0700 |
---|---|---|
committer | Sen Jiang <senj@google.com> | 2018-08-10 11:07:06 -0700 |
commit | 0fa01c38cc2beff8d7e11e4b512692ecdb640ca8 (patch) | |
tree | 279e9e692e3a7db704f65e6d3977e43e8e75b46a /policy | |
parent | b5f20f52ab0885f1676b1c2024df541b3e6cc5f5 (diff) | |
parent | 904c2c9cd8d5ff06783030fb27ee23dcff743035 (diff) | |
download | platform_external_libbrillo-0fa01c38cc2beff8d7e11e4b512692ecdb640ca8.tar.gz platform_external_libbrillo-0fa01c38cc2beff8d7e11e4b512692ecdb640ca8.tar.bz2 platform_external_libbrillo-0fa01c38cc2beff8d7e11e4b512692ecdb640ca8.zip |
Merge remote-tracking branch 'aosp/upstream-master' into aosp/master.android-o-mr1-iot-release-1.0.4
Merge Chromium ToT to AOSP:
git fetch aosp upstream-master
git merge -X patience aosp/upstream-master
Bug: 112326236
Test: libbrillo_test
Change-Id: I35fbbddad556b051ce12b9cdd95bb2afef3cf6af
Diffstat (limited to 'policy')
-rw-r--r-- | policy/device_policy.h | 77 | ||||
-rw-r--r-- | policy/device_policy_impl.cc | 283 | ||||
-rw-r--r-- | policy/device_policy_impl.h | 38 | ||||
-rw-r--r-- | policy/libpolicy.cc | 48 | ||||
-rw-r--r-- | policy/libpolicy.h | 16 | ||||
-rw-r--r-- | policy/mock_device_policy.h | 10 | ||||
-rw-r--r-- | policy/mock_libpolicy.h | 1 | ||||
-rw-r--r-- | policy/tests/device_policy_impl_unittest.cc | 250 | ||||
-rw-r--r-- | policy/tests/libpolicy_unittest.cc | 269 | ||||
-rw-r--r-- | policy/tests/policy_util_unittest.cc | 6 | ||||
-rw-r--r-- | policy/tests/resilient_policy_util_unittest.cc | 12 | ||||
-rw-r--r-- | policy/tests/whitelist/policy_all | bin | 929 -> 1203 bytes |
12 files changed, 879 insertions, 131 deletions
diff --git a/policy/device_policy.h b/policy/device_policy.h index 2a3cb4b..5913d8c 100644 --- a/policy/device_policy.h +++ b/policy/device_policy.h @@ -9,9 +9,11 @@ #include <set> #include <string> +#include <utility> #include <vector> #include <base/macros.h> +#include <base/time/time.h> #pragma GCC visibility push(default) @@ -35,10 +37,35 @@ class DevicePolicy { uint16_t product_id; }; + // Time interval represented by two |day_of_week| and |time| pairs. The start + // of the interval is inclusive and the end is exclusive. The time represented + // by those pairs will be interpreted to be in the local timezone. Because of + // this, there exists the possibility of intervals being repeated or skipped + // in a day with daylight savings transitions, this is expected behavior. + struct WeeklyTimeInterval { + // Value is from 1 to 7 (1 = Monday, 2 = Tuesday, etc.). All values outside + // this range are invalid and will be discarded. + int start_day_of_week; + // Time since the start of the day. This value will be interpreted to be in + // the system's current timezone when used for range checking. + base::TimeDelta start_time; + int end_day_of_week; + base::TimeDelta end_time; + }; + + // Identifies a <day, percentage> pair in a staging schedule. + struct DayPercentagePair { + bool operator==(const DayPercentagePair& other) const { + return days == other.days && percentage == other.percentage; + } + int days; + int percentage; + }; + DevicePolicy(); virtual ~DevicePolicy(); - // Load the signed policy off of disk into |policy_|. + // Load device policy off of disk into |policy_|. // Returns true unless there is a policy on disk and loading it fails. virtual bool LoadPolicy() = 0; @@ -90,7 +117,7 @@ class DevicePolicy { // Writes the value of the EphemeralUsersEnabled policy in // |ephemeral_users_enabled|. Returns true on success. virtual bool GetEphemeralUsersEnabled( - bool* ephemeral_users_enabled) const = 0; + bool* ephemeral_users_enabled) const = 0; // Writes the value of the release channel policy in |release_channel|. // Returns true on success. @@ -110,6 +137,18 @@ class DevicePolicy { virtual bool GetTargetVersionPrefix( std::string* target_version_prefix) const = 0; + // Writes the value of the rollback_to_target_version policy in + // |rollback_to_target_version|. |rollback_to_target_version| will be one of + // the values in AutoUpdateSettingsProto's RollbackToTargetVersion enum. + // Returns true on success. + virtual bool GetRollbackToTargetVersion( + int* rollback_to_target_version) const = 0; + + // Writes the value of the rollback_allowed_milestones policy in + // |rollback_allowed_milestones|. Returns true on success. + virtual bool GetRollbackAllowedMilestones( + int* rollback_allowed_milestones) const = 0; + // Writes the value of the scatter_factor_in_seconds policy in // |scatter_factor_in_seconds|. Returns true on success. virtual bool GetScatterFactorInSeconds( @@ -152,8 +191,38 @@ class DevicePolicy { // Writes the value of the kiosk app id into |app_id_out|. // Only succeeds if the device is in auto-launched kiosk mode. - virtual bool GetAutoLaunchedKioskAppId( - std::string* app_id_out) const = 0; + virtual bool GetAutoLaunchedKioskAppId(std::string* app_id_out) const = 0; + + // Returns true if the policy data indicates that the device is enterprise + // managed. Note that this potentially could be faked by an exploit, therefore + // InstallAttributesReader must be used when tamper-proof evidence of the + // management state is required. + virtual bool IsEnterpriseManaged() const = 0; + + // Writes the value of the DeviceSecondFactorAuthentication policy in + // |mode_out|. |mode_out| is one of the values from + // DeviceSecondFactorAuthenticationProto's U2fMode enum (e.g. DISABLED, + // U2F or U2F_EXTENDED). Returns true on success. + virtual bool GetSecondFactorAuthenticationMode(int* mode_out) const = 0; + + // Writes the valid time intervals to |intervals_out|. These + // intervals are taken from the disallowed time intervals field in the + // AutoUpdateSettingsProto. Returns true if the intervals in the proto are + // valid. + virtual bool GetDisallowedTimeIntervals( + std::vector<WeeklyTimeInterval>* intervals_out) const = 0; + + // Writes the value of the DeviceUpdateStagingSchedule policy to + // |staging_schedule_out|. Returns true on success. + // The schedule is a list of <days, percentage> pairs. The percentages are + // expected to be mononically increasing in the range of [1, 100]. Similarly, + // days are expected to be monotonically increasing in the range [1, 28]. Each + // pair describes the |percentage| of the fleet that is expected to receive an + // update after |days| days after an update was discovered. e.g. [<4, 30>, <8, + // 100>] means that 30% of devices should be updated in the first 4 days, and + // then 100% should be updated after 8 days. + virtual bool GetDeviceUpdateStagingSchedule( + std::vector<DayPercentagePair>* staging_schedule_out) const = 0; private: // Verifies that the policy signature is correct. diff --git a/policy/device_policy_impl.cc b/policy/device_policy_impl.cc index ec52be6..76b82a1 100644 --- a/policy/device_policy_impl.cc +++ b/policy/device_policy_impl.cc @@ -4,26 +4,34 @@ #include "policy/device_policy_impl.h" +#include <algorithm> #include <memory> +#include <set> +#include <string> #include <base/containers/adapters.h> #include <base/files/file_util.h> +#include <base/json/json_reader.h> #include <base/logging.h> #include <base/macros.h> #include <base/memory/ptr_util.h> +#include <base/time/time.h> +#include <base/values.h> #include <openssl/evp.h> #include <openssl/x509.h> -#include <set> -#include <string> - #include "bindings/chrome_device_policy.pb.h" #include "bindings/device_management_backend.pb.h" #include "policy/policy_util.h" #include "policy/resilient_policy_util.h" +namespace em = enterprise_management; + namespace policy { +// Maximum value of RollbackAllowedMilestones policy. +const int kMaxRollbackAllowedMilestones = 4; + namespace { const char kPolicyPath[] = "/var/lib/whitelist/policy"; const char kPublicKeyPath[] = "/var/lib/whitelist/owner.key"; @@ -93,12 +101,76 @@ std::string DecodeConnectionType(int type) { return kConnectionTypes[type]; } +// TODO(adokar): change type to base::Optional<int> when available. +int ConvertDayOfWeekStringToInt(const std::string& day_of_week_str) { + if (day_of_week_str == "Sunday") return 0; + if (day_of_week_str == "Monday") return 1; + if (day_of_week_str == "Tuesday") return 2; + if (day_of_week_str == "Wednesday") return 3; + if (day_of_week_str == "Thursday") return 4; + if (day_of_week_str == "Friday") return 5; + if (day_of_week_str == "Saturday") return 6; + return -1; +} + +bool DecodeWeeklyTimeFromValue(const base::DictionaryValue& dict_value, + int* day_of_week_out, + base::TimeDelta* time_out) { + std::string day_of_week_str; + if (!dict_value.GetString("day_of_week", &day_of_week_str)) { + LOG(ERROR) << "Day of the week is absent."; + return false; + } + *day_of_week_out = ConvertDayOfWeekStringToInt(day_of_week_str); + if (*day_of_week_out == -1) { + LOG(ERROR) << "Undefined day of the week: " << day_of_week_str; + return false; + } + + int hours; + if (!dict_value.GetInteger("hours", &hours) || hours < 0 || hours > 23) { + LOG(ERROR) << "Hours are absent or are outside of the range [0, 24)."; + return false; + } + + int minutes; + if (!dict_value.GetInteger("minutes", &minutes) || minutes < 0 || + minutes > 59) { + LOG(ERROR) << "Minutes are absent or are outside the range [0, 60)"; + return false; + } + + *time_out = + base::TimeDelta::FromMinutes(minutes) + base::TimeDelta::FromHours(hours); + return true; +} + +std::unique_ptr<base::ListValue> DecodeListValueFromJSON( + const std::string& json_string) { + std::string error; + std::unique_ptr<base::Value> decoded_json = + base::JSONReader::ReadAndReturnError(json_string, + base::JSON_ALLOW_TRAILING_COMMAS, + nullptr, &error); + if (!decoded_json) { + LOG(ERROR) << "Invalid JSON string: " << error; + return nullptr; + } + + std::unique_ptr<base::ListValue> list_val = + base::ListValue::From(std::move(decoded_json)); + if (!list_val) { + LOG(ERROR) << "JSON string is not a list"; + return nullptr; + } + + return list_val; +} + } // namespace DevicePolicyImpl::DevicePolicyImpl() - : policy_path_(kPolicyPath), - keyfile_path_(kPublicKeyPath), - verify_root_ownership_(true) {} + : policy_path_(kPolicyPath), keyfile_path_(kPublicKeyPath) {} DevicePolicyImpl::~DevicePolicyImpl() {} @@ -136,8 +208,7 @@ bool DevicePolicyImpl::GetUserWhitelist( std::vector<std::string>* user_whitelist) const { if (!device_policy_.has_user_whitelist()) return false; - const enterprise_management::UserWhitelistProto& proto = - device_policy_.user_whitelist(); + const em::UserWhitelistProto& proto = device_policy_.user_whitelist(); user_whitelist->clear(); for (int i = 0; i < proto.user_whitelist_size(); i++) user_whitelist->push_back(proto.user_whitelist(i)); @@ -192,8 +263,7 @@ bool DevicePolicyImpl::GetReportVersionInfo(bool* report_version_info) const { if (!device_policy_.has_device_reporting()) return false; - const enterprise_management::DeviceReportingProto& proto = - device_policy_.device_reporting(); + const em::DeviceReportingProto& proto = device_policy_.device_reporting(); if (!proto.has_report_version_info()) return false; @@ -206,8 +276,7 @@ bool DevicePolicyImpl::GetReportActivityTimes( if (!device_policy_.has_device_reporting()) return false; - const enterprise_management::DeviceReportingProto& proto = - device_policy_.device_reporting(); + const em::DeviceReportingProto& proto = device_policy_.device_reporting(); if (!proto.has_report_activity_times()) return false; @@ -219,8 +288,7 @@ bool DevicePolicyImpl::GetReportBootMode(bool* report_boot_mode) const { if (!device_policy_.has_device_reporting()) return false; - const enterprise_management::DeviceReportingProto& proto = - device_policy_.device_reporting(); + const em::DeviceReportingProto& proto = device_policy_.device_reporting(); if (!proto.has_report_boot_mode()) return false; @@ -241,8 +309,7 @@ bool DevicePolicyImpl::GetReleaseChannel(std::string* release_channel) const { if (!device_policy_.has_release_channel()) return false; - const enterprise_management::ReleaseChannelProto& proto = - device_policy_.release_channel(); + const em::ReleaseChannelProto& proto = device_policy_.release_channel(); if (!proto.has_release_channel()) return false; @@ -255,8 +322,7 @@ bool DevicePolicyImpl::GetReleaseChannelDelegated( if (!device_policy_.has_release_channel()) return false; - const enterprise_management::ReleaseChannelProto& proto = - device_policy_.release_channel(); + const em::ReleaseChannelProto& proto = device_policy_.release_channel(); if (!proto.has_release_channel_delegated()) return false; @@ -268,7 +334,7 @@ bool DevicePolicyImpl::GetUpdateDisabled(bool* update_disabled) const { if (!device_policy_.has_auto_update_settings()) return false; - const enterprise_management::AutoUpdateSettingsProto& proto = + const em::AutoUpdateSettingsProto& proto = device_policy_.auto_update_settings(); if (!proto.has_update_disabled()) return false; @@ -282,7 +348,7 @@ bool DevicePolicyImpl::GetTargetVersionPrefix( if (!device_policy_.has_auto_update_settings()) return false; - const enterprise_management::AutoUpdateSettingsProto& proto = + const em::AutoUpdateSettingsProto& proto = device_policy_.auto_update_settings(); if (!proto.has_target_version_prefix()) return false; @@ -291,12 +357,58 @@ bool DevicePolicyImpl::GetTargetVersionPrefix( return true; } +bool DevicePolicyImpl::GetRollbackToTargetVersion( + int* rollback_to_target_version) const { + if (!device_policy_.has_auto_update_settings()) + return false; + + const em::AutoUpdateSettingsProto& proto = + device_policy_.auto_update_settings(); + if (!proto.has_rollback_to_target_version()) + return false; + + *rollback_to_target_version = proto.rollback_to_target_version(); + return true; +} + +bool DevicePolicyImpl::GetRollbackAllowedMilestones( + int* rollback_allowed_milestones) const { + // This policy can be only set for devices which are enterprise enrolled. + if (!install_attributes_reader_->IsLocked()) + return false; + if (install_attributes_reader_->GetAttribute( + InstallAttributesReader::kAttrMode) != + InstallAttributesReader::kDeviceModeEnterprise && + install_attributes_reader_->GetAttribute( + InstallAttributesReader::kAttrMode) != + InstallAttributesReader::kDeviceModeEnterpriseAD) + return false; + + if (device_policy_.has_auto_update_settings()) { + const em::AutoUpdateSettingsProto& proto = + device_policy_.auto_update_settings(); + if (proto.has_rollback_allowed_milestones()) { + // Policy is set, enforce minimum and maximum constraints. + *rollback_allowed_milestones = proto.rollback_allowed_milestones(); + if (*rollback_allowed_milestones < 0) + *rollback_allowed_milestones = 0; + if (*rollback_allowed_milestones > kMaxRollbackAllowedMilestones) + *rollback_allowed_milestones = kMaxRollbackAllowedMilestones; + return true; + } + } + // Policy is not present, use default for enterprise devices. + VLOG(1) << "RollbackAllowedMilestones policy is not set, using default 0."; + *rollback_allowed_milestones = 0; + return true; +} + bool DevicePolicyImpl::GetScatterFactorInSeconds( int64_t* scatter_factor_in_seconds) const { if (!device_policy_.has_auto_update_settings()) return false; - const enterprise_management::AutoUpdateSettingsProto& proto = + const em::AutoUpdateSettingsProto& proto = device_policy_.auto_update_settings(); if (!proto.has_scatter_factor_in_seconds()) return false; @@ -310,7 +422,7 @@ bool DevicePolicyImpl::GetAllowedConnectionTypesForUpdate( if (!device_policy_.has_auto_update_settings()) return false; - const enterprise_management::AutoUpdateSettingsProto& proto = + const em::AutoUpdateSettingsProto& proto = device_policy_.auto_update_settings(); if (proto.allowed_connection_types_size() <= 0) return false; @@ -328,7 +440,7 @@ bool DevicePolicyImpl::GetOpenNetworkConfiguration( if (!device_policy_.has_open_network_configuration()) return false; - const enterprise_management::DeviceOpenNetworkConfigurationProto& proto = + const em::DeviceOpenNetworkConfigurationProto& proto = device_policy_.open_network_configuration(); if (!proto.has_open_network_configuration()) return false; @@ -338,11 +450,11 @@ bool DevicePolicyImpl::GetOpenNetworkConfiguration( } bool DevicePolicyImpl::GetOwner(std::string* owner) const { - // The device is enterprise enrolled iff a request token exists. - if (policy_data_.has_request_token()) { + if (IsEnterpriseManaged()) { *owner = ""; return true; } + if (!policy_data_.has_username()) return false; *owner = policy_data_.username(); @@ -354,7 +466,7 @@ bool DevicePolicyImpl::GetHttpDownloadsEnabled( if (!device_policy_.has_auto_update_settings()) return false; - const enterprise_management::AutoUpdateSettingsProto& proto = + const em::AutoUpdateSettingsProto& proto = device_policy_.auto_update_settings(); if (!proto.has_http_downloads_enabled()) @@ -368,7 +480,7 @@ bool DevicePolicyImpl::GetAuP2PEnabled(bool* au_p2p_enabled) const { if (!device_policy_.has_auto_update_settings()) return false; - const enterprise_management::AutoUpdateSettingsProto& proto = + const em::AutoUpdateSettingsProto& proto = device_policy_.auto_update_settings(); if (!proto.has_p2p_enabled()) @@ -383,7 +495,7 @@ bool DevicePolicyImpl::GetAllowKioskAppControlChromeVersion( if (!device_policy_.has_allow_kiosk_app_control_chrome_version()) return false; - const enterprise_management::AllowKioskAppControlChromeVersionProto& proto = + const em::AllowKioskAppControlChromeVersionProto& proto = device_policy_.allow_kiosk_app_control_chrome_version(); if (!proto.has_allow_kiosk_app_control_chrome_version()) @@ -398,11 +510,11 @@ bool DevicePolicyImpl::GetUsbDetachableWhitelist( std::vector<UsbDeviceId>* usb_whitelist) const { if (!device_policy_.has_usb_detachable_whitelist()) return false; - const enterprise_management::UsbDetachableWhitelistProto& proto = + const em::UsbDetachableWhitelistProto& proto = device_policy_.usb_detachable_whitelist(); usb_whitelist->clear(); for (int i = 0; i < proto.id_size(); i++) { - const ::enterprise_management::UsbDeviceIdProto& id = proto.id(i); + const em::UsbDeviceIdProto& id = proto.id(i); UsbDeviceId dev_id; dev_id.vendor_id = id.has_vendor_id() ? id.vendor_id() : 0; dev_id.product_id = id.has_product_id() ? id.product_id() : 0; @@ -411,12 +523,46 @@ bool DevicePolicyImpl::GetUsbDetachableWhitelist( return true; } +bool DevicePolicyImpl::GetDeviceUpdateStagingSchedule( + std::vector<DayPercentagePair>* staging_schedule_out) const { + staging_schedule_out->clear(); + + if (!device_policy_.has_auto_update_settings()) + return false; + + const em::AutoUpdateSettingsProto &proto = + device_policy_.auto_update_settings(); + + if (!proto.has_staging_schedule()) + return false; + + std::unique_ptr<base::ListValue> list_val = + DecodeListValueFromJSON(proto.staging_schedule()); + if (!list_val) + return false; + + for (base::Value* const& pair_value : *list_val) { + base::DictionaryValue* day_percentage_pair; + if (!pair_value->GetAsDictionary(&day_percentage_pair)) + return false; + int days, percentage; + if (!day_percentage_pair->GetInteger("days", &days) || + !day_percentage_pair->GetInteger("percentage", &percentage)) + return false; + // Limit the percentage to [0, 100] and days to [1, 28]; + staging_schedule_out->push_back({std::max(std::min(days, 28), 1), + std::max(std::min(percentage, 100), 0)}); + } + + return true; +} + bool DevicePolicyImpl::GetAutoLaunchedKioskAppId( std::string* app_id_out) const { if (!device_policy_.has_device_local_accounts()) return false; - const enterprise_management::DeviceLocalAccountsProto& local_accounts = + const em::DeviceLocalAccountsProto& local_accounts = device_policy_.device_local_accounts(); // For auto-launched kiosk apps, the delay needs to be 0. @@ -424,7 +570,7 @@ bool DevicePolicyImpl::GetAutoLaunchedKioskAppId( local_accounts.auto_login_delay() != 0) return false; - for (const enterprise_management::DeviceLocalAccountInfoProto& account : + for (const em::DeviceLocalAccountInfoProto& account : local_accounts.account()) { // If this isn't an auto-login account, move to the next one. if (account.account_id() != local_accounts.auto_login_id()) @@ -433,8 +579,7 @@ bool DevicePolicyImpl::GetAutoLaunchedKioskAppId( // If the auto-launched account is not a kiosk app, bail out, we aren't // running in auto-launched kiosk mode. if (account.type() != - enterprise_management::DeviceLocalAccountInfoProto:: - ACCOUNT_TYPE_KIOSK_APP) { + em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_KIOSK_APP) { return false; } @@ -446,6 +591,74 @@ bool DevicePolicyImpl::GetAutoLaunchedKioskAppId( return false; } +bool DevicePolicyImpl::IsEnterpriseManaged() const { + if (policy_data_.has_management_mode()) + return policy_data_.management_mode() == em::PolicyData::ENTERPRISE_MANAGED; + // Fall back to checking the request token, see management_mode documentation + // in device_management_backend.proto. + return policy_data_.has_request_token(); +} + +bool DevicePolicyImpl::GetSecondFactorAuthenticationMode(int* mode_out) const { + if (!device_policy_.has_device_second_factor_authentication()) + return false; + + const em::DeviceSecondFactorAuthenticationProto& proto = + device_policy_.device_second_factor_authentication(); + + if (!proto.has_mode()) + return false; + + *mode_out = proto.mode(); + return true; +} + +bool DevicePolicyImpl::GetDisallowedTimeIntervals( + std::vector<WeeklyTimeInterval>* intervals_out) const { + intervals_out->clear(); + + if (!device_policy_.has_auto_update_settings()) { + return false; + } + + const em::AutoUpdateSettingsProto& proto = + device_policy_.auto_update_settings(); + + if (!proto.has_disallowed_time_intervals()) { + return false; + } + + std::unique_ptr<base::ListValue> list_val = + DecodeListValueFromJSON(proto.disallowed_time_intervals()); + if (!list_val) + return false; + + for (base::Value* const& interval_value : *list_val) { + base::DictionaryValue* interval_dict; + if (!interval_value->GetAsDictionary(&interval_dict)) { + LOG(ERROR) << "Invalid JSON string given. Interval is not a dict."; + return false; + } + base::DictionaryValue* start; + base::DictionaryValue* end; + if (!interval_dict->GetDictionary("start", &start) || + !interval_dict->GetDictionary("end", &end)) { + LOG(ERROR) << "Interval is missing start/end."; + return false; + } + WeeklyTimeInterval weekly_interval; + if (!DecodeWeeklyTimeFromValue(*start, &weekly_interval.start_day_of_week, + &weekly_interval.start_time) || + !DecodeWeeklyTimeFromValue(*end, &weekly_interval.end_day_of_week, + &weekly_interval.end_time)) { + return false; + } + + intervals_out->push_back(weekly_interval); + } + return true; +} + bool DevicePolicyImpl::VerifyPolicyFile(const base::FilePath& policy_path) { if (!verify_root_ownership_) { return true; @@ -506,7 +719,7 @@ bool DevicePolicyImpl::LoadPolicyFromFile(const base::FilePath& policy_path) { return false; } - bool verify_policy = true; + bool verify_policy = verify_policy_; if (!install_attributes_reader_) { install_attributes_reader_ = std::make_unique<InstallAttributesReader>(); } diff --git a/policy/device_policy_impl.h b/policy/device_policy_impl.h index b178e28..6891312 100644 --- a/policy/device_policy_impl.h +++ b/policy/device_policy_impl.h @@ -5,8 +5,10 @@ #ifndef LIBBRILLO_POLICY_DEVICE_POLICY_IMPL_H_ #define LIBBRILLO_POLICY_DEVICE_POLICY_IMPL_H_ +#include <memory> #include <set> #include <string> +#include <utility> #include <vector> #include <base/files/file_path.h> @@ -14,6 +16,7 @@ #include "bindings/chrome_device_policy.pb.h" #include "bindings/device_management_backend.pb.h" +#include "install_attributes/libinstallattributes.h" #include "policy/device_policy.h" #pragma GCC visibility push(default) @@ -30,6 +33,12 @@ class DevicePolicyImpl : public DevicePolicy { DevicePolicyImpl(); ~DevicePolicyImpl() override; + const enterprise_management::ChromeDeviceSettingsProto& get_device_policy() + const { + return device_policy_; + } + + // DevicePolicy overrides: bool LoadPolicy() override; bool GetPolicyRefreshRate(int* rate) const override; bool GetUserWhitelist( @@ -50,6 +59,10 @@ class DevicePolicyImpl : public DevicePolicy { bool GetUpdateDisabled(bool* update_disabled) const override; bool GetTargetVersionPrefix( std::string* target_version_prefix) const override; + bool GetRollbackToTargetVersion( + int* rollback_to_target_version) const override; + bool GetRollbackAllowedMilestones( + int* rollback_allowed_milestones) const override; bool GetScatterFactorInSeconds( int64_t* scatter_factor_in_seconds) const override; bool GetAllowedConnectionTypesForUpdate( @@ -64,6 +77,12 @@ class DevicePolicyImpl : public DevicePolicy { bool GetUsbDetachableWhitelist( std::vector<UsbDeviceId>* usb_whitelist) const override; bool GetAutoLaunchedKioskAppId(std::string* app_id_out) const override; + bool IsEnterpriseManaged() const override; + bool GetSecondFactorAuthenticationMode(int* mode_out) const override; + bool GetDisallowedTimeIntervals( + std::vector<WeeklyTimeInterval>* intervals_out) const override; + bool GetDeviceUpdateStagingSchedule( + std::vector<DayPercentagePair> *staging_schedule_out) const override; // Methods that can be used only for testing. void set_policy_data_for_testing( @@ -77,12 +96,17 @@ class DevicePolicyImpl : public DevicePolicy { std::unique_ptr<InstallAttributesReader> install_attributes_reader) { install_attributes_reader_ = std::move(install_attributes_reader); } + void set_policy_for_testing( + const enterprise_management::ChromeDeviceSettingsProto& device_policy) { + device_policy_ = device_policy; + } void set_policy_path_for_testing(const base::FilePath& policy_path) { policy_path_ = policy_path; } void set_key_file_path_for_testing(const base::FilePath& keyfile_path) { keyfile_path_ = keyfile_path; } + void set_verify_policy_for_testing(bool value) { verify_policy_ = value; } private: // Verifies that both the policy file and the signature file exist and are @@ -93,11 +117,14 @@ class DevicePolicyImpl : public DevicePolicy { // Verifies that the policy signature is correct. bool VerifyPolicySignature() override; - // Loads the signed policy off of disk from |policy_path| into |policy_|. - // Returns true if the |policy_path| is present on disk and loading it is - // successful. + // Loads policy off of disk from |policy_path| into |policy_|. Returns true if + // the |policy_path| is present on disk and loading it is successful. bool LoadPolicyFromFile(const base::FilePath& policy_path); + // Path of the default policy file, e.g. /path/to/policy. In order to make + // device policy more resilient against broken files, this class also tries to + // load indexed paths /path/to/policy.1, /path/to/policy.2 etc., see + // resilient_policy_utils.h. base::FilePath policy_path_; base::FilePath keyfile_path_; std::unique_ptr<InstallAttributesReader> install_attributes_reader_; @@ -107,7 +134,10 @@ class DevicePolicyImpl : public DevicePolicy { // If true, verify that policy files are owned by root. True in production // but can be set to false by tests. - bool verify_root_ownership_; + bool verify_root_ownership_ = true; + // If false, all types of verification are disabled. True in production + // but can be set to false by tests. + bool verify_policy_ = true; DISALLOW_COPY_AND_ASSIGN(DevicePolicyImpl); }; diff --git a/policy/libpolicy.cc b/policy/libpolicy.cc index 99fa46d..a0b7640 100644 --- a/policy/libpolicy.cc +++ b/policy/libpolicy.cc @@ -4,6 +4,8 @@ #include "policy/libpolicy.h" +#include <memory> + #include <base/logging.h> #include "policy/device_policy.h" @@ -13,17 +15,23 @@ namespace policy { -PolicyProvider::PolicyProvider() - : device_policy_(nullptr), - device_policy_is_loaded_(false) { +PolicyProvider::PolicyProvider() { #ifndef __ANDROID__ - device_policy_.reset(new DevicePolicyImpl()); + device_policy_ = std::make_unique<DevicePolicyImpl>(); + install_attributes_reader_ = std::make_unique<InstallAttributesReader>(); #endif } PolicyProvider::PolicyProvider(std::unique_ptr<DevicePolicy> device_policy) : device_policy_(std::move(device_policy)), - device_policy_is_loaded_(true) {} +#ifdef __ANDROID__ + device_policy_is_loaded_(true) { +} +#else + device_policy_is_loaded_(true), + install_attributes_reader_(std::make_unique<InstallAttributesReader>()) { +} +#endif // __ANDROID__ PolicyProvider::~PolicyProvider() {} @@ -42,10 +50,34 @@ bool PolicyProvider::device_policy_is_loaded() const { } const DevicePolicy& PolicyProvider::GetDevicePolicy() const { - if (!device_policy_is_loaded_) - DCHECK("Trying to get policy data but policy was not loaded!"); - + DCHECK(device_policy_is_loaded_) + << "Trying to get policy data but policy was not loaded!"; return *device_policy_; } +bool PolicyProvider::IsConsumerDevice() const { +#ifdef __ANDROID__ + return true; +#else + if (!install_attributes_reader_->IsLocked()) + return false; + + const std::string& device_mode = install_attributes_reader_->GetAttribute( + InstallAttributesReader::kAttrMode); + return device_mode != InstallAttributesReader::kDeviceModeEnterprise && + device_mode != InstallAttributesReader::kDeviceModeEnterpriseAD; +#endif // __ANDROID__ +} + +void PolicyProvider::SetDevicePolicyForTesting( + std::unique_ptr<DevicePolicy> device_policy) { + device_policy_ = std::move(device_policy); + device_policy_is_loaded_ = true; +} + +void PolicyProvider::SetInstallAttributesReaderForTesting( + std::unique_ptr<InstallAttributesReader> install_attributes_reader) { + install_attributes_reader_ = std::move(install_attributes_reader); +} + } // namespace policy diff --git a/policy/libpolicy.h b/policy/libpolicy.h index 1a411cf..5e87f58 100644 --- a/policy/libpolicy.h +++ b/policy/libpolicy.h @@ -10,6 +10,8 @@ #include <base/macros.h> +#include "install_attributes/libinstallattributes.h" + #pragma GCC visibility push(default) namespace policy { @@ -22,6 +24,7 @@ class DevicePolicy; // its signature. class PolicyProvider { public: + // The default constructor does not load policy. PolicyProvider(); virtual ~PolicyProvider(); @@ -37,9 +40,20 @@ class PolicyProvider { // Returns a value from the device policy cache. virtual const DevicePolicy& GetDevicePolicy() const; + // Returns true if the device is not an enterprise enrolled device, so it + // won't have device policy before the next powerwash. Returns false if device + // is still in OOBE (so device mode is not determined yet). + virtual bool IsConsumerDevice() const; + + void SetDevicePolicyForTesting( + std::unique_ptr<DevicePolicy> device_policy); + void SetInstallAttributesReaderForTesting( + std::unique_ptr<InstallAttributesReader> install_attributes_reader); + private: std::unique_ptr<DevicePolicy> device_policy_; - bool device_policy_is_loaded_; + bool device_policy_is_loaded_ = false; + std::unique_ptr<InstallAttributesReader> install_attributes_reader_; DISALLOW_COPY_AND_ASSIGN(PolicyProvider); }; diff --git a/policy/mock_device_policy.h b/policy/mock_device_policy.h index 23e8147..90470e2 100644 --- a/policy/mock_device_policy.h +++ b/policy/mock_device_policy.h @@ -7,6 +7,7 @@ #include <set> #include <string> +#include <utility> #include <vector> #include <gmock/gmock.h> @@ -82,6 +83,8 @@ class MockDevicePolicy : public DevicePolicy { MOCK_CONST_METHOD1(GetUpdateDisabled, bool(bool*)); // NOLINT(readability/function) MOCK_CONST_METHOD1(GetTargetVersionPrefix, bool(std::string*)); + MOCK_CONST_METHOD1(GetRollbackToTargetVersion, bool(int*)); + MOCK_CONST_METHOD1(GetRollbackAllowedMilestones, bool(int*)); MOCK_CONST_METHOD1(GetScatterFactorInSeconds, bool(int64_t*)); // NOLINT(readability/function) MOCK_CONST_METHOD1(GetAllowedConnectionTypesForUpdate, @@ -97,7 +100,12 @@ class MockDevicePolicy : public DevicePolicy { MOCK_CONST_METHOD1(GetUsbDetachableWhitelist, bool(std::vector<DevicePolicy::UsbDeviceId>*)); MOCK_CONST_METHOD1(GetAutoLaunchedKioskAppId, bool(std::string*)); - + MOCK_CONST_METHOD0(IsEnterpriseManaged, bool()); + MOCK_CONST_METHOD1(GetSecondFactorAuthenticationMode, bool(int*)); + MOCK_CONST_METHOD1(GetDisallowedTimeIntervals, + bool(std::vector<WeeklyTimeInterval>*)); + MOCK_CONST_METHOD1(GetDeviceUpdateStagingSchedule, + bool(std::vector<DayPercentagePair>*)); MOCK_METHOD0(VerifyPolicyFiles, bool(void)); MOCK_METHOD0(VerifyPolicySignature, bool(void)); }; diff --git a/policy/mock_libpolicy.h b/policy/mock_libpolicy.h index acb9b8b..a0f6920 100644 --- a/policy/mock_libpolicy.h +++ b/policy/mock_libpolicy.h @@ -23,6 +23,7 @@ class MockPolicyProvider : public PolicyProvider { MOCK_METHOD0(Reload, bool(void)); MOCK_CONST_METHOD0(device_policy_is_loaded, bool(void)); MOCK_CONST_METHOD0(GetDevicePolicy, const DevicePolicy&(void)); + MOCK_CONST_METHOD0(IsConsumerDevice, bool(void)); private: DISALLOW_COPY_AND_ASSIGN(MockPolicyProvider); diff --git a/policy/tests/device_policy_impl_unittest.cc b/policy/tests/device_policy_impl_unittest.cc new file mode 100644 index 0000000..37c3916 --- /dev/null +++ b/policy/tests/device_policy_impl_unittest.cc @@ -0,0 +1,250 @@ +// 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 <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "policy/device_policy_impl.h" + +#include "bindings/chrome_device_policy.pb.h" +#include "install_attributes/mock_install_attributes_reader.h" + +namespace em = enterprise_management; + +using testing::ElementsAre; + +namespace policy { + +class DevicePolicyImplTest : public testing::Test, public DevicePolicyImpl { + protected: + void InitializePolicy(const char* device_mode, + const em::ChromeDeviceSettingsProto& proto) { + device_policy_.set_policy_for_testing(proto); + device_policy_.set_install_attributes_for_testing( + std::make_unique<MockInstallAttributesReader>( + device_mode, true /* initialized */)); + } + + DevicePolicyImpl device_policy_; +}; + +// Enterprise managed. +TEST_F(DevicePolicyImplTest, GetOwner_Managed) { + em::PolicyData policy_data; + policy_data.set_username("user@example.com"); + policy_data.set_management_mode(em::PolicyData::ENTERPRISE_MANAGED); + device_policy_.set_policy_data_for_testing(policy_data); + + std::string owner("something"); + EXPECT_TRUE(device_policy_.GetOwner(&owner)); + EXPECT_TRUE(owner.empty()); +} + +// Consumer owned. +TEST_F(DevicePolicyImplTest, GetOwner_Consumer) { + em::PolicyData policy_data; + policy_data.set_username("user@example.com"); + policy_data.set_management_mode(em::PolicyData::LOCAL_OWNER); + policy_data.set_request_token("codepath-must-ignore-dmtoken"); + device_policy_.set_policy_data_for_testing(policy_data); + + std::string owner; + EXPECT_TRUE(device_policy_.GetOwner(&owner)); + EXPECT_EQ("user@example.com", owner); +} + +// Consumer owned, username is missing. +TEST_F(DevicePolicyImplTest, GetOwner_ConsumerMissingUsername) { + em::PolicyData policy_data; + device_policy_.set_policy_data_for_testing(policy_data); + + std::string owner("something"); + EXPECT_FALSE(device_policy_.GetOwner(&owner)); + EXPECT_EQ("something", owner); +} + +// Enterprise managed, denoted by management_mode. +TEST_F(DevicePolicyImplTest, IsEnterpriseManaged_ManagementModeManaged) { + em::PolicyData policy_data; + policy_data.set_management_mode(em::PolicyData::ENTERPRISE_MANAGED); + device_policy_.set_policy_data_for_testing(policy_data); + + EXPECT_TRUE(device_policy_.IsEnterpriseManaged()); +} + +// Enterprise managed, fallback to DM token. +TEST_F(DevicePolicyImplTest, IsEnterpriseManaged_DMTokenManaged) { + em::PolicyData policy_data; + policy_data.set_request_token("abc"); + device_policy_.set_policy_data_for_testing(policy_data); + + EXPECT_TRUE(device_policy_.IsEnterpriseManaged()); +} + +// Consumer owned, denoted by management_mode. +TEST_F(DevicePolicyImplTest, IsEnterpriseManaged_ManagementModeConsumer) { + em::PolicyData policy_data; + policy_data.set_management_mode(em::PolicyData::LOCAL_OWNER); + policy_data.set_request_token("codepath-must-ignore-dmtoken"); + device_policy_.set_policy_data_for_testing(policy_data); + + EXPECT_FALSE(device_policy_.IsEnterpriseManaged()); +} + +// Consumer owned, fallback to interpreting absence of DM token. +TEST_F(DevicePolicyImplTest, IsEnterpriseManaged_DMTokenConsumer) { + em::PolicyData policy_data; + device_policy_.set_policy_data_for_testing(policy_data); + + EXPECT_FALSE(device_policy_.IsEnterpriseManaged()); +} + +// RollbackAllowedMilestones is not set. +TEST_F(DevicePolicyImplTest, GetRollbackAllowedMilestones_NotSet) { + device_policy_.set_install_attributes_for_testing( + std::make_unique<MockInstallAttributesReader>( + InstallAttributesReader::kDeviceModeEnterprise, true)); + + int value = -1; + ASSERT_TRUE(device_policy_.GetRollbackAllowedMilestones(&value)); + EXPECT_EQ(0, value); +} + +// RollbackAllowedMilestones is set to a valid value. +TEST_F(DevicePolicyImplTest, GetRollbackAllowedMilestones_Set) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto* auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_rollback_allowed_milestones(3); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterprise, + device_policy_proto); + + int value = -1; + ASSERT_TRUE(device_policy_.GetRollbackAllowedMilestones(&value)); + EXPECT_EQ(3, value); +} + +// RollbackAllowedMilestones is set to a valid value, using AD. +TEST_F(DevicePolicyImplTest, GetRollbackAllowedMilestones_SetAD) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto* auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_rollback_allowed_milestones(3); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterpriseAD, + device_policy_proto); + int value = -1; + ASSERT_TRUE(device_policy_.GetRollbackAllowedMilestones(&value)); + EXPECT_EQ(3, value); +} + +// RollbackAllowedMilestones is set to a valid value, but it's not an enterprise +// device. +TEST_F(DevicePolicyImplTest, GetRollbackAllowedMilestones_SetConsumer) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto* auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_rollback_allowed_milestones(3); + InitializePolicy(InstallAttributesReader::kDeviceModeConsumer, + device_policy_proto); + + int value = -1; + ASSERT_FALSE(device_policy_.GetRollbackAllowedMilestones(&value)); +} + +// RollbackAllowedMilestones is set to an invalid value. +TEST_F(DevicePolicyImplTest, GetRollbackAllowedMilestones_SetTooLarge) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto* auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_rollback_allowed_milestones(10); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterprise, + device_policy_proto); + + int value = -1; + ASSERT_TRUE(device_policy_.GetRollbackAllowedMilestones(&value)); + EXPECT_EQ(4, value); +} + +// RollbackAllowedMilestones is set to an invalid value. +TEST_F(DevicePolicyImplTest, GetRollbackAllowedMilestones_SetTooSmall) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto* auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_rollback_allowed_milestones(-1); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterprise, + device_policy_proto); + + int value = -1; + ASSERT_TRUE(device_policy_.GetRollbackAllowedMilestones(&value)); + EXPECT_EQ(0, value); +} + +// Update staging schedule has no values +TEST_F(DevicePolicyImplTest, GetDeviceUpdateStagingSchedule_NoValues) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto *auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_staging_schedule("[]"); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterprise, + device_policy_proto); + + std::vector<DayPercentagePair> staging_schedule; + ASSERT_TRUE(device_policy_.GetDeviceUpdateStagingSchedule(&staging_schedule)); + EXPECT_EQ(0, staging_schedule.size()); +} + +// Update staging schedule has valid values +TEST_F(DevicePolicyImplTest, GetDeviceUpdateStagingSchedule_Valid) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto *auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_staging_schedule( + "[{\"days\": 4, \"percentage\": 40}, {\"days\": 10, \"percentage\": " + "100}]"); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterprise, + device_policy_proto); + + std::vector<DayPercentagePair> staging_schedule; + ASSERT_TRUE(device_policy_.GetDeviceUpdateStagingSchedule(&staging_schedule)); + EXPECT_THAT(staging_schedule, ElementsAre(DayPercentagePair{4, 40}, + DayPercentagePair{10, 100})); +} + +// Update staging schedule has valid values, set using AD. +TEST_F(DevicePolicyImplTest, GetDeviceUpdateStagingSchedule_Valid_AD) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto *auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_staging_schedule( + "[{\"days\": 4, \"percentage\": 40}, {\"days\": 10, \"percentage\": " + "100}]"); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterpriseAD, + device_policy_proto); + + std::vector<DayPercentagePair> staging_schedule; + ASSERT_TRUE(device_policy_.GetDeviceUpdateStagingSchedule(&staging_schedule)); + EXPECT_THAT(staging_schedule, ElementsAre(DayPercentagePair{4, 40}, + DayPercentagePair{10, 100})); +} + +// Update staging schedule has values with values set larger than the max +// allowed days/percentage and smaller than the min allowed days/percentage. +TEST_F(DevicePolicyImplTest, + GetDeviceUpdateStagingSchedule_SetOutsideAllowable) { + em::ChromeDeviceSettingsProto device_policy_proto; + em::AutoUpdateSettingsProto *auto_update_settings = + device_policy_proto.mutable_auto_update_settings(); + auto_update_settings->set_staging_schedule( + "[{\"days\": -1, \"percentage\": -10}, {\"days\": 30, \"percentage\": " + "110}]"); + InitializePolicy(InstallAttributesReader::kDeviceModeEnterprise, + device_policy_proto); + + std::vector<DayPercentagePair> staging_schedule; + ASSERT_TRUE(device_policy_.GetDeviceUpdateStagingSchedule(&staging_schedule)); + EXPECT_THAT(staging_schedule, ElementsAre(DayPercentagePair{1, 0}, + DayPercentagePair{28, 100})); +} + +} // namespace policy diff --git a/policy/tests/libpolicy_unittest.cc b/policy/tests/libpolicy_unittest.cc index bd2b49a..aaf497c 100644 --- a/policy/tests/libpolicy_unittest.cc +++ b/policy/tests/libpolicy_unittest.cc @@ -4,6 +4,9 @@ #include "policy/libpolicy.h" +#include <memory> +#include <utility> + #include <openssl/err.h> #include <openssl/ssl.h> @@ -11,6 +14,8 @@ #include <base/logging.h> #include <gtest/gtest.h> +#include "bindings/chrome_device_policy.pb.h" +#include "install_attributes/mock_install_attributes_reader.h" #include "policy/device_policy_impl.h" namespace policy { @@ -18,6 +23,7 @@ namespace policy { static const char kPolicyFileAllSet[] = "policy/tests/whitelist/policy_all"; static const char kPolicyFileNoneSet[] = "policy/tests/whitelist/policy_none"; static const char kKeyFile[] = "policy/tests/whitelist/owner.key"; +static const char kNonExistingFile[] = "file-does-not-exist"; // Creates the DevicePolicyImpl with given parameters for test. std::unique_ptr<DevicePolicyImpl> CreateDevicePolicyImpl( @@ -40,10 +46,11 @@ std::unique_ptr<DevicePolicyImpl> CreateDevicePolicyImpl( TEST(PolicyTest, DevicePolicyAllSetTest) { base::FilePath policy_file(kPolicyFileAllSet); base::FilePath key_file(kKeyFile); - PolicyProvider provider( - CreateDevicePolicyImpl(std::make_unique<MockInstallAttributesReader>( - cryptohome::SerializedInstallAttributes()), - policy_file, key_file, false)); + PolicyProvider provider; + provider.SetDevicePolicyForTesting(CreateDevicePolicyImpl( + std::make_unique<MockInstallAttributesReader>( + InstallAttributesReader::kDeviceModeEnterprise, true), + policy_file, key_file, false)); provider.Reload(); // Ensure we successfully loaded the device policy file. @@ -54,111 +61,143 @@ TEST(PolicyTest, DevicePolicyAllSetTest) { // Check that we can read out all fields of the sample protobuf. int int_value = -1; ASSERT_TRUE(policy.GetPolicyRefreshRate(&int_value)); - ASSERT_EQ(100, int_value); + EXPECT_EQ(100, int_value); std::vector<std::string> list_value; ASSERT_TRUE(policy.GetUserWhitelist(&list_value)); ASSERT_EQ(3, list_value.size()); - ASSERT_EQ("me@here.com", list_value[0]); - ASSERT_EQ("you@there.com", list_value[1]); - ASSERT_EQ("*@monsters.com", list_value[2]); + EXPECT_EQ("me@here.com", list_value[0]); + EXPECT_EQ("you@there.com", list_value[1]); + EXPECT_EQ("*@monsters.com", list_value[2]); bool bool_value = true; ASSERT_TRUE(policy.GetGuestModeEnabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetCameraEnabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetShowUserNames(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetDataRoamingEnabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetAllowNewUsers(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetMetricsEnabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetReportVersionInfo(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetReportActivityTimes(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetReportBootMode(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetEphemeralUsersEnabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); std::string string_value; ASSERT_TRUE(policy.GetReleaseChannel(&string_value)); - ASSERT_EQ("stable-channel", string_value); + EXPECT_EQ("stable-channel", string_value); bool_value = false; ASSERT_TRUE(policy.GetReleaseChannelDelegated(&bool_value)); - ASSERT_TRUE(bool_value); + EXPECT_TRUE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetUpdateDisabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); int64_t int64_value = -1LL; ASSERT_TRUE(policy.GetScatterFactorInSeconds(&int64_value)); - ASSERT_EQ(17LL, int64_value); + EXPECT_EQ(17LL, int64_value); ASSERT_TRUE(policy.GetTargetVersionPrefix(&string_value)); - ASSERT_EQ("42.0.", string_value); + EXPECT_EQ("42.0.", string_value); + + int_value = -1; + ASSERT_TRUE(policy.GetRollbackToTargetVersion(&int_value)); + EXPECT_EQ(enterprise_management::AutoUpdateSettingsProto:: + ROLLBACK_WITH_FULL_POWERWASH, + int_value); + + int_value = -1; + ASSERT_TRUE(policy.GetRollbackAllowedMilestones(&int_value)); + EXPECT_EQ(3, int_value); std::set<std::string> types; ASSERT_TRUE(policy.GetAllowedConnectionTypesForUpdate(&types)); - ASSERT_TRUE(types.end() != types.find("ethernet")); - ASSERT_TRUE(types.end() != types.find("wifi")); - ASSERT_EQ(2, types.size()); + EXPECT_TRUE(types.end() != types.find("ethernet")); + EXPECT_TRUE(types.end() != types.find("wifi")); + EXPECT_EQ(2, types.size()); ASSERT_TRUE(policy.GetOpenNetworkConfiguration(&string_value)); - ASSERT_EQ("{}", string_value); + EXPECT_EQ("{}", string_value); ASSERT_TRUE(policy.GetOwner(&string_value)); - ASSERT_EQ("", string_value); + EXPECT_EQ("", string_value); bool_value = true; ASSERT_TRUE(policy.GetHttpDownloadsEnabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetAuP2PEnabled(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); bool_value = true; ASSERT_TRUE(policy.GetAllowKioskAppControlChromeVersion(&bool_value)); - ASSERT_FALSE(bool_value); + EXPECT_FALSE(bool_value); std::vector<DevicePolicy::UsbDeviceId> list_device; ASSERT_TRUE(policy.GetUsbDetachableWhitelist(&list_device)); - ASSERT_EQ(2, list_device.size()); - ASSERT_EQ(0x413c, list_device[0].vendor_id); - ASSERT_EQ(0x2105, list_device[0].product_id); - ASSERT_EQ(0x0403, list_device[1].vendor_id); - ASSERT_EQ(0x6001, list_device[1].product_id); + EXPECT_EQ(2, list_device.size()); + EXPECT_EQ(0x413c, list_device[0].vendor_id); + EXPECT_EQ(0x2105, list_device[0].product_id); + EXPECT_EQ(0x0403, list_device[1].vendor_id); + EXPECT_EQ(0x6001, list_device[1].product_id); + + ASSERT_TRUE(policy.GetAutoLaunchedKioskAppId(&string_value)); + EXPECT_EQ("my_kiosk_app", string_value); + + int_value = -1; + ASSERT_TRUE(policy.GetSecondFactorAuthenticationMode(&int_value)); + EXPECT_EQ(2, int_value); + + std::vector<DevicePolicy::WeeklyTimeInterval> intervals; + ASSERT_TRUE(policy.GetDisallowedTimeIntervals(&intervals)); + ASSERT_EQ(2, intervals.size()); + EXPECT_EQ(4, intervals[0].start_day_of_week); + EXPECT_EQ(base::TimeDelta::FromMinutes(30) + base::TimeDelta::FromHours(12), + intervals[0].start_time); + EXPECT_EQ(6, intervals[0].end_day_of_week); + EXPECT_EQ(base::TimeDelta::FromMinutes(15) + base::TimeDelta::FromHours(3), + intervals[0].end_time); + EXPECT_EQ(1, intervals[1].start_day_of_week); + EXPECT_EQ(base::TimeDelta::FromMinutes(10) + base::TimeDelta::FromHours(20), + intervals[1].start_time); + EXPECT_EQ(3, intervals[1].end_day_of_week); + EXPECT_EQ(base::TimeDelta::FromMinutes(20), intervals[1].end_time); ASSERT_TRUE(policy.GetAutoLaunchedKioskAppId(&string_value)); ASSERT_EQ("my_kiosk_app", string_value); // Reloading the protobuf should succeed. - ASSERT_TRUE(provider.Reload()); + EXPECT_TRUE(provider.Reload()); } // Test that a policy file can be verified and parsed correctly. The file @@ -167,10 +206,11 @@ TEST(PolicyTest, DevicePolicyNoneSetTest) { base::FilePath policy_file(kPolicyFileNoneSet); base::FilePath key_file(kKeyFile); - PolicyProvider provider( - CreateDevicePolicyImpl(std::make_unique<MockInstallAttributesReader>( - cryptohome::SerializedInstallAttributes()), - policy_file, key_file, false)); + PolicyProvider provider; + provider.SetDevicePolicyForTesting(CreateDevicePolicyImpl( + std::make_unique<MockInstallAttributesReader>( + InstallAttributesReader::kDeviceModeEnterprise, true), + policy_file, key_file, false)); provider.Reload(); // Ensure we successfully loaded the device policy file. @@ -185,45 +225,136 @@ TEST(PolicyTest, DevicePolicyNoneSetTest) { bool bool_value; std::string string_value; std::vector<DevicePolicy::UsbDeviceId> list_device; - - ASSERT_FALSE(policy.GetPolicyRefreshRate(&int_value)); - ASSERT_FALSE(policy.GetUserWhitelist(&list_value)); - ASSERT_FALSE(policy.GetGuestModeEnabled(&bool_value)); - ASSERT_FALSE(policy.GetCameraEnabled(&bool_value)); - ASSERT_FALSE(policy.GetShowUserNames(&bool_value)); - ASSERT_FALSE(policy.GetDataRoamingEnabled(&bool_value)); - ASSERT_FALSE(policy.GetAllowNewUsers(&bool_value)); - ASSERT_FALSE(policy.GetMetricsEnabled(&bool_value)); - ASSERT_FALSE(policy.GetReportVersionInfo(&bool_value)); - ASSERT_FALSE(policy.GetReportActivityTimes(&bool_value)); - ASSERT_FALSE(policy.GetReportBootMode(&bool_value)); - ASSERT_FALSE(policy.GetEphemeralUsersEnabled(&bool_value)); - ASSERT_FALSE(policy.GetReleaseChannel(&string_value)); - ASSERT_FALSE(policy.GetUpdateDisabled(&bool_value)); - ASSERT_FALSE(policy.GetTargetVersionPrefix(&string_value)); - ASSERT_FALSE(policy.GetScatterFactorInSeconds(&int64_value)); - ASSERT_FALSE(policy.GetOpenNetworkConfiguration(&string_value)); - ASSERT_FALSE(policy.GetHttpDownloadsEnabled(&bool_value)); - ASSERT_FALSE(policy.GetAuP2PEnabled(&bool_value)); - ASSERT_FALSE(policy.GetAllowKioskAppControlChromeVersion(&bool_value)); - ASSERT_FALSE(policy.GetUsbDetachableWhitelist(&list_device)); + std::vector<DevicePolicy::WeeklyTimeInterval> intervals; + + EXPECT_FALSE(policy.GetPolicyRefreshRate(&int_value)); + EXPECT_FALSE(policy.GetUserWhitelist(&list_value)); + EXPECT_FALSE(policy.GetGuestModeEnabled(&bool_value)); + EXPECT_FALSE(policy.GetCameraEnabled(&bool_value)); + EXPECT_FALSE(policy.GetShowUserNames(&bool_value)); + EXPECT_FALSE(policy.GetDataRoamingEnabled(&bool_value)); + EXPECT_FALSE(policy.GetAllowNewUsers(&bool_value)); + EXPECT_FALSE(policy.GetMetricsEnabled(&bool_value)); + EXPECT_FALSE(policy.GetReportVersionInfo(&bool_value)); + EXPECT_FALSE(policy.GetReportActivityTimes(&bool_value)); + EXPECT_FALSE(policy.GetReportBootMode(&bool_value)); + EXPECT_FALSE(policy.GetEphemeralUsersEnabled(&bool_value)); + EXPECT_FALSE(policy.GetReleaseChannel(&string_value)); + EXPECT_FALSE(policy.GetUpdateDisabled(&bool_value)); + EXPECT_FALSE(policy.GetTargetVersionPrefix(&string_value)); + EXPECT_FALSE(policy.GetRollbackToTargetVersion(&int_value)); + // RollbackAllowedMilestones has the default value of 0 for enterprise + // devices. + ASSERT_TRUE(policy.GetRollbackAllowedMilestones(&int_value)); + EXPECT_EQ(0, int_value); + EXPECT_FALSE(policy.GetScatterFactorInSeconds(&int64_value)); + EXPECT_FALSE(policy.GetOpenNetworkConfiguration(&string_value)); + EXPECT_FALSE(policy.GetHttpDownloadsEnabled(&bool_value)); + EXPECT_FALSE(policy.GetAuP2PEnabled(&bool_value)); + EXPECT_FALSE(policy.GetAllowKioskAppControlChromeVersion(&bool_value)); + EXPECT_FALSE(policy.GetUsbDetachableWhitelist(&list_device)); + EXPECT_FALSE(policy.GetSecondFactorAuthenticationMode(&int_value)); + EXPECT_FALSE(policy.GetDisallowedTimeIntervals(&intervals)); } // Verify that the library will correctly recognize and signal missing files. TEST(PolicyTest, DevicePolicyFailure) { LOG(INFO) << "Errors expected."; // Try loading non-existing protobuf should fail. - base::FilePath non_existing("this_file_is_doof"); - PolicyProvider provider( + base::FilePath policy_file(kNonExistingFile); + base::FilePath key_file(kNonExistingFile); + PolicyProvider provider; + provider.SetDevicePolicyForTesting( CreateDevicePolicyImpl(std::make_unique<MockInstallAttributesReader>( cryptohome::SerializedInstallAttributes()), - non_existing, - non_existing, - true)); + policy_file, key_file, true)); // Even after reload the policy should still be not loaded. ASSERT_FALSE(provider.Reload()); - ASSERT_FALSE(provider.device_policy_is_loaded()); + EXPECT_FALSE(provider.device_policy_is_loaded()); +} + +// Verify that signature verification is waived for a device in enterprise_ad +// mode. +TEST(PolicyTest, SkipSignatureForEnterpriseAD) { + base::FilePath policy_file(kPolicyFileAllSet); + base::FilePath key_file(kNonExistingFile); + PolicyProvider provider; + provider.SetDevicePolicyForTesting(CreateDevicePolicyImpl( + std::make_unique<MockInstallAttributesReader>( + InstallAttributesReader::kDeviceModeEnterpriseAD, true), + policy_file, key_file, false)); + provider.Reload(); + + // Ensure we successfully loaded the device policy file. + EXPECT_TRUE(provider.device_policy_is_loaded()); +} + +// Ensure that signature verification is enforced for a device in vanilla +// enterprise mode. +TEST(PolicyTest, DontSkipSignatureForEnterprise) { + base::FilePath policy_file(kPolicyFileAllSet); + base::FilePath key_file(kNonExistingFile); + + PolicyProvider provider; + provider.SetDevicePolicyForTesting(CreateDevicePolicyImpl( + std::make_unique<MockInstallAttributesReader>( + InstallAttributesReader::kDeviceModeEnterprise, true), + policy_file, key_file, false)); + provider.Reload(); + + // Ensure that unverifed policy is not loaded. + EXPECT_FALSE(provider.device_policy_is_loaded()); +} + +// Ensure that signature verification is enforced for a device in consumer mode. +TEST(PolicyTest, DontSkipSignatureForConsumer) { + base::FilePath policy_file(kPolicyFileAllSet); + base::FilePath key_file(kNonExistingFile); + cryptohome::SerializedInstallAttributes install_attributes; + + PolicyProvider provider; + provider.SetDevicePolicyForTesting(CreateDevicePolicyImpl( + std::make_unique<MockInstallAttributesReader>(install_attributes), + policy_file, key_file, false)); + provider.Reload(); + + // Ensure that unverifed policy is not loaded. + EXPECT_FALSE(provider.device_policy_is_loaded()); +} + +// Checks return value of IsConsumerDevice when it's a still in OOBE. +TEST(PolicyTest, IsConsumerDeviceOobe) { + PolicyProvider provider; + provider.SetInstallAttributesReaderForTesting( + std::make_unique<MockInstallAttributesReader>("", false)); + EXPECT_FALSE(provider.IsConsumerDevice()); +} + +// Checks return value of IsConsumerDevice when it's a consumer device. +TEST(PolicyTest, IsConsumerDeviceConsumer) { + PolicyProvider provider; + provider.SetInstallAttributesReaderForTesting( + std::make_unique<MockInstallAttributesReader>("", true)); + EXPECT_TRUE(provider.IsConsumerDevice()); +} + +// Checks return value of IsConsumerDevice when it's an enterprise device. +TEST(PolicyTest, IsConsumerDeviceEnterprise) { + PolicyProvider provider; + provider.SetInstallAttributesReaderForTesting( + std::make_unique<MockInstallAttributesReader>( + InstallAttributesReader::kDeviceModeEnterprise, true)); + EXPECT_FALSE(provider.IsConsumerDevice()); +} + +// Checks return value of IsConsumerDevice when it's an enterprise AD device. +TEST(PolicyTest, IsConsumerDeviceEnterpriseAd) { + PolicyProvider provider; + provider.SetInstallAttributesReaderForTesting( + std::make_unique<MockInstallAttributesReader>( + InstallAttributesReader::kDeviceModeEnterpriseAD, true)); + EXPECT_FALSE(provider.IsConsumerDevice()); } } // namespace policy diff --git a/policy/tests/policy_util_unittest.cc b/policy/tests/policy_util_unittest.cc index 74032d4..f26622f 100644 --- a/policy/tests/policy_util_unittest.cc +++ b/policy/tests/policy_util_unittest.cc @@ -20,9 +20,9 @@ TEST(DevicePolicyUtilTest, LoadPolicyFromPath) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - base::FilePath invalid_policy_data_path(temp_dir.path().Append("policy")); - base::FilePath inexistent_file(temp_dir.path().Append("policy.1")); - base::FilePath good_policy_data_path(temp_dir.path().Append("policy.2")); + base::FilePath invalid_policy_data_path(temp_dir.GetPath().Append("policy")); + base::FilePath inexistent_file(temp_dir.GetPath().Append("policy.1")); + base::FilePath good_policy_data_path(temp_dir.GetPath().Append("policy.2")); // Create the file with invalid data. std::string data = "invalid data"; diff --git a/policy/tests/resilient_policy_util_unittest.cc b/policy/tests/resilient_policy_util_unittest.cc index e45ab34..0963b08 100644 --- a/policy/tests/resilient_policy_util_unittest.cc +++ b/policy/tests/resilient_policy_util_unittest.cc @@ -31,11 +31,11 @@ TEST(DevicePolicyUtilTest, GetSortedResilientPolicyFilePaths) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - base::FilePath file0(temp_dir.path().Append("policy")); - base::FilePath file1(temp_dir.path().Append("policy.12")); - base::FilePath file2(temp_dir.path().Append("policy.2")); - base::FilePath file3(temp_dir.path().Append("policy.30")); - base::FilePath invalid(temp_dir.path().Append("policy_4")); + base::FilePath file0(temp_dir.GetPath().Append("policy")); + base::FilePath file1(temp_dir.GetPath().Append("policy.12")); + base::FilePath file2(temp_dir.GetPath().Append("policy.2")); + base::FilePath file3(temp_dir.GetPath().Append("policy.30")); + base::FilePath invalid(temp_dir.GetPath().Append("policy_4")); CreateFile(file0); CreateFile(file1); @@ -43,7 +43,7 @@ TEST(DevicePolicyUtilTest, GetSortedResilientPolicyFilePaths) { CreateFile(file3); const base::FilePath test_file_path( - temp_dir.path().Append(kDefaultResilientPolicyFilePath)); + temp_dir.GetPath().Append(kDefaultResilientPolicyFilePath)); std::map<int, base::FilePath> sorted_file_paths = GetSortedResilientPolicyFilePaths(test_file_path); diff --git a/policy/tests/whitelist/policy_all b/policy/tests/whitelist/policy_all Binary files differindex ff197cd..c0dfaaf 100644 --- a/policy/tests/whitelist/policy_all +++ b/policy/tests/whitelist/policy_all |