device_cloud_policy_manager_chromeos_unittest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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_.get());
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_,
125                   &device_management_service_,
126                   scoped_ptr<CloudPolicyClient::StatusProvider>());
127
128  PolicyBundle bundle;
129  EXPECT_TRUE(manager_.policies().Equals(bundle));
130}
131
132TEST_F(DeviceCloudPolicyManagerChromeOSTest, EnrolledDevice) {
133  base::RunLoop loop;
134  EnterpriseInstallAttributes::LockResult result;
135  install_attributes_.LockDevice(PolicyBuilder::kFakeUsername,
136                                 DEVICE_MODE_ENTERPRISE,
137                                 PolicyBuilder::kFakeDeviceId,
138                                 base::Bind(&CopyLockResult, &loop, &result));
139  loop.Run();
140  ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS, result);
141
142  FlushDeviceSettings();
143  EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
144  EXPECT_TRUE(manager_.IsInitializationComplete(POLICY_DOMAIN_CHROME));
145
146  PolicyBundle bundle;
147  bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
148      .Set(key::kDeviceMetricsReportingEnabled,
149           POLICY_LEVEL_MANDATORY,
150           POLICY_SCOPE_MACHINE,
151           Value::CreateBooleanValue(false));
152  EXPECT_TRUE(manager_.policies().Equals(bundle));
153
154  manager_.Connect(&local_state_,
155                   &device_management_service_,
156                   scoped_ptr<CloudPolicyClient::StatusProvider>());
157  EXPECT_TRUE(manager_.policies().Equals(bundle));
158
159  manager_.Shutdown();
160  EXPECT_TRUE(manager_.policies().Equals(bundle));
161}
162
163TEST_F(DeviceCloudPolicyManagerChromeOSTest, ConsumerDevice) {
164  FlushDeviceSettings();
165  EXPECT_EQ(CloudPolicyStore::STATUS_BAD_STATE, store_->status());
166  EXPECT_TRUE(manager_.IsInitializationComplete(POLICY_DOMAIN_CHROME));
167
168  PolicyBundle bundle;
169  EXPECT_TRUE(manager_.policies().Equals(bundle));
170
171  manager_.Connect(&local_state_,
172                   &device_management_service_,
173                   scoped_ptr<CloudPolicyClient::StatusProvider>());
174  EXPECT_TRUE(manager_.policies().Equals(bundle));
175
176  manager_.Shutdown();
177  EXPECT_TRUE(manager_.policies().Equals(bundle));
178}
179
180class DeviceCloudPolicyManagerChromeOSEnrollmentTest
181    : public DeviceCloudPolicyManagerChromeOSTest {
182 public:
183  void Done(EnrollmentStatus status) {
184    status_ = status;
185    done_ = true;
186  }
187
188 protected:
189  DeviceCloudPolicyManagerChromeOSEnrollmentTest()
190      : is_auto_enrollment_(false),
191        register_status_(DM_STATUS_SUCCESS),
192        policy_fetch_status_(DM_STATUS_SUCCESS),
193        robot_auth_fetch_status_(DM_STATUS_SUCCESS),
194        store_result_(true),
195        status_(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS)),
196        done_(false) {}
197
198  virtual void SetUp() OVERRIDE {
199    DeviceCloudPolicyManagerChromeOSTest::SetUp();
200
201    // Set up test data.
202    device_policy_.set_new_signing_key(
203        PolicyBuilder::CreateTestNewSigningKey());
204    device_policy_.policy_data().set_timestamp(
205        (base::Time::NowFromSystemTime() -
206         base::Time::UnixEpoch()).InMilliseconds());
207    device_policy_.Build();
208
209    register_response_.mutable_register_response()->set_device_management_token(
210        PolicyBuilder::kFakeToken);
211    policy_fetch_response_.mutable_policy_response()->add_response()->CopyFrom(
212        device_policy_.policy());
213    robot_auth_fetch_response_.mutable_service_api_access_response()
214        ->set_auth_code("auth_code_for_test");
215    loaded_blob_ = device_policy_.GetBlob();
216
217    // Initialize the manager.
218    FlushDeviceSettings();
219    EXPECT_EQ(CloudPolicyStore::STATUS_BAD_STATE, store_->status());
220    EXPECT_TRUE(manager_.IsInitializationComplete(POLICY_DOMAIN_CHROME));
221
222    PolicyBundle bundle;
223    EXPECT_TRUE(manager_.policies().Equals(bundle));
224
225    manager_.Connect(&local_state_,
226                     &device_management_service_,
227                     scoped_ptr<CloudPolicyClient::StatusProvider>());
228  }
229
230  void ExpectFailedEnrollment(EnrollmentStatus::Status status) {
231    EXPECT_EQ(status, status_.status());
232    EXPECT_FALSE(store_->is_managed());
233    PolicyBundle empty_bundle;
234    EXPECT_TRUE(manager_.policies().Equals(empty_bundle));
235  }
236
237  void ExpectSuccessfulEnrollment() {
238    EXPECT_EQ(EnrollmentStatus::STATUS_SUCCESS, status_.status());
239    EXPECT_EQ(DEVICE_MODE_ENTERPRISE, install_attributes_.GetMode());
240    EXPECT_TRUE(store_->has_policy());
241    EXPECT_TRUE(store_->is_managed());
242    ASSERT_TRUE(manager_.core()->client());
243    EXPECT_TRUE(manager_.core()->client()->is_registered());
244
245    PolicyBundle bundle;
246    bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
247        .Set(key::kDeviceMetricsReportingEnabled,
248             POLICY_LEVEL_MANDATORY,
249             POLICY_SCOPE_MACHINE,
250             Value::CreateBooleanValue(false));
251    EXPECT_TRUE(manager_.policies().Equals(bundle));
252  }
253
254  void RunTest() {
255    // Trigger enrollment.
256    MockDeviceManagementJob* register_job = NULL;
257    EXPECT_CALL(device_management_service_,
258                CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION))
259        .Times(AtMost(1))
260        .WillOnce(device_management_service_.CreateAsyncJob(&register_job));
261    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _))
262        .Times(AtMost(1))
263        .WillOnce(DoAll(SaveArg<5>(&client_id_),
264                        SaveArg<6>(&register_request_)));
265    DeviceCloudPolicyManagerChromeOS::AllowedDeviceModes modes;
266    modes[DEVICE_MODE_ENTERPRISE] = true;
267    manager_.StartEnrollment(
268        "auth token", is_auto_enrollment_, modes,
269        base::Bind(&DeviceCloudPolicyManagerChromeOSEnrollmentTest::Done,
270                   base::Unretained(this)));
271    Mock::VerifyAndClearExpectations(&device_management_service_);
272
273    if (done_)
274      return;
275
276    // Process registration.
277    ASSERT_TRUE(register_job);
278    MockDeviceManagementJob* policy_fetch_job = NULL;
279    EXPECT_CALL(device_management_service_,
280                CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH))
281        .Times(AtMost(1))
282        .WillOnce(device_management_service_.CreateAsyncJob(&policy_fetch_job));
283    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _))
284        .Times(AtMost(1));
285    register_job->SendResponse(register_status_, register_response_);
286    Mock::VerifyAndClearExpectations(&device_management_service_);
287
288    if (done_)
289      return;
290
291    // Process policy fetch.
292    ASSERT_TRUE(policy_fetch_job);
293    policy_fetch_job->SendResponse(policy_fetch_status_,
294                                   policy_fetch_response_);
295
296    if (done_)
297      return;
298
299    // Process verification.
300    MockDeviceManagementJob* robot_auth_fetch_job = NULL;
301    EXPECT_CALL(device_management_service_,
302                CreateJob(DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH))
303        .Times(AtMost(1))
304        .WillOnce(device_management_service_.CreateAsyncJob(
305            &robot_auth_fetch_job));
306    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _))
307        .Times(AtMost(1));
308    base::RunLoop().RunUntilIdle();
309    Mock::VerifyAndClearExpectations(&device_management_service_);
310
311    if (done_)
312      return;
313
314    // Process robot auth token fetch.
315    ASSERT_TRUE(robot_auth_fetch_job);
316    robot_auth_fetch_job->SendResponse(robot_auth_fetch_status_,
317                                       robot_auth_fetch_response_);
318    Mock::VerifyAndClearExpectations(&device_management_service_);
319
320    if (done_)
321      return;
322
323    // Process robot refresh token fetch if the auth code fetch succeeded.
324    // DeviceCloudPolicyManagerChromeOS holds an EnrollmentHandlerChromeOS which
325    // holds a GaiaOAuthClient that fetches the refresh token during enrollment.
326    // We return a successful OAuth response via a TestURLFetcher to trigger the
327    // happy path for these classes so that enrollment can continue.
328    if (robot_auth_fetch_status_ == DM_STATUS_SUCCESS) {
329      net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
330      ASSERT_TRUE(url_fetcher);
331      url_fetcher->SetMaxRetriesOn5xx(0);
332      url_fetcher->set_status(net::URLRequestStatus());
333      url_fetcher->set_response_code(url_fetcher_response_code_);
334      url_fetcher->SetResponseString(url_fetcher_response_string_);
335      url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
336    }
337    base::RunLoop().RunUntilIdle();
338
339    // Process policy store.
340    device_settings_test_helper_.set_store_result(store_result_);
341    device_settings_test_helper_.FlushStore();
342    EXPECT_EQ(device_policy_.GetBlob(),
343              device_settings_test_helper_.policy_blob());
344
345    if (done_)
346      return;
347
348    // Key installation, policy load and refresh token save.
349    device_settings_test_helper_.set_policy_blob(loaded_blob_);
350    owner_key_util_->SetPublicKeyFromPrivateKey(
351        device_policy_.new_signing_key());
352    ReloadDeviceSettings();
353
354    if (done_)
355      return;
356
357    // Process robot refresh token store.
358    EXPECT_EQ(
359        "refreshToken4Test",
360        chromeos::DeviceOAuth2TokenServiceFactory::Get()->GetRefreshToken());
361  }
362
363  bool is_auto_enrollment_;
364
365  DeviceManagementStatus register_status_;
366  em::DeviceManagementResponse register_response_;
367
368  DeviceManagementStatus policy_fetch_status_;
369  em::DeviceManagementResponse policy_fetch_response_;
370
371  DeviceManagementStatus robot_auth_fetch_status_;
372  em::DeviceManagementResponse robot_auth_fetch_response_;
373
374  bool store_result_;
375  std::string loaded_blob_;
376
377  em::DeviceManagementRequest register_request_;
378  std::string client_id_;
379  EnrollmentStatus status_;
380
381  bool done_;
382
383 private:
384  DISALLOW_COPY_AND_ASSIGN(DeviceCloudPolicyManagerChromeOSEnrollmentTest);
385};
386
387TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, Success) {
388  RunTest();
389  ExpectSuccessfulEnrollment();
390}
391
392TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, AutoEnrollment) {
393  is_auto_enrollment_ = true;
394  RunTest();
395  ExpectSuccessfulEnrollment();
396  EXPECT_TRUE(register_request_.register_request().auto_enrolled());
397}
398
399TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, Reenrollment) {
400  base::RunLoop loop;
401  EnterpriseInstallAttributes::LockResult result;
402  install_attributes_.LockDevice(PolicyBuilder::kFakeUsername,
403                                 DEVICE_MODE_ENTERPRISE,
404                                 PolicyBuilder::kFakeDeviceId,
405                                 base::Bind(&CopyLockResult, &loop, &result));
406  loop.Run();
407  ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS, result);
408
409  RunTest();
410  ExpectSuccessfulEnrollment();
411  EXPECT_TRUE(register_request_.register_request().reregister());
412  EXPECT_EQ(PolicyBuilder::kFakeDeviceId, client_id_);
413}
414
415TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, RegistrationFailed) {
416  register_status_ = DM_STATUS_REQUEST_FAILED;
417  RunTest();
418  ExpectFailedEnrollment(EnrollmentStatus::STATUS_REGISTRATION_FAILED);
419  EXPECT_EQ(DM_STATUS_REQUEST_FAILED, status_.client_status());
420}
421
422// Policy server implementations are not required to support robot auth
423// tokens, so the following 4 Robot* tests verify that enrollment succeeds
424// even if the robot auth token fetch fails.
425TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest,
426       RobotAuthCodeFetchFailed) {
427  robot_auth_fetch_status_ = DM_STATUS_REQUEST_FAILED;
428  RunTest();
429  ExpectSuccessfulEnrollment();
430}
431
432TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest,
433       RobotRefreshTokenFetchResponseCodeFailed) {
434  url_fetcher_response_code_ = 400;
435  RunTest();
436  ExpectSuccessfulEnrollment();
437}
438
439TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest,
440       RobotRefreshTokenFetchResponseStringFailed) {
441  url_fetcher_response_string_ = "invalid response json";
442  RunTest();
443  ExpectSuccessfulEnrollment();
444}
445
446TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, RobotRefreshSaveFailed) {
447  // Without a DeviceOAuth2TokenService, the refresh token can't be saved.
448  chromeos::DeviceOAuth2TokenServiceFactory::Shutdown();
449  RunTest();
450  ExpectSuccessfulEnrollment();
451}
452
453TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, PolicyFetchFailed) {
454  policy_fetch_status_ = DM_STATUS_REQUEST_FAILED;
455  RunTest();
456  ExpectFailedEnrollment(EnrollmentStatus::STATUS_POLICY_FETCH_FAILED);
457  EXPECT_EQ(DM_STATUS_REQUEST_FAILED, status_.client_status());
458}
459
460TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, ValidationFailed) {
461  device_policy_.policy().set_policy_data_signature("bad");
462  policy_fetch_response_.clear_policy_response();
463  policy_fetch_response_.mutable_policy_response()->add_response()->CopyFrom(
464      device_policy_.policy());
465  RunTest();
466  ExpectFailedEnrollment(EnrollmentStatus::STATUS_VALIDATION_FAILED);
467  EXPECT_EQ(CloudPolicyValidatorBase::VALIDATION_BAD_INITIAL_SIGNATURE,
468            status_.validation_status());
469}
470
471TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, StoreError) {
472  store_result_ = false;
473  RunTest();
474  ExpectFailedEnrollment(EnrollmentStatus::STATUS_STORE_ERROR);
475  EXPECT_EQ(CloudPolicyStore::STATUS_STORE_ERROR,
476            status_.store_status());
477}
478
479TEST_F(DeviceCloudPolicyManagerChromeOSEnrollmentTest, LoadError) {
480  loaded_blob_.clear();
481  RunTest();
482  ExpectFailedEnrollment(EnrollmentStatus::STATUS_STORE_ERROR);
483  EXPECT_EQ(CloudPolicyStore::STATUS_LOAD_ERROR,
484            status_.store_status());
485}
486
487}  // namespace test
488}  // namespace policy
489