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