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