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