blob: b20bf485ccaeb93dbd641a4e49f19b675418b8e6 [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/policy/enrollment/device_cloud_policy_initializer.h"
#include "ash/constants/ash_switches.h"
#include "base/command_line.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "chrome/browser/ash/login/login_pref_names.h"
#include "chrome/browser/ash/policy/enrollment/enrollment_config.h"
#include "chrome/browser/ash/policy/server_backed_state/server_backed_device_state.h"
#include "chrome/browser/ash/settings/device_settings_service.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/common/pref_names.h"
#include "chromeos/ash/components/install_attributes/stub_install_attributes.h"
#include "chromeos/ash/components/system/fake_statistics_provider.h"
#include "chromeos/ash/components/system/statistics_provider.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
struct ZeroTouchParam {
const char* enable_zero_touch_flag;
EnrollmentConfig::AuthMechanism auth_mechanism;
EnrollmentConfig::AuthMechanism auth_mechanism_after_oobe;
ZeroTouchParam(const char* flag,
EnrollmentConfig::AuthMechanism auth,
EnrollmentConfig::AuthMechanism auth_after_oobe)
: enable_zero_touch_flag(flag),
auth_mechanism(auth),
auth_mechanism_after_oobe(auth_after_oobe) {}
};
class EnrollmentConfigTest : public testing::Test {
protected:
EnrollmentConfigTest() {
RegisterLocalState(local_state_.registry());
statistics_provider_.SetMachineStatistic(
ash::system::kSerialNumberKeyForTest, "fake-serial");
statistics_provider_.SetMachineStatistic(ash::system::kHardwareClassKey,
"fake-hardware");
}
ash::system::ScopedFakeStatisticsProvider statistics_provider_;
TestingPrefServiceSimple local_state_;
ash::StubInstallAttributes install_attributes_;
ash::ScopedTestDeviceSettingsService scoped_device_settings_service_;
};
// TODO(b/329271128): Remove this test once token enrollment is supported.
TEST_F(EnrollmentConfigTest,
TokenEnrollmentModeYieldsEnrollmentConfigModeNone) {
auto state_dict = base::Value::Dict().Set(
kDeviceStateMode, kDeviceStateInitialModeTokenEnrollment);
local_state_.SetDict(prefs::kServerBackedDeviceState, state_dict.Clone());
EnrollmentConfig config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(config.mode, EnrollmentConfig::MODE_NONE);
EXPECT_FALSE(config.should_enroll());
}
class EnrollmentConfigZeroTouchTest
: public EnrollmentConfigTest,
public testing::WithParamInterface<ZeroTouchParam> {
protected:
void SetupZeroTouchCommandLineSwitch();
};
void EnrollmentConfigZeroTouchTest::SetupZeroTouchCommandLineSwitch() {
const ZeroTouchParam& param = GetParam();
if (param.enable_zero_touch_flag != nullptr) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
ash::switches::kEnterpriseEnableZeroTouchEnrollment,
param.enable_zero_touch_flag);
}
}
TEST_P(EnrollmentConfigZeroTouchTest, GetPrescribedEnrollmentConfigDuringOOBE) {
SetupZeroTouchCommandLineSwitch();
// Default configuration is empty.
EnrollmentConfig config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_NONE, config.mode);
EXPECT_TRUE(config.management_domain.empty());
EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism);
// Set signals in increasing order of precedence, check results.
// OEM manifest: advertised enrollment.
statistics_provider_.SetMachineFlag(ash::system::kOemIsEnterpriseManagedKey,
true);
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_LOCAL_ADVERTISED, config.mode);
EXPECT_TRUE(config.management_domain.empty());
EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism);
// Pref: advertised enrollment. The resulting |config| is indistinguishable
// from the OEM manifest configuration, so clear the latter to at least
// verify the pref configuration results in the expect behavior on its own.
statistics_provider_.ClearMachineFlag(
ash::system::kOemIsEnterpriseManagedKey);
local_state_.SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_LOCAL_ADVERTISED, config.mode);
EXPECT_TRUE(config.management_domain.empty());
EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism);
// Server-backed state: advertised enrollment.
auto state_dict =
base::Value::Dict()
.Set(kDeviceStateMode, kDeviceStateRestoreModeReEnrollmentRequested)
.Set(kDeviceStateManagementDomain, "example.com");
local_state_.SetDict(prefs::kServerBackedDeviceState, state_dict.Clone());
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_SERVER_ADVERTISED, config.mode);
EXPECT_EQ("example.com", config.management_domain);
EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism);
// OEM manifest: forced enrollment.
statistics_provider_.SetMachineFlag(ash::system::kOemIsEnterpriseManagedKey,
true);
statistics_provider_.SetMachineFlag(
ash::system::kOemCanExitEnterpriseEnrollmentKey, false);
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_LOCAL_FORCED, config.mode);
EXPECT_TRUE(config.management_domain.empty());
EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism);
// Pref: forced enrollment. The resulting |config| is indistinguishable from
// the OEM manifest configuration, so clear the latter to at least verify the
// pref configuration results in the expect behavior on its own.
statistics_provider_.ClearMachineFlag(
ash::system::kOemIsEnterpriseManagedKey);
local_state_.SetBoolean(prefs::kDeviceEnrollmentCanExit, false);
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_LOCAL_FORCED, config.mode);
EXPECT_TRUE(config.management_domain.empty());
EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism);
// Server-backed state: forced enrollment.
state_dict.Set(kDeviceStateMode, kDeviceStateRestoreModeReEnrollmentEnforced);
local_state_.SetDict(prefs::kServerBackedDeviceState, state_dict.Clone());
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_SERVER_FORCED, config.mode);
EXPECT_EQ("example.com", config.management_domain);
EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism);
}
TEST_P(EnrollmentConfigZeroTouchTest, GetPrescribedEnrollmentConfigAfterOOBE) {
SetupZeroTouchCommandLineSwitch();
// If OOBE is complete, we may re-enroll to the domain configured in install
// attributes. This is only enforced after detecting enrollment loss.
local_state_.SetBoolean(ash::prefs::kOobeComplete, true);
EnrollmentConfig config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_NONE, config.mode);
EXPECT_TRUE(config.management_domain.empty());
EXPECT_EQ(GetParam().auth_mechanism_after_oobe, config.auth_mechanism);
// Advertised enrollment gets ignored.
local_state_.SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
statistics_provider_.SetMachineFlag(ash::system::kOemIsEnterpriseManagedKey,
true);
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_NONE, config.mode);
EXPECT_TRUE(config.management_domain.empty());
EXPECT_EQ(GetParam().auth_mechanism_after_oobe, config.auth_mechanism);
// If the device is enterprise-managed, the management domain gets pulled from
// install attributes.
install_attributes_.SetCloudManaged("example.com", "fake-id");
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_NONE, config.mode);
EXPECT_EQ("example.com", config.management_domain);
EXPECT_EQ(GetParam().auth_mechanism_after_oobe, config.auth_mechanism);
// If enrollment recovery is on, this is signaled in |config.mode|.
local_state_.SetBoolean(prefs::kEnrollmentRecoveryRequired, true);
config = EnrollmentConfig::GetPrescribedEnrollmentConfig(
&local_state_, install_attributes_, &statistics_provider_);
EXPECT_EQ(EnrollmentConfig::MODE_RECOVERY, config.mode);
EXPECT_EQ("example.com", config.management_domain);
EXPECT_EQ(GetParam().auth_mechanism_after_oobe, config.auth_mechanism);
}
INSTANTIATE_TEST_SUITE_P(
ZeroTouchFlag,
EnrollmentConfigZeroTouchTest,
::testing::Values(
ZeroTouchParam(nullptr, // No flag set.
EnrollmentConfig::AUTH_MECHANISM_INTERACTIVE,
EnrollmentConfig::AUTH_MECHANISM_INTERACTIVE),
ZeroTouchParam("", // Flag set without a set value.
EnrollmentConfig::AUTH_MECHANISM_BEST_AVAILABLE,
EnrollmentConfig::AUTH_MECHANISM_INTERACTIVE),
ZeroTouchParam("forced",
EnrollmentConfig::AUTH_MECHANISM_ATTESTATION,
EnrollmentConfig::AUTH_MECHANISM_ATTESTATION)));
} // namespace policy