device_cloud_policy_manager_chromeos_unittest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 6 7#include "base/basictypes.h" 8#include "base/compiler_specific.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/message_loop/message_loop.h" 11#include "base/prefs/pref_registry_simple.h" 12#include "base/prefs/testing_pref_service.h" 13#include "base/run_loop.h" 14#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h" 15#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" 16#include "chrome/browser/chromeos/settings/cros_settings.h" 17#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" 18#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h" 19#include "chrome/browser/chromeos/settings/device_settings_service.h" 20#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" 21#include "chrome/browser/policy/cloud/cloud_policy_client.h" 22#include "chrome/browser/policy/cloud/mock_device_management_service.h" 23#include "chrome/browser/policy/external_data_fetcher.h" 24#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" 25#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 26#include "chrome/browser/prefs/browser_prefs.h" 27#include "chrome/test/base/testing_browser_process.h" 28#include "chromeos/cryptohome/cryptohome_library.h" 29#include "chromeos/dbus/dbus_client_implementation_type.h" 30#include "chromeos/dbus/dbus_thread_manager.h" 31#include "chromeos/system/mock_statistics_provider.h" 32#include "chromeos/system/statistics_provider.h" 33#include "google_apis/gaia/gaia_oauth_client.h" 34#include "net/url_request/test_url_fetcher_factory.h" 35#include "net/url_request/url_request_test_util.h" 36#include "policy/policy_constants.h" 37#include "testing/gmock/include/gmock/gmock.h" 38#include "testing/gtest/include/gtest/gtest.h" 39 40using testing::AnyNumber; 41using testing::AtMost; 42using testing::DoAll; 43using testing::Mock; 44using testing::Return; 45using testing::SaveArg; 46using testing::SetArgumentPointee; 47using testing::_; 48 49namespace em = enterprise_management; 50 51namespace policy { 52namespace { 53 54void CopyLockResult(base::RunLoop* loop, 55 EnterpriseInstallAttributes::LockResult* out, 56 EnterpriseInstallAttributes::LockResult result) { 57 *out = result; 58 loop->Quit(); 59} 60 61class DeviceCloudPolicyManagerChromeOSTest 62 : public chromeos::DeviceSettingsTestBase { 63 protected: 64 DeviceCloudPolicyManagerChromeOSTest() : store_(NULL) { 65 EXPECT_CALL(mock_statistics_provider_, 66 GetMachineStatistic(_, _)) 67 .WillRepeatedly(Return(false)); 68 EXPECT_CALL(mock_statistics_provider_, 69 GetMachineStatistic("serial_number", _)) 70 .WillRepeatedly(DoAll(SetArgumentPointee<1>(std::string("test_sn")), 71 Return(true))); 72 chromeos::system::StatisticsProvider::SetTestProvider( 73 &mock_statistics_provider_); 74 } 75 76 virtual ~DeviceCloudPolicyManagerChromeOSTest() { 77 chromeos::system::StatisticsProvider::SetTestProvider(NULL); 78 } 79 80 virtual void SetUp() OVERRIDE { 81 DeviceSettingsTestBase::SetUp(); 82 83 // DBusThreadManager is set up in DeviceSettingsTestBase::SetUp(). 84 install_attributes_.reset(new EnterpriseInstallAttributes( 85 chromeos::DBusThreadManager::Get()->GetCryptohomeClient())); 86 store_ = new DeviceCloudPolicyStoreChromeOS(&device_settings_service_, 87 install_attributes_.get()); 88 manager_.reset(new DeviceCloudPolicyManagerChromeOS( 89 make_scoped_ptr(store_), 90 loop_.message_loop_proxy(), 91 install_attributes_.get())); 92 93 chrome::RegisterLocalState(local_state_.registry()); 94 manager_->Init(); 95 96 // DeviceOAuth2TokenService uses the system request context to fetch 97 // OAuth tokens, then writes the token to local state, encrypting it 98 // first with methods in CryptohomeTokenEncryptor. 99 request_context_getter_ = new net::TestURLRequestContextGetter( 100 loop_.message_loop_proxy()); 101 TestingBrowserProcess::GetGlobal()->SetSystemRequestContext( 102 request_context_getter_.get()); 103 TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_); 104 chromeos::DeviceOAuth2TokenServiceFactory::Initialize(); 105 // This is needed as CryptohomeLibrary is used for encrypting tokens in 106 // CryptohomeTokenEncryptor. 107 chromeos::CryptohomeLibrary::Initialize(); 108 url_fetcher_response_code_ = 200; 109 url_fetcher_response_string_ = "{\"access_token\":\"accessToken4Test\"," 110 "\"expires_in\":1234," 111 "\"refresh_token\":\"refreshToken4Test\"}"; 112 } 113 114 virtual void TearDown() OVERRIDE { 115 manager_->Shutdown(); 116 DeviceSettingsTestBase::TearDown(); 117 118 chromeos::DeviceOAuth2TokenServiceFactory::Shutdown(); 119 chromeos::CryptohomeLibrary::Shutdown(); 120 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL); 121 } 122 123 scoped_ptr<EnterpriseInstallAttributes> install_attributes_; 124 125 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 126 net::TestURLFetcherFactory url_fetcher_factory_; 127 int url_fetcher_response_code_; 128 string url_fetcher_response_string_; 129 TestingPrefServiceSimple local_state_; 130 MockDeviceManagementService device_management_service_; 131 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 132 chromeos::ScopedTestCrosSettings test_cros_settings_; 133 chromeos::system::MockStatisticsProvider mock_statistics_provider_; 134 135 DeviceCloudPolicyStoreChromeOS* store_; 136 scoped_ptr<DeviceCloudPolicyManagerChromeOS> manager_; 137 138 private: 139 DISALLOW_COPY_AND_ASSIGN(DeviceCloudPolicyManagerChromeOSTest); 140}; 141 142TEST_F(DeviceCloudPolicyManagerChromeOSTest, FreshDevice) { 143 owner_key_util_->Clear(); 144 FlushDeviceSettings(); 145 EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME)); 146 147 manager_->Connect(&local_state_, 148 &device_management_service_, 149 scoped_ptr<CloudPolicyClient::StatusProvider>()); 150 151 PolicyBundle bundle; 152 EXPECT_TRUE(manager_->policies().Equals(bundle)); 153} 154 155TEST_F(DeviceCloudPolicyManagerChromeOSTest, EnrolledDevice) { 156 base::RunLoop loop; 157 EnterpriseInstallAttributes::LockResult result; 158 install_attributes_->LockDevice(PolicyBuilder::kFakeUsername, 159 DEVICE_MODE_ENTERPRISE, 160 PolicyBuilder::kFakeDeviceId, 161 base::Bind(&CopyLockResult, &loop, &result)); 162 loop.Run(); 163 ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS, result); 164 165 FlushDeviceSettings(); 166 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 167 EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME)); 168 169 PolicyBundle bundle; 170 bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 171 .Set(key::kDeviceMetricsReportingEnabled, 172 POLICY_LEVEL_MANDATORY, 173 POLICY_SCOPE_MACHINE, 174 Value::CreateBooleanValue(false), 175 NULL); 176 EXPECT_TRUE(manager_->policies().Equals(bundle)); 177 178 manager_->Connect(&local_state_, 179 &device_management_service_, 180 scoped_ptr<CloudPolicyClient::StatusProvider>()); 181 EXPECT_TRUE(manager_->policies().Equals(bundle)); 182 183 manager_->Shutdown(); 184 EXPECT_TRUE(manager_->policies().Equals(bundle)); 185 186 EXPECT_EQ(manager_->GetRobotAccountId(), 187 PolicyBuilder::kFakeServiceAccountIdentity); 188} 189 190TEST_F(DeviceCloudPolicyManagerChromeOSTest, ConsumerDevice) { 191 FlushDeviceSettings(); 192 EXPECT_EQ(CloudPolicyStore::STATUS_BAD_STATE, store_->status()); 193 EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME)); 194 195 PolicyBundle bundle; 196 EXPECT_TRUE(manager_->policies().Equals(bundle)); 197 198 manager_->Connect(&local_state_, 199 &device_management_service_, 200 scoped_ptr<CloudPolicyClient::StatusProvider>()); 201 EXPECT_TRUE(manager_->policies().Equals(bundle)); 202 203 manager_->Shutdown(); 204 EXPECT_TRUE(manager_->policies().Equals(bundle)); 205} 206 207class DeviceCloudPolicyManagerChromeOSEnrollmentTest 208 : public DeviceCloudPolicyManagerChromeOSTest { 209 public: 210 void Done(EnrollmentStatus status) { 211 status_ = status; 212 done_ = true; 213 } 214 215 protected: 216 DeviceCloudPolicyManagerChromeOSEnrollmentTest() 217 : is_auto_enrollment_(false), 218 register_status_(DM_STATUS_SUCCESS), 219 policy_fetch_status_(DM_STATUS_SUCCESS), 220 robot_auth_fetch_status_(DM_STATUS_SUCCESS), 221 store_result_(true), 222 status_(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS)), 223 done_(false) {} 224 225 virtual void SetUp() OVERRIDE { 226 DeviceCloudPolicyManagerChromeOSTest::SetUp(); 227 228 // Set up test data. 229 device_policy_.SetDefaultNewSigningKey(); 230 device_policy_.policy_data().set_timestamp( 231 (base::Time::NowFromSystemTime() - 232 base::Time::UnixEpoch()).InMilliseconds()); 233 device_policy_.Build(); 234 235 register_response_.mutable_register_response()->set_device_management_token( 236 PolicyBuilder::kFakeToken); 237 policy_fetch_response_.mutable_policy_response()->add_response()->CopyFrom( 238 device_policy_.policy()); 239 robot_auth_fetch_response_.mutable_service_api_access_response() 240 ->set_auth_code("auth_code_for_test"); 241 loaded_blob_ = device_policy_.GetBlob(); 242 243 // Initialize the manager. 244 FlushDeviceSettings(); 245 EXPECT_EQ(CloudPolicyStore::STATUS_BAD_STATE, store_->status()); 246 EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME)); 247 248 PolicyBundle bundle; 249 EXPECT_TRUE(manager_->policies().Equals(bundle)); 250 251 manager_->Connect(&local_state_, 252 &device_management_service_, 253 scoped_ptr<CloudPolicyClient::StatusProvider>()); 254 } 255 256 void ExpectFailedEnrollment(EnrollmentStatus::Status status) { 257 EXPECT_EQ(status, status_.status()); 258 EXPECT_FALSE(store_->is_managed()); 259 PolicyBundle empty_bundle; 260 EXPECT_TRUE(manager_->policies().Equals(empty_bundle)); 261 } 262 263 void ExpectSuccessfulEnrollment() { 264 EXPECT_EQ(EnrollmentStatus::STATUS_SUCCESS, status_.status()); 265 EXPECT_EQ(DEVICE_MODE_ENTERPRISE, install_attributes_->GetMode()); 266 EXPECT_TRUE(store_->has_policy()); 267 EXPECT_TRUE(store_->is_managed()); 268 ASSERT_TRUE(manager_->core()->client()); 269 EXPECT_TRUE(manager_->core()->client()->is_registered()); 270 271 PolicyBundle bundle; 272 bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 273 .Set(key::kDeviceMetricsReportingEnabled, 274 POLICY_LEVEL_MANDATORY, 275 POLICY_SCOPE_MACHINE, 276 Value::CreateBooleanValue(false), 277 NULL); 278 EXPECT_TRUE(manager_->policies().Equals(bundle)); 279 } 280 281 void RunTest() { 282 // Trigger enrollment. 283 MockDeviceManagementJob* register_job = NULL; 284 EXPECT_CALL(device_management_service_, 285 CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)) 286 .Times(AtMost(1)) 287 .WillOnce(device_management_service_.CreateAsyncJob(®ister_job)); 288 EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _)) 289 .Times(AtMost(1)) 290 .WillOnce(DoAll(SaveArg<5>(&client_id_), 291 SaveArg<6>(®ister_request_))); 292 DeviceCloudPolicyManagerChromeOS::AllowedDeviceModes modes; 293 modes[DEVICE_MODE_ENTERPRISE] = true; 294 manager_->StartEnrollment( 295 "auth token", is_auto_enrollment_, modes, 296 base::Bind(&DeviceCloudPolicyManagerChromeOSEnrollmentTest::Done, 297 base::Unretained(this))); 298 Mock::VerifyAndClearExpectations(&device_management_service_); 299 300 if (done_) 301 return; 302 303 // Process registration. 304 ASSERT_TRUE(register_job); 305 MockDeviceManagementJob* policy_fetch_job = NULL; 306 EXPECT_CALL(device_management_service_, 307 CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH)) 308 .Times(AtMost(1)) 309 .WillOnce(device_management_service_.CreateAsyncJob(&policy_fetch_job)); 310 EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _)) 311 .Times(AtMost(1)); 312 register_job->SendResponse(register_status_, register_response_); 313 Mock::VerifyAndClearExpectations(&device_management_service_); 314 315 if (done_) 316 return; 317 318 // Process policy fetch. 319 ASSERT_TRUE(policy_fetch_job); 320 policy_fetch_job->SendResponse(policy_fetch_status_, 321 policy_fetch_response_); 322 323 if (done_) 324 return; 325 326 // Process verification. 327 MockDeviceManagementJob* robot_auth_fetch_job = NULL; 328 EXPECT_CALL(device_management_service_, 329 CreateJob(DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH)) 330 .Times(AtMost(1)) 331 .WillOnce(device_management_service_.CreateAsyncJob( 332 &robot_auth_fetch_job)); 333 EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _)) 334 .Times(AtMost(1)); 335 base::RunLoop().RunUntilIdle(); 336 Mock::VerifyAndClearExpectations(&device_management_service_); 337 338 if (done_) 339 return; 340 341 // Process robot auth token fetch. 342 ASSERT_TRUE(robot_auth_fetch_job); 343 robot_auth_fetch_job->SendResponse(robot_auth_fetch_status_, 344 robot_auth_fetch_response_); 345 Mock::VerifyAndClearExpectations(&device_management_service_); 346 347 if (done_) 348 return; 349 350 // Process robot refresh token fetch if the auth code fetch succeeded. 351 // DeviceCloudPolicyManagerChromeOS holds an EnrollmentHandlerChromeOS which 352 // holds a GaiaOAuthClient that fetches the refresh token during enrollment. 353 // We return a successful OAuth response via a TestURLFetcher to trigger the 354 // happy path for these classes so that enrollment can continue. 355 if (robot_auth_fetch_status_ == DM_STATUS_SUCCESS) { 356 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID( 357 gaia::GaiaOAuthClient::kUrlFetcherId); 358 ASSERT_TRUE(url_fetcher); 359 url_fetcher->SetMaxRetriesOn5xx(0); 360 url_fetcher->set_status(net::URLRequestStatus()); 361 url_fetcher->set_response_code(url_fetcher_response_code_); 362 url_fetcher->SetResponseString(url_fetcher_response_string_); 363 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); 364 } 365 base::RunLoop().RunUntilIdle(); 366 367 // Process policy store. 368 device_settings_test_helper_.set_store_result(store_result_); 369 device_settings_test_helper_.FlushStore(); 370 EXPECT_EQ(device_policy_.GetBlob(), 371 device_settings_test_helper_.policy_blob()); 372 373 if (done_) 374 return; 375 376 // Key installation, policy load and refresh token save. 377 device_settings_test_helper_.set_policy_blob(loaded_blob_); 378 owner_key_util_->SetPublicKeyFromPrivateKey( 379 *device_policy_.GetNewSigningKey()); 380 ReloadDeviceSettings(); 381 382 if (done_) 383 return; 384 385 chromeos::DeviceOAuth2TokenService* token_service = 386 chromeos::DeviceOAuth2TokenServiceFactory::Get(); 387 // Process robot refresh token store. 388 EXPECT_EQ( 389 "refreshToken4Test", 390 token_service->GetRefreshToken(token_service->GetRobotAccountId())); 391 } 392 393 bool is_auto_enrollment_; 394 395 DeviceManagementStatus register_status_; 396 em::DeviceManagementResponse register_response_; 397 398 DeviceManagementStatus policy_fetch_status_; 399 em::DeviceManagementResponse policy_fetch_response_; 400 401 DeviceManagementStatus robot_auth_fetch_status_; 402 em::DeviceManagementResponse robot_auth_fetch_response_; 403 404 bool store_result_; 405 std::string loaded_blob_; 406 407 em::DeviceManagementRequest register_request_; 408 std::string client_id_; 409 EnrollmentStatus status_; 410 411 bool done_; 412 413 private: 414 DISALLOW_COPY_AND_ASSIGN(DeviceCloudPolicyManagerChromeOSEnrollmentTest); 415}; 416 417TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, Success) { 418 RunTest(); 419 ExpectSuccessfulEnrollment(); 420} 421 422TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, AutoEnrollment) { 423 is_auto_enrollment_ = true; 424 RunTest(); 425 ExpectSuccessfulEnrollment(); 426 EXPECT_TRUE(register_request_.register_request().auto_enrolled()); 427} 428 429TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, Reenrollment) { 430 base::RunLoop loop; 431 EnterpriseInstallAttributes::LockResult result; 432 install_attributes_->LockDevice(PolicyBuilder::kFakeUsername, 433 DEVICE_MODE_ENTERPRISE, 434 PolicyBuilder::kFakeDeviceId, 435 base::Bind(&CopyLockResult, &loop, &result)); 436 loop.Run(); 437 ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS, result); 438 439 RunTest(); 440 ExpectSuccessfulEnrollment(); 441 EXPECT_TRUE(register_request_.register_request().reregister()); 442 EXPECT_EQ(PolicyBuilder::kFakeDeviceId, client_id_); 443} 444 445TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, RegistrationFailed) { 446 register_status_ = DM_STATUS_REQUEST_FAILED; 447 RunTest(); 448 ExpectFailedEnrollment(EnrollmentStatus::STATUS_REGISTRATION_FAILED); 449 EXPECT_EQ(DM_STATUS_REQUEST_FAILED, status_.client_status()); 450} 451 452// Policy server implementations are not required to support robot auth 453// tokens, so the following 4 Robot* tests verify that enrollment succeeds 454// even if the robot auth token fetch fails. 455TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, 456 RobotAuthCodeFetchFailed) { 457 robot_auth_fetch_status_ = DM_STATUS_REQUEST_FAILED; 458 RunTest(); 459 ExpectSuccessfulEnrollment(); 460} 461 462TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, 463 RobotRefreshTokenFetchResponseCodeFailed) { 464 url_fetcher_response_code_ = 400; 465 RunTest(); 466 ExpectSuccessfulEnrollment(); 467} 468 469TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, 470 RobotRefreshTokenFetchResponseStringFailed) { 471 url_fetcher_response_string_ = "invalid response json"; 472 RunTest(); 473 ExpectSuccessfulEnrollment(); 474} 475 476TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, RobotRefreshSaveFailed) { 477 // Without a DeviceOAuth2TokenService, the refresh token can't be saved. 478 chromeos::DeviceOAuth2TokenServiceFactory::Shutdown(); 479 RunTest(); 480 ExpectSuccessfulEnrollment(); 481} 482 483TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, PolicyFetchFailed) { 484 policy_fetch_status_ = DM_STATUS_REQUEST_FAILED; 485 RunTest(); 486 ExpectFailedEnrollment(EnrollmentStatus::STATUS_POLICY_FETCH_FAILED); 487 EXPECT_EQ(DM_STATUS_REQUEST_FAILED, status_.client_status()); 488} 489 490TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, ValidationFailed) { 491 device_policy_.policy().set_policy_data_signature("bad"); 492 policy_fetch_response_.clear_policy_response(); 493 policy_fetch_response_.mutable_policy_response()->add_response()->CopyFrom( 494 device_policy_.policy()); 495 RunTest(); 496 ExpectFailedEnrollment(EnrollmentStatus::STATUS_VALIDATION_FAILED); 497 EXPECT_EQ(CloudPolicyValidatorBase::VALIDATION_BAD_INITIAL_SIGNATURE, 498 status_.validation_status()); 499} 500 501TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, StoreError) { 502 store_result_ = false; 503 RunTest(); 504 ExpectFailedEnrollment(EnrollmentStatus::STATUS_STORE_ERROR); 505 EXPECT_EQ(CloudPolicyStore::STATUS_STORE_ERROR, 506 status_.store_status()); 507} 508 509TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, LoadError) { 510 loaded_blob_.clear(); 511 RunTest(); 512 ExpectFailedEnrollment(EnrollmentStatus::STATUS_STORE_ERROR); 513 EXPECT_EQ(CloudPolicyStore::STATUS_LOAD_ERROR, 514 status_.store_status()); 515} 516 517} // namespace 518} // namespace policy 519