Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / policy / core / common / cloud / user_cloud_policy_store_unittest.cc
1 // Copyright 2013 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 "components/policy/core/common/cloud/user_cloud_policy_store.h"
6
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/run_loop.h"
12 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
13 #include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h"
14 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
15 #include "components/policy/core/common/cloud/policy_builder.h"
16 #include "components/policy/core/common/policy_switches.h"
17 #include "net/url_request/url_request_context_getter.h"
18 #include "policy/policy_constants.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using testing::AllOf;
23 using testing::Eq;
24 using testing::Mock;
25 using testing::Property;
26 using testing::Sequence;
27
28 namespace policy {
29
30 namespace {
31
32 void RunUntilIdle() {
33   base::RunLoop run_loop;
34   run_loop.RunUntilIdle();
35 }
36
37 bool WriteStringToFile(const base::FilePath path, const std::string& data) {
38  if (!base::CreateDirectory(path.DirName())) {
39     DLOG(WARNING) << "Failed to create directory " << path.DirName().value();
40     return false;
41   }
42
43   int size = data.size();
44   if (base::WriteFile(path, data.c_str(), size) != size) {
45     DLOG(WARNING) << "Failed to write " << path.value();
46     return false;
47   }
48
49   return true;
50 }
51
52 }  // namespace
53
54 class UserCloudPolicyStoreTest : public testing::Test {
55  public:
56   UserCloudPolicyStoreTest() {}
57
58   void SetUp() override {
59     ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
60     store_.reset(
61         new UserCloudPolicyStore(policy_file(),
62                                  key_file(),
63                                  GetPolicyVerificationKey(),
64                                  loop_.message_loop_proxy()));
65     external_data_manager_.reset(new MockCloudExternalDataManager);
66     external_data_manager_->SetPolicyStore(store_.get());
67     store_->SetSigninUsername(PolicyBuilder::kFakeUsername);
68     store_->AddObserver(&observer_);
69
70     // Install an initial public key, so that by default the validation of
71     // the stored/loaded policy blob succeeds (it looks like a new key
72     // provision).
73     policy_.SetDefaultInitialSigningKey();
74
75     InitPolicyPayload(&policy_.payload());
76
77     policy_.Build();
78   }
79
80   void TearDown() override {
81     store_->RemoveObserver(&observer_);
82     external_data_manager_.reset();
83     store_.reset();
84     RunUntilIdle();
85   }
86
87   void InitPolicyPayload(enterprise_management::CloudPolicySettings* payload) {
88     payload->mutable_passwordmanagerenabled()->set_value(true);
89     payload->mutable_urlblacklist()->mutable_value()->add_entries(
90         "chromium.org");
91   }
92
93   base::FilePath policy_file() {
94     return tmp_dir_.path().AppendASCII("policy");
95   }
96
97   base::FilePath key_file() {
98     return tmp_dir_.path().AppendASCII("policy_key");
99   }
100
101   // Verifies that store_->policy_map() has the appropriate entries.
102   void VerifyPolicyMap(CloudPolicyStore* store) {
103     EXPECT_EQ(2U, store->policy_map().size());
104     const PolicyMap::Entry* entry =
105         store->policy_map().Get(key::kPasswordManagerEnabled);
106     ASSERT_TRUE(entry);
107     EXPECT_TRUE(base::FundamentalValue(true).Equals(entry->value));
108     ASSERT_TRUE(store->policy_map().Get(key::kURLBlacklist));
109   }
110
111   // Install an expectation on |observer_| for an error code.
112   void ExpectError(CloudPolicyStore* store, CloudPolicyStore::Status error) {
113     EXPECT_CALL(observer_,
114                 OnStoreError(AllOf(Eq(store),
115                                    Property(&CloudPolicyStore::status,
116                                             Eq(error)))));
117   }
118
119   void StorePolicyAndEnsureLoaded(
120       const enterprise_management::PolicyFetchResponse& policy) {
121     Sequence s;
122     EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
123     EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
124     store_->Store(policy);
125     RunUntilIdle();
126     Mock::VerifyAndClearExpectations(external_data_manager_.get());
127     Mock::VerifyAndClearExpectations(&observer_);
128     ASSERT_TRUE(store_->policy());
129   }
130
131   UserPolicyBuilder policy_;
132   MockCloudPolicyStoreObserver observer_;
133   scoped_ptr<UserCloudPolicyStore> store_;
134   scoped_ptr<MockCloudExternalDataManager> external_data_manager_;
135
136   // CloudPolicyValidator() requires a FILE thread so declare one here. Both
137   // |ui_thread_| and |file_thread_| share the same MessageLoop |loop_| so
138   // callers can use RunLoop to manage both virtual threads.
139   base::MessageLoopForUI loop_;
140
141   base::ScopedTempDir tmp_dir_;
142
143   DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyStoreTest);
144 };
145
146 TEST_F(UserCloudPolicyStoreTest, LoadWithNoFile) {
147   EXPECT_FALSE(store_->policy());
148   EXPECT_TRUE(store_->policy_map().empty());
149
150   Sequence s;
151   EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
152   EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
153   store_->Load();
154   RunUntilIdle();
155
156   EXPECT_FALSE(store_->policy());
157   EXPECT_TRUE(store_->policy_map().empty());
158 }
159
160 TEST_F(UserCloudPolicyStoreTest, LoadWithInvalidFile) {
161   EXPECT_FALSE(store_->policy());
162   EXPECT_TRUE(store_->policy_map().empty());
163
164   // Create a bogus file.
165   ASSERT_TRUE(base::CreateDirectory(policy_file().DirName()));
166   std::string bogus_data = "bogus_data";
167   int size = bogus_data.size();
168   ASSERT_EQ(size, base::WriteFile(policy_file(),
169                                   bogus_data.c_str(), bogus_data.size()));
170
171   ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
172   store_->Load();
173   RunUntilIdle();
174
175   EXPECT_FALSE(store_->policy());
176   EXPECT_TRUE(store_->policy_map().empty());
177 }
178
179 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithNoFile) {
180   EXPECT_FALSE(store_->policy());
181   EXPECT_TRUE(store_->policy_map().empty());
182
183   Sequence s;
184   EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
185   EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
186   store_->LoadImmediately();  // Should load without running the message loop.
187
188   EXPECT_FALSE(store_->policy());
189   EXPECT_TRUE(store_->policy_map().empty());
190 }
191
192 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithInvalidFile) {
193   EXPECT_FALSE(store_->policy());
194   EXPECT_TRUE(store_->policy_map().empty());
195
196   // Create a bogus file.
197   ASSERT_TRUE(base::CreateDirectory(policy_file().DirName()));
198   std::string bogus_data = "bogus_data";
199   int size = bogus_data.size();
200   ASSERT_EQ(size, base::WriteFile(policy_file(),
201                                   bogus_data.c_str(), bogus_data.size()));
202
203   ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
204   store_->LoadImmediately();  // Should load without running the message loop.
205
206   EXPECT_FALSE(store_->policy());
207   EXPECT_TRUE(store_->policy_map().empty());
208 }
209
210 // Load file from cache with no key data - should give us a validation error.
211 TEST_F(UserCloudPolicyStoreTest, ShouldFailToLoadUnsignedPolicy) {
212   UserPolicyBuilder unsigned_builder;
213   unsigned_builder.UnsetSigningKey();
214   InitPolicyPayload(&unsigned_builder.payload());
215   unsigned_builder.Build();
216   // Policy should be unsigned.
217   EXPECT_FALSE(unsigned_builder.policy().has_policy_data_signature());
218
219   // Write policy to disk.
220   std::string data;
221   ASSERT_TRUE(unsigned_builder.policy().SerializeToString(&data));
222   ASSERT_TRUE(base::CreateDirectory(policy_file().DirName()));
223   int size = data.size();
224   ASSERT_EQ(size, base::WriteFile(policy_file(), data.c_str(), size));
225
226   // Now make sure the data generates a validation error.
227   ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
228   store_->LoadImmediately();  // Should load without running the message loop.
229   Mock::VerifyAndClearExpectations(&observer_);
230
231   // Now mimic a new policy coming down - this should result in a new key
232   // being installed.
233   StorePolicyAndEnsureLoaded(policy_.policy());
234   EXPECT_EQ(policy_.policy().new_public_key(), store_->policy_key());
235   EXPECT_TRUE(store_->policy()->has_public_key_version());
236   EXPECT_TRUE(base::PathExists(key_file()));
237 }
238
239 TEST_F(UserCloudPolicyStoreTest, Store) {
240   EXPECT_FALSE(store_->policy());
241   EXPECT_TRUE(store_->policy_map().empty());
242
243   // Store a simple policy and make sure it ends up as the currently active
244   // policy.
245   StorePolicyAndEnsureLoaded(policy_.policy());
246
247   // Policy should be decoded and stored.
248   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
249             store_->policy()->SerializeAsString());
250   VerifyPolicyMap(store_.get());
251   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
252 }
253
254 TEST_F(UserCloudPolicyStoreTest, StoreThenClear) {
255   EXPECT_FALSE(store_->policy());
256   EXPECT_TRUE(store_->policy_map().empty());
257
258   // Store a simple policy and make sure the file exists.
259   // policy.
260   StorePolicyAndEnsureLoaded(policy_.policy());
261   EXPECT_FALSE(store_->policy_map().empty());
262
263   // Policy file should exist.
264   ASSERT_TRUE(base::PathExists(policy_file()));
265
266   Sequence s2;
267   EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s2);
268   EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s2);
269   store_->Clear();
270   RunUntilIdle();
271
272   // Policy file should not exist.
273   ASSERT_TRUE(!base::PathExists(policy_file()));
274
275   // Policy should be gone.
276   EXPECT_FALSE(store_->policy());
277   EXPECT_TRUE(store_->policy_map().empty());
278   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
279 }
280
281 TEST_F(UserCloudPolicyStoreTest, StoreRotatedKey) {
282   EXPECT_FALSE(store_->policy());
283   EXPECT_TRUE(store_->policy_map().empty());
284
285   // Store a simple policy and make sure it ends up as the currently active
286   // policy.
287   StorePolicyAndEnsureLoaded(policy_.policy());
288   EXPECT_FALSE(policy_.policy().has_new_public_key_signature());
289   std::string original_policy_key = policy_.policy().new_public_key();
290   EXPECT_EQ(original_policy_key, store_->policy_key());
291
292   // Now do key rotation.
293   policy_.SetDefaultSigningKey();
294   policy_.SetDefaultNewSigningKey();
295   policy_.Build();
296   EXPECT_TRUE(policy_.policy().has_new_public_key_signature());
297   EXPECT_NE(original_policy_key, policy_.policy().new_public_key());
298   StorePolicyAndEnsureLoaded(policy_.policy());
299   EXPECT_EQ(policy_.policy().new_public_key(), store_->policy_key());
300 }
301
302 TEST_F(UserCloudPolicyStoreTest, ProvisionKeyTwice) {
303   EXPECT_FALSE(store_->policy());
304   EXPECT_TRUE(store_->policy_map().empty());
305
306   // Store a simple policy and make sure it ends up as the currently active
307   // policy.
308   StorePolicyAndEnsureLoaded(policy_.policy());
309
310   // Now try sending down policy signed with a different key (i.e. do key
311   // rotation with a key not signed with the original signing key).
312   policy_.UnsetSigningKey();
313   policy_.SetDefaultNewSigningKey();
314   policy_.Build();
315   EXPECT_FALSE(policy_.policy().has_new_public_key_signature());
316
317   ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
318   store_->Store(policy_.policy());
319   RunUntilIdle();
320 }
321
322 TEST_F(UserCloudPolicyStoreTest, StoreTwoTimes) {
323   EXPECT_FALSE(store_->policy());
324   EXPECT_TRUE(store_->policy_map().empty());
325
326   // Store a simple policy then store a second policy before the first one
327   // finishes validating, and make sure the second policy ends up as the active
328   // policy.
329   UserPolicyBuilder first_policy;
330   first_policy.SetDefaultInitialSigningKey();
331   first_policy.payload().mutable_passwordmanagerenabled()->set_value(false);
332   first_policy.Build();
333   StorePolicyAndEnsureLoaded(first_policy.policy());
334
335   // Rebuild policy with the same signing key as |first_policy| (no rotation).
336   policy_.UnsetNewSigningKey();
337   policy_.SetDefaultSigningKey();
338   policy_.Build();
339   ASSERT_FALSE(policy_.policy().has_new_public_key());
340   StorePolicyAndEnsureLoaded(policy_.policy());
341
342   // Policy should be decoded and stored.
343   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
344             store_->policy()->SerializeAsString());
345   VerifyPolicyMap(store_.get());
346   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
347 }
348
349 TEST_F(UserCloudPolicyStoreTest, StoreThenLoad) {
350   // Store a simple policy and make sure it can be read back in.
351   // policy.
352   StorePolicyAndEnsureLoaded(policy_.policy());
353   EXPECT_FALSE(store_->policy_key().empty());
354
355   // Now, make sure the policy can be read back in from a second store.
356   scoped_ptr<UserCloudPolicyStore> store2(
357       new UserCloudPolicyStore(policy_file(),
358                                key_file(),
359                                GetPolicyVerificationKey(),
360                                loop_.message_loop_proxy()));
361   store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
362   store2->AddObserver(&observer_);
363   EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
364   store2->Load();
365   RunUntilIdle();
366
367   ASSERT_TRUE(store2->policy());
368   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
369             store2->policy()->SerializeAsString());
370   VerifyPolicyMap(store2.get());
371   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
372   store2->RemoveObserver(&observer_);
373   // Make sure that we properly resurrected the keys.
374   EXPECT_EQ(store2->policy_key(), store_->policy_key());
375 }
376
377 TEST_F(UserCloudPolicyStoreTest, StoreThenLoadImmediately) {
378   // Store a simple policy and make sure it can be read back in.
379   // policy.
380   StorePolicyAndEnsureLoaded(policy_.policy());
381
382   // Now, make sure the policy can be read back in from a second store.
383   scoped_ptr<UserCloudPolicyStore> store2(
384       new UserCloudPolicyStore(policy_file(),
385                                key_file(),
386                                GetPolicyVerificationKey(),
387                                loop_.message_loop_proxy()));
388   store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
389   store2->AddObserver(&observer_);
390   EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
391   store2->LoadImmediately();  // Should load without running the message loop.
392
393   ASSERT_TRUE(store2->policy());
394   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
395             store2->policy()->SerializeAsString());
396   VerifyPolicyMap(store2.get());
397   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
398   store2->RemoveObserver(&observer_);
399 }
400
401 TEST_F(UserCloudPolicyStoreTest, StoreValidationError) {
402   // Create an invalid policy (no policy type).
403   policy_.policy_data().clear_policy_type();
404   policy_.Build();
405
406   // Store policy.
407   ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
408   store_->Store(policy_.policy());
409   RunUntilIdle();
410   ASSERT_FALSE(store_->policy());
411 }
412
413 TEST_F(UserCloudPolicyStoreTest, StoreUnsigned) {
414   // Create unsigned policy, try to store it, should get a validation error.
415   policy_.policy().mutable_policy_data_signature()->clear();
416
417   // Store policy.
418   ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
419   store_->Store(policy_.policy());
420   RunUntilIdle();
421   ASSERT_FALSE(store_->policy());
422 }
423
424 TEST_F(UserCloudPolicyStoreTest, LoadValidationError) {
425   // Force a validation error by changing the username after policy is stored.
426   StorePolicyAndEnsureLoaded(policy_.policy());
427
428   // Sign out, and sign back in as a different user, and try to load the profile
429   // data (should fail due to mismatched username).
430   scoped_ptr<UserCloudPolicyStore> store2(
431       new UserCloudPolicyStore(policy_file(),
432                                key_file(),
433                                GetPolicyVerificationKey(),
434                                loop_.message_loop_proxy()));
435   store2->SetSigninUsername("foobar@foobar.com");
436   store2->AddObserver(&observer_);
437   ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
438   store2->Load();
439   RunUntilIdle();
440
441   ASSERT_FALSE(store2->policy());
442   store2->RemoveObserver(&observer_);
443
444   // Sign out - we should be able to load the policy (don't check usernames
445   // when signed out).
446   scoped_ptr<UserCloudPolicyStore> store3(
447       new UserCloudPolicyStore(policy_file(),
448                                key_file(),
449                                GetPolicyVerificationKey(),
450                                loop_.message_loop_proxy()));
451   store3->AddObserver(&observer_);
452   EXPECT_CALL(observer_, OnStoreLoaded(store3.get()));
453   store3->Load();
454   RunUntilIdle();
455
456   ASSERT_TRUE(store3->policy());
457   store3->RemoveObserver(&observer_);
458
459   // Now start a signin as a different user - this should fail validation.
460   scoped_ptr<UserCloudPolicyStore> store4(
461       new UserCloudPolicyStore(policy_file(),
462                                key_file(),
463                                GetPolicyVerificationKey(),
464                                loop_.message_loop_proxy()));
465   store4->SetSigninUsername("foobar@foobar.com");
466   store4->AddObserver(&observer_);
467   ExpectError(store4.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
468   store4->Load();
469   RunUntilIdle();
470
471   ASSERT_FALSE(store4->policy());
472   store4->RemoveObserver(&observer_);
473 }
474
475 TEST_F(UserCloudPolicyStoreTest, KeyRotation) {
476   // Make sure when we load data from disk with a different key, that we trigger
477   // a server-side key rotation.
478   StorePolicyAndEnsureLoaded(policy_.policy());
479   ASSERT_TRUE(store_->policy()->has_public_key_version());
480
481   std::string key_data;
482   enterprise_management::PolicySigningKey key;
483   ASSERT_TRUE(base::ReadFileToString(key_file(), &key_data));
484   ASSERT_TRUE(key.ParseFromString(key_data));
485   key.set_verification_key("different_key");
486   key.SerializeToString(&key_data);
487   WriteStringToFile(key_file(), key_data);
488
489   // Now load this in a new store - this should trigger key rotation. The keys
490   // will still verify using the existing verification key.
491   scoped_ptr<UserCloudPolicyStore> store2(
492       new UserCloudPolicyStore(policy_file(),
493                                key_file(),
494                                GetPolicyVerificationKey(),
495                                loop_.message_loop_proxy()));
496   store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
497   store2->AddObserver(&observer_);
498   EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
499   store2->Load();
500   RunUntilIdle();
501   ASSERT_TRUE(store2->policy());
502   ASSERT_FALSE(store2->policy()->has_public_key_version());
503   store2->RemoveObserver(&observer_);
504 }
505
506 TEST_F(UserCloudPolicyStoreTest, InvalidCachedVerificationSignature) {
507   // Make sure that we reject code with an invalid key.
508   StorePolicyAndEnsureLoaded(policy_.policy());
509
510   std::string key_data;
511   enterprise_management::PolicySigningKey key;
512   ASSERT_TRUE(base::ReadFileToString(key_file(), &key_data));
513   ASSERT_TRUE(key.ParseFromString(key_data));
514   key.set_signing_key_signature("different_key");
515   key.SerializeToString(&key_data);
516   WriteStringToFile(key_file(), key_data);
517
518   // Now load this in a new store - this should cause a validation error because
519   // the key won't verify.
520   scoped_ptr<UserCloudPolicyStore> store2(
521       new UserCloudPolicyStore(policy_file(),
522                                key_file(),
523                                GetPolicyVerificationKey(),
524                                loop_.message_loop_proxy()));
525   store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
526   store2->AddObserver(&observer_);
527   ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
528   store2->Load();
529   RunUntilIdle();
530   store2->RemoveObserver(&observer_);
531 }
532
533 }  // namespace policy