blob: b4fc979d0509138685173eb5235b939b8eed5703 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/policy/active_directory_policy_manager.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chromeos/dbus/auth_policy/auth_policy_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "components/account_id/account_id.h"
#include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
#include "components/policy/core/common/schema_registry.h"
#include "components/user_manager/scoped_user_manager.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class TestAuthPolicyClient : public chromeos::AuthPolicyClient {
public:
void JoinAdDomain(const authpolicy::JoinDomainRequest& request,
int password_fd,
JoinCallback callback) override {
NOTIMPLEMENTED();
}
void AuthenticateUser(const authpolicy::AuthenticateUserRequest& request,
int password_fd,
AuthCallback callback) override {
NOTIMPLEMENTED();
}
void GetUserStatus(const authpolicy::GetUserStatusRequest& request,
GetUserStatusCallback callback) override {
NOTIMPLEMENTED();
}
void GetUserKerberosFiles(const std::string& object_guid,
GetUserKerberosFilesCallback callback) override {
NOTIMPLEMENTED();
}
void RefreshDevicePolicy(RefreshPolicyCallback callback) override {
NOTIMPLEMENTED();
}
void RefreshUserPolicy(const AccountId& account_id,
RefreshPolicyCallback callback) override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
refresh_user_policy_callback_error_));
}
void ConnectToSignal(
const std::string& signal_name,
dbus::ObjectProxy::SignalCallback signal_callback,
dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
NOTIMPLEMENTED();
}
void WaitForServiceToBeAvailable(
dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)
override {
NOTIMPLEMENTED();
}
void SetRefreshUserPolicyCallbackError(authpolicy::ErrorType error) {
refresh_user_policy_callback_error_ = error;
}
private:
authpolicy::ErrorType refresh_user_policy_callback_error_ =
authpolicy::ERROR_NONE;
};
} // namespace
namespace policy {
// Note that session exit is asynchronous and thus ActiveDirectoryPolicyManager
// still needs to react reasonably to events happening after session exit has
// been fired.
class ActiveDirectoryPolicyManagerTest : public testing::Test {
public:
ActiveDirectoryPolicyManagerTest()
: user_manager_enabler_(
std::make_unique<chromeos::FakeChromeUserManager>()) {}
// testing::Test overrides:
void SetUp() override {
// Base class constructor sets the global instance which will be destroyed
// in AuthPolicyClient::Shutdown().
mock_client_ = new TestAuthPolicyClient();
}
void TearDown() override {
if (mock_external_data_manager())
EXPECT_CALL(*mock_external_data_manager(), Disconnect());
policy_manager_->Shutdown();
chromeos::AuthPolicyClient::Shutdown();
}
protected:
// Gets the store passed to the policy manager during construction.
MockCloudPolicyStore* mock_store() {
DCHECK(policy_manager_);
return static_cast<MockCloudPolicyStore*>(policy_manager_->store());
}
// Gets the data manager passed to the policy manager during construction.
MockCloudExternalDataManager* mock_external_data_manager() {
DCHECK(policy_manager_);
return static_cast<MockCloudExternalDataManager*>(
policy_manager_->external_data_manager());
}
// Initializes the policy manager and verifies expectations on mock classes.
void InitPolicyManagerAndVerifyExpectations() {
if (!mock_store()->is_initialized())
EXPECT_CALL(*mock_store(), Load());
if (mock_external_data_manager()) {
EXPECT_CALL(*mock_external_data_manager(),
Connect(scoped_refptr<network::SharedURLLoaderFactory>()));
}
policy_manager_->Init(&schema_registry_);
testing::Mock::VerifyAndClearExpectations(mock_store());
if (mock_external_data_manager())
testing::Mock::VerifyAndClearExpectations(mock_external_data_manager());
}
// Owned by the AuthPolicyClient global instance.
TestAuthPolicyClient* mock_client_ = nullptr;
// Used to set FakeUserManager.
user_manager::ScopedUserManager user_manager_enabler_;
// Initialized by the individual tests but owned by the test class so that it
// can be shut down automatically after the test has run.
std::unique_ptr<ActiveDirectoryPolicyManager> policy_manager_;
SchemaRegistry schema_registry_;
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
DISALLOW_COPY_AND_ASSIGN(ActiveDirectoryPolicyManagerTest);
};
class UserActiveDirectoryPolicyManagerTest
: public ActiveDirectoryPolicyManagerTest {
public:
~UserActiveDirectoryPolicyManagerTest() override {
EXPECT_EQ(session_exit_expected_, session_exited_);
}
protected:
UserActiveDirectoryPolicyManager* user_policy_manager() const {
return static_cast<UserActiveDirectoryPolicyManager*>(
policy_manager_.get());
}
// Creates |policy_manager_| with fake AD account id and
// |initial_policy_fetch_timeout| as timeout.
void CreatePolicyManager(base::TimeDelta initial_policy_fetch_timeout) {
auto account_id = AccountId::AdFromUserEmailObjGuid("bla", "ble");
base::OnceClosure exit_session =
base::BindOnce(&UserActiveDirectoryPolicyManagerTest::ExitSession,
base::Unretained(this));
policy_manager_ = std::make_unique<UserActiveDirectoryPolicyManager>(
account_id, true /* policy_required */, initial_policy_fetch_timeout,
std::move(exit_session), std::make_unique<MockCloudPolicyStore>(),
std::make_unique<MockCloudExternalDataManager>());
EXPECT_FALSE(
policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// Expect that session exit will be called below. (Must only be called once.)
void ExpectSessionExit() {
ASSERT_FALSE(session_exit_expected_);
EXPECT_FALSE(session_exited_);
session_exit_expected_ = true;
}
// Expect that session exit has been called above. (Must only be called after
// ExpectSessionExit().)
void ExpectSessionExited() {
ASSERT_TRUE(session_exit_expected_);
EXPECT_TRUE(session_exited_);
}
// Closure to exit the session.
void ExitSession() {
EXPECT_TRUE(session_exit_expected_);
session_exited_ = true;
}
bool session_exited_ = false;
bool session_exit_expected_ = false;
};
TEST_F(UserActiveDirectoryPolicyManagerTest, DontWait_HasCachedPolicy) {
CreatePolicyManager(base::TimeDelta());
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_UNKNOWN);
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
TEST_F(UserActiveDirectoryPolicyManagerTest, DontWait_NoCachedPolicy) {
CreatePolicyManager(base::TimeDelta());
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_UNKNOWN);
mock_store()->NotifyStoreError();
ExpectSessionExit();
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
ExpectSessionExited();
}
// Initialization is only complete after policy has been fetched and after that
// has been loaded.
TEST_F(UserActiveDirectoryPolicyManagerTest,
WaitFinite_LoadSuccess_FetchSuccess_LoadSuccess) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to succeed.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_NONE);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Process reply for mock policy fetch.
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Simulate successful store load. At this point initialization is complete.
mock_store()->NotifyStoreLoaded();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// Initialization is only complete after policy has been fetched and after that
// has failed to load. Load failure should not prevent session start as long as
// we have cached policy.
TEST_F(UserActiveDirectoryPolicyManagerTest,
WaitFinite_LoadSuccess_FetchSuccess_LoadFail) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to succeed.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_NONE);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Process reply for mock policy fetch.
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Simulate failed store load.
mock_store()->NotifyStoreError();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// If the initial fetch timeout is not infinite, we're in best-effort mode but
// still require the policy load to succeed so that there's *some* policy
// present (though possibly outdated).
TEST_F(UserActiveDirectoryPolicyManagerTest, WaitFinite_LoadSuccess_FetchFail) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_UNKNOWN);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Process reply for mock policy fetch. At this point initialization is
// complete (we have waited for the fetch but now that we know it has failed
// we continue).
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Simulate successful store load.
mock_store()->NotifyStoreLoaded();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// If the initial fetch timeout is not infinite, we're in best-effort mode but
// still require the policy load to succeed so that there's *some* policy
// present (though possibly outdated). Here the sequence is inverted: Fetch
// returns before load.
TEST_F(UserActiveDirectoryPolicyManagerTest, WaitFinite_FetchFail_LoadSuccess) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_UNKNOWN);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
// Process reply for mock policy fetch.
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// If the initial fetch timeout is not infinite, we're in best-effort mode but
// if we can't load existing policy from disk we have to give up.
TEST_F(UserActiveDirectoryPolicyManagerTest, WaitFinite_LoadFail_FetchFail) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_UNKNOWN);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
// Simulate failed store load.
mock_store()->NotifyStoreError();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
ExpectSessionExit();
// Process reply for mock policy fetch.
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
ExpectSessionExited();
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// If the initial fetch timeout is not infinite, we're in best-effort mode and
// upon timeout initialization is complete if any policy could be loaded from
// disk.
TEST_F(UserActiveDirectoryPolicyManagerTest,
WaitFinite_LoadSuccess_FetchTimeout) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_UNKNOWN);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Simulate policy fetch timeout.
user_policy_manager()->ForceTimeoutForTesting();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// If load fails and fetch times out, we wait until fetch response is called.
TEST_F(UserActiveDirectoryPolicyManagerTest,
WaitFinite_LoadFail_FetchTimeout_FetchSuccess) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_NONE);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
mock_store()->NotifyStoreError();
// Simulate policy fetch timeout.
user_policy_manager()->ForceTimeoutForTesting();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Process reply for mock policy fetch.
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
// If load fails and fetch times out, we wait until fetch response is called.
// Failure should end the session.
TEST_F(UserActiveDirectoryPolicyManagerTest,
WaitFinite_LoadFail_FetchTimeout_FetchFail) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Configure mock policy fetch to fail.
mock_client_->SetRefreshUserPolicyCallbackError(authpolicy::ERROR_UNKNOWN);
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
mock_store()->NotifyStoreError();
// Simulate policy fetch timeout.
user_policy_manager()->ForceTimeoutForTesting();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
ExpectSessionExit();
// Process reply for mock policy fetch.
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
ExpectSessionExited();
}
// Simulate long load by policy store.
TEST_F(UserActiveDirectoryPolicyManagerTest, WaitFinite_FetchSucces_LongLoad) {
CreatePolicyManager(base::TimeDelta::FromDays(365));
// Trigger mock policy fetch from authpolicyd.
InitPolicyManagerAndVerifyExpectations();
// Process reply for mock policy fetch.
EXPECT_CALL(*mock_store(), Load());
base::RunLoop().RunUntilIdle();
user_policy_manager()->ForceTimeoutForTesting();
EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// Simulate successful store load.
mock_store()->policy_ = std::make_unique<enterprise_management::PolicyData>();
mock_store()->NotifyStoreLoaded();
EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
class DeviceActiveDirectoryPolicyManagerTest
: public ActiveDirectoryPolicyManagerTest {
protected:
// Creates |mock_store()| and |policy_manager_|.
void CreatePolicyManager() {
policy_manager_ = std::make_unique<DeviceActiveDirectoryPolicyManager>(
std::make_unique<MockCloudPolicyStore>());
EXPECT_FALSE(
policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
};
TEST_F(DeviceActiveDirectoryPolicyManagerTest, Initialization) {
CreatePolicyManager();
InitPolicyManagerAndVerifyExpectations();
}
} // namespace policy