session_manager_operation_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/session_manager_operation.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/mock_owner_key_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/policy/cloud_policy_constants.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/policy/cloud_policy_validator.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/policy/policy_builder.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/policy/proto/device_management_backend.pb.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/rsa_private_key.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Mock;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SessionManagerOperationTest : public testing::Test {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionManagerOperationTest()
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ui_thread_(content::BrowserThread::UI, &message_loop_),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_thread_(content::BrowserThread::FILE, &message_loop_),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        owner_key_util_(new MockOwnerKeyUtil()),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        validated_(false) {}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    policy_.payload().mutable_pinned_apps()->add_app_id("fake-app");
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    policy_.Build();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD2(OnOperationCompleted,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               void(SessionManagerOperation*, DeviceSettingsService::Status));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckSuccessfulValidation(
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      policy::DeviceCloudPolicyValidator* validator) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(validator->success());
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(validator->payload().get());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(validator->payload()->SerializeAsString(),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              policy_.payload().SerializeAsString());
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    validated_ = true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckPublicKeyLoaded(SessionManagerOperation* op) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(op->owner_key().get());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(op->owner_key()->public_key());
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<uint8> public_key;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(policy_.signing_key()->ExportPublicKey(&public_key));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(public_key, *op->owner_key()->public_key());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckPrivateKeyLoaded(SessionManagerOperation* op) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(op->owner_key().get());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(op->owner_key()->private_key());
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<uint8> expected_key;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(policy_.signing_key()->ExportPrivateKey(&expected_key));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<uint8> actual_key;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(op->owner_key()->private_key()->ExportPrivateKey(&actual_key));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected_key, actual_key);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop message_loop_;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread file_thread_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  policy::DevicePolicyBuilder policy_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeviceSettingsTestHelper device_settings_test_helper_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockOwnerKeyUtil> owner_key_util_;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool validated_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SessionManagerOperationTest);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SessionManagerOperationTest, LoadNoPolicyNoKey) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadSettingsOperation op(
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SessionManagerOperationTest::OnOperationCompleted,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(*this,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              OnOperationCompleted(
97                  &op, DeviceSettingsService::STORE_KEY_UNAVAILABLE));
98  op.Start(&device_settings_test_helper_, owner_key_util_, NULL);
99  device_settings_test_helper_.Flush();
100  Mock::VerifyAndClearExpectations(this);
101
102  EXPECT_FALSE(op.policy_data().get());
103  EXPECT_FALSE(op.device_settings().get());
104  ASSERT_TRUE(op.owner_key().get());
105  EXPECT_FALSE(op.owner_key()->public_key());
106  EXPECT_FALSE(op.owner_key()->private_key());
107}
108
109TEST_F(SessionManagerOperationTest, LoadOwnerKey) {
110  owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
111  LoadSettingsOperation op(
112      base::Bind(&SessionManagerOperationTest::OnOperationCompleted,
113                 base::Unretained(this)));
114
115  EXPECT_CALL(*this,
116              OnOperationCompleted(
117                  &op, DeviceSettingsService::STORE_NO_POLICY));
118  op.Start(&device_settings_test_helper_, owner_key_util_, NULL);
119  device_settings_test_helper_.Flush();
120  Mock::VerifyAndClearExpectations(this);
121
122  CheckPublicKeyLoaded(&op);
123}
124
125TEST_F(SessionManagerOperationTest, LoadPolicy) {
126  owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
127  device_settings_test_helper_.set_policy_blob(policy_.GetBlob());
128  LoadSettingsOperation op(
129      base::Bind(&SessionManagerOperationTest::OnOperationCompleted,
130                 base::Unretained(this)));
131
132  EXPECT_CALL(*this,
133              OnOperationCompleted(
134                  &op, DeviceSettingsService::STORE_SUCCESS));
135  op.Start(&device_settings_test_helper_, owner_key_util_, NULL);
136  device_settings_test_helper_.Flush();
137  Mock::VerifyAndClearExpectations(this);
138
139  ASSERT_TRUE(op.policy_data().get());
140  EXPECT_EQ(policy_.policy_data().SerializeAsString(),
141            op.policy_data()->SerializeAsString());
142  ASSERT_TRUE(op.device_settings().get());
143  EXPECT_EQ(policy_.payload().SerializeAsString(),
144            op.device_settings()->SerializeAsString());
145}
146
147TEST_F(SessionManagerOperationTest, LoadPrivateOwnerKey) {
148  owner_key_util_->SetPrivateKey(policy_.signing_key());
149  LoadSettingsOperation op(
150      base::Bind(&SessionManagerOperationTest::OnOperationCompleted,
151                 base::Unretained(this)));
152
153  EXPECT_CALL(*this,
154              OnOperationCompleted(
155                  &op, DeviceSettingsService::STORE_NO_POLICY));
156  op.Start(&device_settings_test_helper_, owner_key_util_, NULL);
157  device_settings_test_helper_.Flush();
158  Mock::VerifyAndClearExpectations(this);
159
160  CheckPublicKeyLoaded(&op);
161  CheckPrivateKeyLoaded(&op);
162}
163
164TEST_F(SessionManagerOperationTest, RestartLoad) {
165  owner_key_util_->SetPrivateKey(policy_.signing_key());
166  device_settings_test_helper_.set_policy_blob(policy_.GetBlob());
167  LoadSettingsOperation op(
168      base::Bind(&SessionManagerOperationTest::OnOperationCompleted,
169                 base::Unretained(this)));
170
171  EXPECT_CALL(*this, OnOperationCompleted(&op, _)).Times(0);
172  op.Start(&device_settings_test_helper_, owner_key_util_, NULL);
173  device_settings_test_helper_.FlushLoops();
174  device_settings_test_helper_.FlushRetrieve();
175  EXPECT_TRUE(op.owner_key());
176  EXPECT_TRUE(op.owner_key()->public_key());
177  Mock::VerifyAndClearExpectations(this);
178
179  // Now install a different key and policy and restart the operation.
180  policy_.set_signing_key(policy::PolicyBuilder::CreateTestNewSigningKey());
181  policy_.payload().mutable_metrics_enabled()->set_metrics_enabled(true);
182  policy_.Build();
183  device_settings_test_helper_.set_policy_blob(policy_.GetBlob());
184  owner_key_util_->SetPrivateKey(policy_.signing_key());
185
186  EXPECT_CALL(*this,
187              OnOperationCompleted(
188                  &op, DeviceSettingsService::STORE_SUCCESS));
189  op.RestartLoad(true);
190  device_settings_test_helper_.Flush();
191  Mock::VerifyAndClearExpectations(this);
192
193  // Check that the new keys have been loaded.
194  CheckPublicKeyLoaded(&op);
195  CheckPrivateKeyLoaded(&op);
196
197  // Verify the new policy.
198  ASSERT_TRUE(op.policy_data().get());
199  EXPECT_EQ(policy_.policy_data().SerializeAsString(),
200            op.policy_data()->SerializeAsString());
201  ASSERT_TRUE(op.device_settings().get());
202  EXPECT_EQ(policy_.payload().SerializeAsString(),
203            op.device_settings()->SerializeAsString());
204}
205
206TEST_F(SessionManagerOperationTest, StoreSettings) {
207  owner_key_util_->SetPublicKeyFromPrivateKey(policy_.signing_key());
208  StoreSettingsOperation op(
209      base::Bind(&SessionManagerOperationTest::OnOperationCompleted,
210                 base::Unretained(this)),
211      policy_.GetCopy());
212
213  EXPECT_CALL(*this,
214              OnOperationCompleted(
215                  &op, DeviceSettingsService::STORE_SUCCESS));
216  op.Start(&device_settings_test_helper_, owner_key_util_, NULL);
217  device_settings_test_helper_.Flush();
218  Mock::VerifyAndClearExpectations(this);
219
220  EXPECT_EQ(device_settings_test_helper_.policy_blob(),
221            policy_.GetBlob());
222  ASSERT_TRUE(op.policy_data().get());
223  EXPECT_EQ(policy_.policy_data().SerializeAsString(),
224            op.policy_data()->SerializeAsString());
225  ASSERT_TRUE(op.device_settings().get());
226  EXPECT_EQ(policy_.payload().SerializeAsString(),
227            op.device_settings()->SerializeAsString());
228}
229
230TEST_F(SessionManagerOperationTest, SignAndStoreSettings) {
231  base::Time before(base::Time::NowFromSystemTime());
232  owner_key_util_->SetPrivateKey(policy_.signing_key());
233  SignAndStoreSettingsOperation op(
234      base::Bind(&SessionManagerOperationTest::OnOperationCompleted,
235                 base::Unretained(this)),
236      scoped_ptr<em::ChromeDeviceSettingsProto>(
237          new em::ChromeDeviceSettingsProto(policy_.payload())),
238      policy_.policy_data().username());
239
240  EXPECT_CALL(*this,
241              OnOperationCompleted(
242                  &op, DeviceSettingsService::STORE_SUCCESS));
243  op.Start(&device_settings_test_helper_, owner_key_util_, NULL);
244  device_settings_test_helper_.Flush();
245  Mock::VerifyAndClearExpectations(this);
246  base::Time after(base::Time::NowFromSystemTime());
247
248  // The blob should validate.
249  scoped_ptr<em::PolicyFetchResponse> policy_response(
250      new em::PolicyFetchResponse());
251  ASSERT_TRUE(
252      policy_response->ParseFromString(
253          device_settings_test_helper_.policy_blob()));
254  policy::DeviceCloudPolicyValidator* validator =
255      policy::DeviceCloudPolicyValidator::Create(
256          policy_response.Pass(),
257          base::Bind(&SessionManagerOperationTest::CheckSuccessfulValidation,
258                     base::Unretained(this)));
259  validator->ValidateUsername(policy_.policy_data().username());
260  validator->ValidateTimestamp(before, after, false);
261  validator->ValidatePolicyType(policy::dm_protocol::kChromeDevicePolicyType);
262  validator->ValidatePayload();
263  std::vector<uint8> public_key;
264  policy_.signing_key()->ExportPublicKey(&public_key);
265  validator->ValidateSignature(public_key, false);
266  validator->StartValidation();
267  message_loop_.RunAllPending();
268  EXPECT_TRUE(validated_);
269
270  // Check that the loaded policy_data contains the expected values.
271  EXPECT_EQ(policy::dm_protocol::kChromeDevicePolicyType,
272            op.policy_data()->policy_type());
273  EXPECT_LE((before - base::Time::UnixEpoch()).InMilliseconds(),
274            op.policy_data()->timestamp());
275  EXPECT_GE((after - base::Time::UnixEpoch()).InMilliseconds(),
276            op.policy_data()->timestamp());
277  EXPECT_FALSE(op.policy_data()->has_request_token());
278  EXPECT_EQ(policy_.policy_data().username(), op.policy_data()->username());
279
280  // Loaded device settings should match what the operation received.
281  ASSERT_TRUE(op.device_settings().get());
282  EXPECT_EQ(policy_.payload().SerializeAsString(),
283            op.device_settings()->SerializeAsString());
284}
285
286}  // namespace chromeos
287