user_cloud_policy_store_chromeos_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <vector> 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/basictypes.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/bind.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/file_util.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/files/scoped_temp_dir.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/message_loop.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_constants.h" 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/policy/cloud/mock_cloud_policy_store.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/policy/cloud/policy_builder.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/policy/proto/cloud/device_management_local.pb.h" 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/dbus/mock_cryptohome_client.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/dbus/mock_session_manager_client.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/test/test_browser_thread.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "policy/policy_constants.h" 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "policy/proto/cloud_policy.pb.h" 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace em = enterprise_management; 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using testing::AllOf; 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using testing::AnyNumber; 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing testing::Eq; 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing testing::Mock; 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing testing::Property; 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing testing::SaveArg; 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing testing::_; 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace policy { 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace { 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kLegacyDeviceId[] = "legacy-device-id"; 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kLegacyToken[] = "legacy-token"; 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kSanitizedUsername[] = "0123456789ABCDEF0123456789ABCDEF012345678"; 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kDefaultHomepage[] = "http://chromium.org"; 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuACTION_P2(SendSanitizedUsername, call_status, sanitized_username) { 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageLoop::current()->PostTask( 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, base::Bind(arg1, call_status, sanitized_username)); 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass UserCloudPolicyStoreChromeOSTest : public testing::Test { 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected: 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu UserCloudPolicyStoreChromeOSTest() 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : loop_(MessageLoop::TYPE_UI), 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ui_thread_(content::BrowserThread::UI, &loop_), 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_thread_(content::BrowserThread::FILE, &loop_) {} 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void SetUp() OVERRIDE { 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(cryptohome_client_, 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GetSanitizedUsername(PolicyBuilder::kFakeUsername, _)) 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu .Times(AnyNumber()) 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) .WillRepeatedly( 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SendSanitizedUsername(chromeos::DBUS_METHOD_CALL_SUCCESS, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kSanitizedUsername)); 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir()); 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch store_.reset(new UserCloudPolicyStoreChromeOS(&cryptohome_client_, 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &session_manager_client_, 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PolicyBuilder::kFakeUsername, 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch user_policy_dir(), 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch token_file(), 730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch policy_file())); 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch store_->AddObserver(&observer_); 750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Install the initial public key, so that by default the validation of 770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the stored/loaded policy blob succeeds. 780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<uint8> public_key; 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(policy_.signing_key()->ExportPublicKey(&public_key)); 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu StoreUserPolicyKey(public_key); 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu policy_.payload().mutable_homepagelocation()->set_value(kDefaultHomepage); 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu policy_.Build(); 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual void TearDown() OVERRIDE { 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) store_->RemoveObserver(&observer_); 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) store_.reset(); 89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RunUntilIdle(); 90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Install an expectation on |observer_| for an error code. 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void ExpectError(CloudPolicyStore::Status error) { 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_CALL(observer_, 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) OnStoreError(AllOf(Eq(store_.get()), 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Property(&CloudPolicyStore::status, 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Eq(error))))); 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Triggers a store_->Load() operation, handles the expected call to 101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // |session_manager_client_| and sends |response|. 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void PerformPolicyLoad(const std::string& response) { 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Issue a load command. 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) chromeos::SessionManagerClient::RetrievePolicyCallback retrieve_callback; 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_CALL(session_manager_client_, RetrieveUserPolicy(_)) 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) .WillOnce(SaveArg<0>(&retrieve_callback)); 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) store_->Load(); 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RunUntilIdle(); 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Mock::VerifyAndClearExpectations(&session_manager_client_); 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(retrieve_callback.is_null()); 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Run the callback. 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) retrieve_callback.Run(response); 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RunUntilIdle(); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Verifies that store_->policy_map() has the HomepageLocation entry with 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the |expected_value|. 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void VerifyPolicyMap(const char* expected_value) { 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(1U, store_->policy_map().size()); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PolicyMap::Entry* entry = 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) store_->policy_map().Get(key::kHomepageLocation); 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(entry); 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_TRUE(base::StringValue(expected_value).Equals(entry->value)); 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void StoreUserPolicyKey(const std::vector<uint8>& public_key) { 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(file_util::CreateDirectory(user_policy_key_file().DirName())); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE( 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_util::WriteFile(user_policy_key_file(), 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<const char*>(public_key.data()), 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public_key.size())); 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Stores the current |policy_| and verifies that it is published. 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If |new_public_key| is set then it will be persisted after storing but 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // before loading the policy, so that the signature validation can succeed. 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If |previous_value| is set then a previously existing policy with that 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // value will be expected; otherwise no previous policy is expected. 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // If |new_value| is set then a new policy with that value is expected after 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // storing the |policy_| blob. 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void PerformStorePolicy(const std::vector<uint8>* new_public_key, 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* previous_value, 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* new_value) { 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chromeos::SessionManagerClient::StorePolicyCallback store_callback; 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(session_manager_client_, StoreUserPolicy(policy_.GetBlob(), _)) 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch .WillOnce(SaveArg<1>(&store_callback)); 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch store_->Store(policy_.policy()); 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RunUntilIdle(); 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Mock::VerifyAndClearExpectations(&session_manager_client_); 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(store_callback.is_null()); 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The new policy shouldn't be present yet. 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PolicyMap previous_policy; 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(previous_value != NULL, store_->policy() != NULL); 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (previous_value) { 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) previous_policy.Set(key::kHomepageLocation, 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch POLICY_LEVEL_MANDATORY, 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch POLICY_SCOPE_USER, 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Value::CreateStringValue(previous_value)); 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(previous_policy.Equals(store_->policy_map())); 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Store the new public key so that the validation after the retrieve 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // operation completes can verify the signature. 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (new_public_key) 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch StoreUserPolicyKey(*new_public_key); 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Let the store operation complete. 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch chromeos::SessionManagerClient::RetrievePolicyCallback retrieve_callback; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(session_manager_client_, RetrieveUserPolicy(_)) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(SaveArg<0>(&retrieve_callback)); 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch store_callback.Run(true); 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RunUntilIdle(); 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(previous_policy.Equals(store_->policy_map())); 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Mock::VerifyAndClearExpectations(&session_manager_client_); 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_FALSE(retrieve_callback.is_null()); 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Finish the retrieve callback. 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_CALL(observer_, OnStoreLoaded(store_.get())); 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) retrieve_callback.Run(policy_.GetBlob()); 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(store_->policy()); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(policy_.policy_data().SerializeAsString(), 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) store_->policy()->SerializeAsString()); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VerifyPolicyMap(new_value); 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void VerifyStoreHasValidationError() { 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(store_->policy()); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(store_->policy_map().empty()); 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status()); 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RunUntilIdle() { 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) loop_.RunUntilIdle(); 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::GetBlockingPool()->FlushForTesting(); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) loop_.RunUntilIdle(); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath user_policy_dir() { 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return tmp_dir_.path().AppendASCII("var_run_user_policy"); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::FilePath user_policy_key_file() { 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return user_policy_dir().AppendASCII(kSanitizedUsername) 2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu .AppendASCII("policy.pub"); 2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::FilePath token_file() { 2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return tmp_dir_.path().AppendASCII("token"); 2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::FilePath policy_file() { 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return tmp_dir_.path().AppendASCII("policy"); 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageLoop loop_; 2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu chromeos::MockCryptohomeClient cryptohome_client_; 2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu chromeos::MockSessionManagerClient session_manager_client_; 2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu UserPolicyBuilder policy_; 2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MockCloudPolicyStoreObserver observer_; 2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<UserCloudPolicyStoreChromeOS> store_; 2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content::TestBrowserThread ui_thread_; 2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content::TestBrowserThread file_thread_; 2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::ScopedTempDir tmp_dir_; 2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyStoreChromeOSTest); 2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(UserCloudPolicyStoreChromeOSTest, InitialStore) { 2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Start without any public key to trigger the initial key checks. 2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(file_util::Delete(user_policy_key_file(), false)); 2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Make the policy blob contain a new public key. 2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu policy_.set_new_signing_key(PolicyBuilder::CreateTestNewSigningKey()); 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu policy_.Build(); 2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<uint8> new_public_key; 2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(policy_.new_signing_key()->ExportPublicKey(&new_public_key)); 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_NO_FATAL_FAILURE( 2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PerformStorePolicy(&new_public_key, NULL, kDefaultHomepage)); 2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(UserCloudPolicyStoreChromeOSTest, StoreWithExistingKey) { 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_NO_FATAL_FAILURE( 250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) PerformStorePolicy(NULL, NULL, kDefaultHomepage)); 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreChromeOSTest, StoreWithRotation) { 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Make the policy blob contain a new public key. 255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) policy_.set_new_signing_key(PolicyBuilder::CreateTestNewSigningKey()); 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) policy_.Build(); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<uint8> new_public_key; 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(policy_.new_signing_key()->ExportPublicKey(&new_public_key)); 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE( 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PerformStorePolicy(&new_public_key, NULL, kDefaultHomepage)); 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreChromeOSTest, StoreFail) { 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Store policy. 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chromeos::SessionManagerClient::StorePolicyCallback store_callback; 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(session_manager_client_, StoreUserPolicy(policy_.GetBlob(), _)) 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(SaveArg<1>(&store_callback)); 268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) store_->Store(policy_.policy()); 269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Mock::VerifyAndClearExpectations(&session_manager_client_); 271 ASSERT_FALSE(store_callback.is_null()); 272 273 // Let the store operation complete. 274 ExpectError(CloudPolicyStore::STATUS_STORE_ERROR); 275 store_callback.Run(false); 276 RunUntilIdle(); 277 EXPECT_FALSE(store_->policy()); 278 EXPECT_TRUE(store_->policy_map().empty()); 279 EXPECT_EQ(CloudPolicyStore::STATUS_STORE_ERROR, store_->status()); 280} 281 282TEST_F(UserCloudPolicyStoreChromeOSTest, StoreValidationError) { 283 policy_.policy_data().clear_policy_type(); 284 policy_.Build(); 285 286 // Store policy. 287 chromeos::SessionManagerClient::StorePolicyCallback store_callback; 288 ExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR); 289 EXPECT_CALL(session_manager_client_, StoreUserPolicy(policy_.GetBlob(), _)) 290 .Times(0); 291 store_->Store(policy_.policy()); 292 RunUntilIdle(); 293 Mock::VerifyAndClearExpectations(&session_manager_client_); 294} 295 296TEST_F(UserCloudPolicyStoreChromeOSTest, StoreWithoutPolicyKey) { 297 // Make the dbus call to cryptohome fail. 298 Mock::VerifyAndClearExpectations(&cryptohome_client_); 299 EXPECT_CALL(cryptohome_client_, 300 GetSanitizedUsername(PolicyBuilder::kFakeUsername, _)) 301 .Times(AnyNumber()) 302 .WillRepeatedly(SendSanitizedUsername(chromeos::DBUS_METHOD_CALL_FAILURE, 303 std::string())); 304 305 // Store policy. 306 chromeos::SessionManagerClient::StorePolicyCallback store_callback; 307 ExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR); 308 EXPECT_CALL(session_manager_client_, StoreUserPolicy(policy_.GetBlob(), _)) 309 .Times(0); 310 store_->Store(policy_.policy()); 311 RunUntilIdle(); 312 Mock::VerifyAndClearExpectations(&session_manager_client_); 313} 314 315TEST_F(UserCloudPolicyStoreChromeOSTest, StoreWithInvalidSignature) { 316 // Break the signature. 317 policy_.policy().mutable_policy_data_signature()->append("garbage"); 318 319 // Store policy. 320 chromeos::SessionManagerClient::StorePolicyCallback store_callback; 321 ExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR); 322 EXPECT_CALL(session_manager_client_, StoreUserPolicy(policy_.GetBlob(), _)) 323 .Times(0); 324 store_->Store(policy_.policy()); 325 RunUntilIdle(); 326 Mock::VerifyAndClearExpectations(&session_manager_client_); 327} 328 329TEST_F(UserCloudPolicyStoreChromeOSTest, Load) { 330 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())); 331 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob())); 332 Mock::VerifyAndClearExpectations(&observer_); 333 334 // Verify that the policy has been loaded. 335 ASSERT_TRUE(store_->policy()); 336 EXPECT_EQ(policy_.policy_data().SerializeAsString(), 337 store_->policy()->SerializeAsString()); 338 VerifyPolicyMap(kDefaultHomepage); 339 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 340} 341 342TEST_F(UserCloudPolicyStoreChromeOSTest, LoadNoPolicy) { 343 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())); 344 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad("")); 345 Mock::VerifyAndClearExpectations(&observer_); 346 347 // Verify no policy has been installed. 348 EXPECT_FALSE(store_->policy()); 349 EXPECT_TRUE(store_->policy_map().empty()); 350 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 351} 352 353TEST_F(UserCloudPolicyStoreChromeOSTest, LoadInvalidPolicy) { 354 ExpectError(CloudPolicyStore::STATUS_PARSE_ERROR); 355 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad("invalid")); 356 357 // Verify no policy has been installed. 358 EXPECT_FALSE(store_->policy()); 359 EXPECT_TRUE(store_->policy_map().empty()); 360 EXPECT_EQ(CloudPolicyStore::STATUS_PARSE_ERROR, store_->status()); 361} 362 363TEST_F(UserCloudPolicyStoreChromeOSTest, LoadValidationError) { 364 policy_.policy_data().clear_policy_type(); 365 policy_.Build(); 366 367 ExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR); 368 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob())); 369 VerifyStoreHasValidationError(); 370} 371 372TEST_F(UserCloudPolicyStoreChromeOSTest, LoadNoKey) { 373 // The loaded policy can't be verified without the public key. 374 ASSERT_TRUE(file_util::Delete(user_policy_key_file(), false)); 375 ExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR); 376 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob())); 377 VerifyStoreHasValidationError(); 378} 379 380TEST_F(UserCloudPolicyStoreChromeOSTest, LoadInvalidSignature) { 381 // Break the signature. 382 policy_.policy().mutable_policy_data_signature()->append("garbage"); 383 ExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR); 384 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob())); 385 VerifyStoreHasValidationError(); 386} 387 388TEST_F(UserCloudPolicyStoreChromeOSTest, MigrationFull) { 389 std::string data; 390 391 em::DeviceCredentials credentials; 392 credentials.set_device_token(kLegacyToken); 393 credentials.set_device_id(kLegacyDeviceId); 394 ASSERT_TRUE(credentials.SerializeToString(&data)); 395 ASSERT_NE(-1, file_util::WriteFile(token_file(), data.c_str(), data.size())); 396 397 em::CachedCloudPolicyResponse cached_policy; 398 cached_policy.mutable_cloud_policy()->CopyFrom(policy_.policy()); 399 ASSERT_TRUE(cached_policy.SerializeToString(&data)); 400 ASSERT_NE(-1, file_util::WriteFile(policy_file(), data.c_str(), data.size())); 401 402 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())); 403 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad("")); 404 Mock::VerifyAndClearExpectations(&observer_); 405 406 // Verify that legacy user policy and token have been loaded. 407 em::PolicyData expected_policy_data; 408 EXPECT_TRUE(expected_policy_data.ParseFromString( 409 cached_policy.cloud_policy().policy_data())); 410 expected_policy_data.clear_public_key_version(); 411 expected_policy_data.set_request_token(kLegacyToken); 412 expected_policy_data.set_device_id(kLegacyDeviceId); 413 ASSERT_TRUE(store_->policy()); 414 EXPECT_EQ(expected_policy_data.SerializeAsString(), 415 store_->policy()->SerializeAsString()); 416 VerifyPolicyMap(kDefaultHomepage); 417 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 418} 419 420TEST_F(UserCloudPolicyStoreChromeOSTest, MigrationNoToken) { 421 std::string data; 422 testing::Sequence seq; 423 424 em::CachedCloudPolicyResponse cached_policy; 425 cached_policy.mutable_cloud_policy()->CopyFrom(policy_.policy()); 426 ASSERT_TRUE(cached_policy.SerializeToString(&data)); 427 ASSERT_NE(-1, file_util::WriteFile(policy_file(), data.c_str(), data.size())); 428 429 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())); 430 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad("")); 431 Mock::VerifyAndClearExpectations(&observer_); 432 433 // Verify the legacy cache has been loaded. 434 em::PolicyData expected_policy_data; 435 EXPECT_TRUE(expected_policy_data.ParseFromString( 436 cached_policy.cloud_policy().policy_data())); 437 expected_policy_data.clear_public_key_version(); 438 ASSERT_TRUE(store_->policy()); 439 EXPECT_EQ(expected_policy_data.SerializeAsString(), 440 store_->policy()->SerializeAsString()); 441 VerifyPolicyMap(kDefaultHomepage); 442 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 443} 444 445TEST_F(UserCloudPolicyStoreChromeOSTest, MigrationNoPolicy) { 446 std::string data; 447 448 em::DeviceCredentials credentials; 449 credentials.set_device_token(kLegacyToken); 450 credentials.set_device_id(kLegacyDeviceId); 451 ASSERT_TRUE(credentials.SerializeToString(&data)); 452 ASSERT_NE(-1, file_util::WriteFile(token_file(), data.c_str(), data.size())); 453 454 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())); 455 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad("")); 456 Mock::VerifyAndClearExpectations(&observer_); 457 458 // Verify that legacy user policy and token have been loaded. 459 em::PolicyData expected_policy_data; 460 expected_policy_data.set_request_token(kLegacyToken); 461 expected_policy_data.set_device_id(kLegacyDeviceId); 462 ASSERT_TRUE(store_->policy()); 463 EXPECT_EQ(expected_policy_data.SerializeAsString(), 464 store_->policy()->SerializeAsString()); 465 EXPECT_TRUE(store_->policy_map().empty()); 466 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 467} 468 469TEST_F(UserCloudPolicyStoreChromeOSTest, MigrationAndStoreNew) { 470 // Start without an existing public key. 471 ASSERT_TRUE(file_util::Delete(user_policy_key_file(), false)); 472 473 std::string data; 474 em::CachedCloudPolicyResponse cached_policy; 475 cached_policy.mutable_cloud_policy()->CopyFrom(policy_.policy()); 476 ASSERT_TRUE(cached_policy.SerializeToString(&data)); 477 ASSERT_NE(-1, file_util::WriteFile(policy_file(), data.c_str(), data.size())); 478 479 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())); 480 ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad("")); 481 Mock::VerifyAndClearExpectations(&observer_); 482 483 // Verify the legacy cache has been loaded. 484 em::PolicyData expected_policy_data; 485 EXPECT_TRUE(expected_policy_data.ParseFromString( 486 cached_policy.cloud_policy().policy_data())); 487 expected_policy_data.clear_public_key_version(); 488 ASSERT_TRUE(store_->policy()); 489 EXPECT_EQ(expected_policy_data.SerializeAsString(), 490 store_->policy()->SerializeAsString()); 491 VerifyPolicyMap(kDefaultHomepage); 492 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 493 EXPECT_TRUE(file_util::PathExists(policy_file())); 494 495 // Now store a new policy using the new homepage location. 496 const char kNewHomepage[] = "http://google.com"; 497 policy_.payload().mutable_homepagelocation()->set_value(kNewHomepage); 498 policy_.set_new_signing_key(PolicyBuilder::CreateTestNewSigningKey()); 499 policy_.Build(); 500 std::vector<uint8> new_public_key; 501 ASSERT_TRUE(policy_.new_signing_key()->ExportPublicKey(&new_public_key)); 502 ASSERT_NO_FATAL_FAILURE( 503 PerformStorePolicy(&new_public_key, kDefaultHomepage, kNewHomepage)); 504 VerifyPolicyMap(kNewHomepage); 505 506 // Verify that the legacy cache has been removed. 507 EXPECT_FALSE(file_util::PathExists(policy_file())); 508} 509 510} // namespace 511 512} // namespace policy 513