Home | History | Annotate | Download | only in cloud
      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   virtual 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   virtual 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 (at) 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 (at) 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
    534