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.
5 #include "components/policy/core/common/cloud/user_cloud_policy_store.h"
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"
25 using testing::Property;
26 using testing::Sequence;
33 base::RunLoop run_loop;
34 run_loop.RunUntilIdle();
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();
43 int size = data.size();
44 if (base::WriteFile(path, data.c_str(), size) != size) {
45 DLOG(WARNING) << "Failed to write " << path.value();
54 class UserCloudPolicyStoreTest : public testing::Test {
56 UserCloudPolicyStoreTest() {}
58 void SetUp() override {
59 ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
61 new UserCloudPolicyStore(policy_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_);
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
73 policy_.SetDefaultInitialSigningKey();
75 InitPolicyPayload(&policy_.payload());
80 void TearDown() override {
81 store_->RemoveObserver(&observer_);
82 external_data_manager_.reset();
87 void InitPolicyPayload(enterprise_management::CloudPolicySettings* payload) {
88 payload->mutable_passwordmanagerenabled()->set_value(true);
89 payload->mutable_urlblacklist()->mutable_value()->add_entries(
93 base::FilePath policy_file() {
94 return tmp_dir_.path().AppendASCII("policy");
97 base::FilePath key_file() {
98 return tmp_dir_.path().AppendASCII("policy_key");
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);
107 EXPECT_TRUE(base::FundamentalValue(true).Equals(entry->value));
108 ASSERT_TRUE(store->policy_map().Get(key::kURLBlacklist));
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,
119 void StorePolicyAndEnsureLoaded(
120 const enterprise_management::PolicyFetchResponse& policy) {
122 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
123 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
124 store_->Store(policy);
126 Mock::VerifyAndClearExpectations(external_data_manager_.get());
127 Mock::VerifyAndClearExpectations(&observer_);
128 ASSERT_TRUE(store_->policy());
131 UserPolicyBuilder policy_;
132 MockCloudPolicyStoreObserver observer_;
133 scoped_ptr<UserCloudPolicyStore> store_;
134 scoped_ptr<MockCloudExternalDataManager> external_data_manager_;
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_;
141 base::ScopedTempDir tmp_dir_;
143 DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyStoreTest);
146 TEST_F(UserCloudPolicyStoreTest, LoadWithNoFile) {
147 EXPECT_FALSE(store_->policy());
148 EXPECT_TRUE(store_->policy_map().empty());
151 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
152 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
156 EXPECT_FALSE(store_->policy());
157 EXPECT_TRUE(store_->policy_map().empty());
160 TEST_F(UserCloudPolicyStoreTest, LoadWithInvalidFile) {
161 EXPECT_FALSE(store_->policy());
162 EXPECT_TRUE(store_->policy_map().empty());
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()));
171 ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
175 EXPECT_FALSE(store_->policy());
176 EXPECT_TRUE(store_->policy_map().empty());
179 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithNoFile) {
180 EXPECT_FALSE(store_->policy());
181 EXPECT_TRUE(store_->policy_map().empty());
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.
188 EXPECT_FALSE(store_->policy());
189 EXPECT_TRUE(store_->policy_map().empty());
192 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithInvalidFile) {
193 EXPECT_FALSE(store_->policy());
194 EXPECT_TRUE(store_->policy_map().empty());
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()));
203 ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
204 store_->LoadImmediately(); // Should load without running the message loop.
206 EXPECT_FALSE(store_->policy());
207 EXPECT_TRUE(store_->policy_map().empty());
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());
219 // Write policy to disk.
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));
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_);
231 // Now mimic a new policy coming down - this should result in a new key
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()));
239 TEST_F(UserCloudPolicyStoreTest, Store) {
240 EXPECT_FALSE(store_->policy());
241 EXPECT_TRUE(store_->policy_map().empty());
243 // Store a simple policy and make sure it ends up as the currently active
245 StorePolicyAndEnsureLoaded(policy_.policy());
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());
254 TEST_F(UserCloudPolicyStoreTest, StoreThenClear) {
255 EXPECT_FALSE(store_->policy());
256 EXPECT_TRUE(store_->policy_map().empty());
258 // Store a simple policy and make sure the file exists.
260 StorePolicyAndEnsureLoaded(policy_.policy());
261 EXPECT_FALSE(store_->policy_map().empty());
263 // Policy file should exist.
264 ASSERT_TRUE(base::PathExists(policy_file()));
267 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s2);
268 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s2);
272 // Policy file should not exist.
273 ASSERT_TRUE(!base::PathExists(policy_file()));
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());
281 TEST_F(UserCloudPolicyStoreTest, StoreRotatedKey) {
282 EXPECT_FALSE(store_->policy());
283 EXPECT_TRUE(store_->policy_map().empty());
285 // Store a simple policy and make sure it ends up as the currently active
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());
292 // Now do key rotation.
293 policy_.SetDefaultSigningKey();
294 policy_.SetDefaultNewSigningKey();
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());
302 TEST_F(UserCloudPolicyStoreTest, ProvisionKeyTwice) {
303 EXPECT_FALSE(store_->policy());
304 EXPECT_TRUE(store_->policy_map().empty());
306 // Store a simple policy and make sure it ends up as the currently active
308 StorePolicyAndEnsureLoaded(policy_.policy());
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();
315 EXPECT_FALSE(policy_.policy().has_new_public_key_signature());
317 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
318 store_->Store(policy_.policy());
322 TEST_F(UserCloudPolicyStoreTest, StoreTwoTimes) {
323 EXPECT_FALSE(store_->policy());
324 EXPECT_TRUE(store_->policy_map().empty());
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
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());
335 // Rebuild policy with the same signing key as |first_policy| (no rotation).
336 policy_.UnsetNewSigningKey();
337 policy_.SetDefaultSigningKey();
339 ASSERT_FALSE(policy_.policy().has_new_public_key());
340 StorePolicyAndEnsureLoaded(policy_.policy());
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());
349 TEST_F(UserCloudPolicyStoreTest, StoreThenLoad) {
350 // Store a simple policy and make sure it can be read back in.
352 StorePolicyAndEnsureLoaded(policy_.policy());
353 EXPECT_FALSE(store_->policy_key().empty());
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(),
359 GetPolicyVerificationKey(),
360 loop_.message_loop_proxy()));
361 store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
362 store2->AddObserver(&observer_);
363 EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
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());
377 TEST_F(UserCloudPolicyStoreTest, StoreThenLoadImmediately) {
378 // Store a simple policy and make sure it can be read back in.
380 StorePolicyAndEnsureLoaded(policy_.policy());
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(),
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.
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_);
401 TEST_F(UserCloudPolicyStoreTest, StoreValidationError) {
402 // Create an invalid policy (no policy type).
403 policy_.policy_data().clear_policy_type();
407 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
408 store_->Store(policy_.policy());
410 ASSERT_FALSE(store_->policy());
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();
418 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
419 store_->Store(policy_.policy());
421 ASSERT_FALSE(store_->policy());
424 TEST_F(UserCloudPolicyStoreTest, LoadValidationError) {
425 // Force a validation error by changing the username after policy is stored.
426 StorePolicyAndEnsureLoaded(policy_.policy());
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(),
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);
441 ASSERT_FALSE(store2->policy());
442 store2->RemoveObserver(&observer_);
444 // Sign out - we should be able to load the policy (don't check usernames
446 scoped_ptr<UserCloudPolicyStore> store3(
447 new UserCloudPolicyStore(policy_file(),
449 GetPolicyVerificationKey(),
450 loop_.message_loop_proxy()));
451 store3->AddObserver(&observer_);
452 EXPECT_CALL(observer_, OnStoreLoaded(store3.get()));
456 ASSERT_TRUE(store3->policy());
457 store3->RemoveObserver(&observer_);
459 // Now start a signin as a different user - this should fail validation.
460 scoped_ptr<UserCloudPolicyStore> store4(
461 new UserCloudPolicyStore(policy_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);
471 ASSERT_FALSE(store4->policy());
472 store4->RemoveObserver(&observer_);
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());
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);
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(),
494 GetPolicyVerificationKey(),
495 loop_.message_loop_proxy()));
496 store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
497 store2->AddObserver(&observer_);
498 EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
501 ASSERT_TRUE(store2->policy());
502 ASSERT_FALSE(store2->policy()->has_public_key_version());
503 store2->RemoveObserver(&observer_);
506 TEST_F(UserCloudPolicyStoreTest, InvalidCachedVerificationSignature) {
507 // Make sure that we reject code with an invalid key.
508 StorePolicyAndEnsureLoaded(policy_.policy());
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);
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(),
523 GetPolicyVerificationKey(),
524 loop_.message_loop_proxy()));
525 store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
526 store2->AddObserver(&observer_);
527 ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
530 store2->RemoveObserver(&observer_);
533 } // namespace policy