Commit 591fe7b9 authored by Jun Mukai's avatar Jun Mukai Committed by Commit Bot

load offline policy blob from the filesystem

This CL looks up the policy blob data for the offline demo mode
from the filesystem and goes through the enrollment flow.

Bug: 827290
Change-Id: Id23959bb710a08db2ad64cf838b15a3b21457cef
Reviewed-on: https://chromium-review.googlesource.com/1048166
Commit-Queue: Jun Mukai <mukai@chromium.org>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarAga Wronska <agawronska@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566768}
parent 570db664
...@@ -1367,6 +1367,7 @@ source_set("chromeos") { ...@@ -1367,6 +1367,7 @@ source_set("chromeos") {
"policy/display_rotation_default_handler.h", "policy/display_rotation_default_handler.h",
"policy/dm_token_storage.cc", "policy/dm_token_storage.cc",
"policy/dm_token_storage.h", "policy/dm_token_storage.h",
"policy/enrollment_config.cc",
"policy/enrollment_config.h", "policy/enrollment_config.h",
"policy/enrollment_handler_chromeos.cc", "policy/enrollment_handler_chromeos.cc",
"policy/enrollment_handler_chromeos.h", "policy/enrollment_handler_chromeos.h",
......
...@@ -5,14 +5,20 @@ ...@@ -5,14 +5,20 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SETUP_CONTROLLER_H_ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SETUP_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SETUP_CONTROLLER_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SETUP_CONTROLLER_H_
#include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h" #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h"
#include "chrome/browser/chromeos/policy/enrollment_config.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
namespace chromeos { namespace chromeos {
// Controlls enrollment flow for setting up Demo Mode. // Controlls enrollment flow for setting up Demo Mode.
class DemoSetupController class DemoSetupController
: public EnterpriseEnrollmentHelper::EnrollmentStatusConsumer { : public EnterpriseEnrollmentHelper::EnrollmentStatusConsumer,
public policy::CloudPolicyStore::Observer {
public: public:
// Delegate that will be notified about result of setup flow when it is // Delegate that will be notified about result of setup flow when it is
// finished. // finished.
...@@ -20,8 +26,9 @@ class DemoSetupController ...@@ -20,8 +26,9 @@ class DemoSetupController
public: public:
virtual ~Delegate() = default; virtual ~Delegate() = default;
// Called when the setup flow finished with error. // Called when the setup flow finished with error. |message| contains
virtual void OnSetupError() = 0; // the error message to describe the error details.
virtual void OnSetupError(const std::string& message) = 0;
// Called when the setup flow finished successfully. // Called when the setup flow finished successfully.
virtual void OnSetupSuccess() = 0; virtual void OnSetupSuccess() = 0;
...@@ -36,8 +43,9 @@ class DemoSetupController ...@@ -36,8 +43,9 @@ class DemoSetupController
// Initiates offline enrollment that locks the device and sets up offline // Initiates offline enrollment that locks the device and sets up offline
// policies required by Demo Mode. It requires no network connectivity since // policies required by Demo Mode. It requires no network connectivity since
// and all setup will be done locally. // and all setup will be done locally. The policy files will be loaded
void EnrollOffline(); // from the |base_path|.
void EnrollOffline(const base::FilePath& base_path);
// EnterpriseEnrollmentHelper::EnrollmentStatusConsumer: // EnterpriseEnrollmentHelper::EnrollmentStatusConsumer:
void OnDeviceEnrolled(const std::string& additional_token) override; void OnDeviceEnrolled(const std::string& additional_token) override;
...@@ -49,11 +57,43 @@ class DemoSetupController ...@@ -49,11 +57,43 @@ class DemoSetupController
void OnMultipleLicensesAvailable( void OnMultipleLicensesAvailable(
const EnrollmentLicenseMap& licenses) override; const EnrollmentLicenseMap& licenses) override;
void SetDeviceLocalAccountPolicyStoreForTest(policy::CloudPolicyStore* store);
private: private:
// Called when the checks of policy files for the offline demo mode is done.
void OnOfflinePolicyFilesExisted(std::string* message, bool ok);
// Called when the device local account policy for the offline demo mode is
// loaded.
void OnDeviceLocalAccountPolicyLoaded(base::Optional<std::string> blob);
// Finish the flow with an error message.
void SetupFailed(const std::string& message);
// Clears the internal state.
void Reset();
// policy::CloudPolicyStore::Observer:
void OnStoreLoaded(policy::CloudPolicyStore* store) override;
void OnStoreError(policy::CloudPolicyStore* store) override;
Delegate* delegate_ = nullptr; Delegate* delegate_ = nullptr;
// The mode of the current enrollment flow.
policy::EnrollmentConfig::Mode mode_ = policy::EnrollmentConfig::MODE_NONE;
// The directory which contains the policy blob files for the offline
// enrollment (i.e. device_policy and local_account_policy). Should be empty
// on the online enrollment.
base::FilePath policy_dir_;
// The CloudPolicyStore for the device local account for the offline policy.
policy::CloudPolicyStore* device_local_account_policy_store_ = nullptr;
std::unique_ptr<EnterpriseEnrollmentHelper> enrollment_helper_; std::unique_ptr<EnterpriseEnrollmentHelper> enrollment_helper_;
base::WeakPtrFactory<DemoSetupController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DemoSetupController); DISALLOW_COPY_AND_ASSIGN(DemoSetupController);
}; };
......
...@@ -3,31 +3,98 @@ ...@@ -3,31 +3,98 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h" #include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_mock.h" #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_mock.h"
#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h" #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chromeos/cryptohome/system_salt_getter.h" #include "chromeos/cryptohome/system_salt_getter.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using testing::_;
namespace chromeos { namespace chromeos {
namespace { namespace {
class MockDemoSetupControllerDelegate : public DemoSetupController::Delegate { class MockDemoSetupControllerDelegate : public DemoSetupController::Delegate {
public: public:
MockDemoSetupControllerDelegate() = default; MockDemoSetupControllerDelegate()
: run_loop_(std::make_unique<base::RunLoop>()) {}
~MockDemoSetupControllerDelegate() override = default; ~MockDemoSetupControllerDelegate() override = default;
MOCK_METHOD0(OnSetupError, void()); void OnSetupError(const std::string&) override {
MOCK_METHOD0(OnSetupSuccess, void()); EXPECT_FALSE(succeeded_.has_value());
succeeded_ = false;
run_loop_->Quit();
}
void OnSetupSuccess() override {
EXPECT_FALSE(succeeded_.has_value());
succeeded_ = true;
run_loop_->Quit();
}
// Wait until the setup result arrives (either OnSetupError or OnSetupSuccess
// is called), returns true when the result matches with |expected|.
bool WaitResult(bool expected) {
// Run() stops immediately if Quit is already called.
run_loop_->Run();
return succeeded_.has_value() && succeeded_.value() == expected;
}
void Reset() {
succeeded_.reset();
run_loop_ = std::make_unique<base::RunLoop>();
}
private: private:
base::Optional<bool> succeeded_;
std::unique_ptr<base::RunLoop> run_loop_;
DISALLOW_COPY_AND_ASSIGN(MockDemoSetupControllerDelegate); DISALLOW_COPY_AND_ASSIGN(MockDemoSetupControllerDelegate);
}; };
bool SetupDummyOfflineDir(const std::string& account_id,
base::ScopedTempDir* temp_dir) {
if (!temp_dir->CreateUniqueTempDir()) {
LOG(ERROR) << "Failed to create unique tempdir";
return false;
}
if (base::WriteFile(temp_dir->GetPath().AppendASCII("device_policy"), "",
0) != 0) {
LOG(ERROR) << "Failed to create device_policy file";
return false;
}
// We use MockCloudPolicyStore for the device local account policy in the
// tests, thus actual policy content can be empty. account_id is specified
// since it is used by DemoSetupController to look up the store.
std::string policy_blob;
if (!account_id.empty()) {
enterprise_management::PolicyData policy_data;
policy_data.set_username(account_id);
enterprise_management::PolicyFetchResponse policy;
policy.set_policy_data(policy_data.SerializeAsString());
policy_blob = policy.SerializeAsString();
}
if (base::WriteFile(temp_dir->GetPath().AppendASCII("local_account_policy"),
policy_blob.data(), policy_blob.size()) !=
static_cast<int>(policy_blob.size())) {
LOG(ERROR) << "Failed to create local_account_policy file";
return false;
}
return true;
}
} // namespace } // namespace
class DemoSetupControllerTest : public testing::Test { class DemoSetupControllerTest : public testing::Test {
...@@ -42,6 +109,8 @@ class DemoSetupControllerTest : public testing::Test { ...@@ -42,6 +109,8 @@ class DemoSetupControllerTest : public testing::Test {
EnterpriseEnrollmentHelperMock* mock = EnterpriseEnrollmentHelperMock* mock =
new EnterpriseEnrollmentHelperMock(status_consumer); new EnterpriseEnrollmentHelperMock(status_consumer);
EXPECT_EQ(enrollment_config.mode,
policy::EnrollmentConfig::MODE_ATTESTATION);
EXPECT_CALL(*mock, EnrollUsingAttestation()) EXPECT_CALL(*mock, EnrollUsingAttestation())
.WillRepeatedly(testing::Invoke([mock]() { .WillRepeatedly(testing::Invoke([mock]() {
if (result == SetupResult::SUCCESS) { if (result == SetupResult::SUCCESS) {
...@@ -64,6 +133,8 @@ class DemoSetupControllerTest : public testing::Test { ...@@ -64,6 +133,8 @@ class DemoSetupControllerTest : public testing::Test {
EnterpriseEnrollmentHelperMock* mock = EnterpriseEnrollmentHelperMock* mock =
new EnterpriseEnrollmentHelperMock(status_consumer); new EnterpriseEnrollmentHelperMock(status_consumer);
EXPECT_EQ(enrollment_config.mode,
policy::EnrollmentConfig::MODE_OFFLINE_DEMO);
EXPECT_CALL(*mock, EnrollForOfflineDemo()) EXPECT_CALL(*mock, EnrollForOfflineDemo())
.WillRepeatedly(testing::Invoke([mock]() { .WillRepeatedly(testing::Invoke([mock]() {
if (result == SetupResult::SUCCESS) { if (result == SetupResult::SUCCESS) {
...@@ -78,17 +149,15 @@ class DemoSetupControllerTest : public testing::Test { ...@@ -78,17 +149,15 @@ class DemoSetupControllerTest : public testing::Test {
return mock; return mock;
} }
DemoSetupControllerTest() DemoSetupControllerTest() = default;
: delegate_(std::make_unique<MockDemoSetupControllerDelegate>()),
tested_controller_(
std::make_unique<DemoSetupController>(delegate_.get())) {}
~DemoSetupControllerTest() override = default; ~DemoSetupControllerTest() override = default;
void SetUp() override { void SetUp() override {
SystemSaltGetter::Initialize(); SystemSaltGetter::Initialize();
DBusThreadManager::Initialize(); DBusThreadManager::Initialize();
DeviceSettingsService::Initialize(); DeviceSettingsService::Initialize();
delegate_ = std::make_unique<MockDemoSetupControllerDelegate>();
tested_controller_ = std::make_unique<DemoSetupController>(delegate_.get());
} }
void TearDown() override { void TearDown() override {
...@@ -107,39 +176,106 @@ class DemoSetupControllerTest : public testing::Test { ...@@ -107,39 +176,106 @@ class DemoSetupControllerTest : public testing::Test {
}; };
TEST_F(DemoSetupControllerTest, OfflineSuccess) { TEST_F(DemoSetupControllerTest, OfflineSuccess) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(SetupDummyOfflineDir("test", &temp_dir));
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOfflineEnrollmentHelperCreator<SetupResult::SUCCESS>);
policy::MockCloudPolicyStore mock_store;
EXPECT_CALL(mock_store, Store(_))
.WillOnce(testing::InvokeWithoutArgs(
&mock_store, &policy::MockCloudPolicyStore::NotifyStoreLoaded));
tested_controller_->SetDeviceLocalAccountPolicyStoreForTest(&mock_store);
tested_controller_->EnrollOffline(temp_dir.GetPath());
EXPECT_TRUE(delegate_->WaitResult(true));
}
TEST_F(DemoSetupControllerTest, OfflineDeviceLocalAccountPolicyLoadFailure) {
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock( EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOfflineEnrollmentHelperCreator<SetupResult::SUCCESS>); &MockOfflineEnrollmentHelperCreator<SetupResult::SUCCESS>);
EXPECT_CALL(*delegate_, OnSetupSuccess()).Times(1); policy::MockCloudPolicyStore mock_store;
EXPECT_CALL(mock_store, Store(_)).Times(0);
tested_controller_->SetDeviceLocalAccountPolicyStoreForTest(&mock_store);
tested_controller_->EnrollOffline(); tested_controller_->EnrollOffline(
base::FilePath(FILE_PATH_LITERAL("/no/such/path")));
EXPECT_TRUE(delegate_->WaitResult(false));
}
TEST_F(DemoSetupControllerTest, OfflineDeviceLocalAccountPolicyStoreFailed) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(SetupDummyOfflineDir("test", &temp_dir));
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOfflineEnrollmentHelperCreator<SetupResult::SUCCESS>);
policy::MockCloudPolicyStore mock_store;
EXPECT_CALL(mock_store, Store(_))
.WillOnce(testing::InvokeWithoutArgs(
&mock_store, &policy::MockCloudPolicyStore::NotifyStoreError));
tested_controller_->SetDeviceLocalAccountPolicyStoreForTest(&mock_store);
tested_controller_->EnrollOffline(temp_dir.GetPath());
EXPECT_TRUE(delegate_->WaitResult(false));
}
TEST_F(DemoSetupControllerTest, OfflineInvalidDeviceLocalAccountPolicyBlob) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(SetupDummyOfflineDir("", &temp_dir));
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOfflineEnrollmentHelperCreator<SetupResult::SUCCESS>);
tested_controller_->EnrollOffline(temp_dir.GetPath());
EXPECT_TRUE(delegate_->WaitResult(false));
} }
TEST_F(DemoSetupControllerTest, OfflineError) { TEST_F(DemoSetupControllerTest, OfflineError) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(SetupDummyOfflineDir("test", &temp_dir));
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock( EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOfflineEnrollmentHelperCreator<SetupResult::ERROR>); &MockOfflineEnrollmentHelperCreator<SetupResult::ERROR>);
EXPECT_CALL(*delegate_, OnSetupError()).Times(1); policy::MockCloudPolicyStore mock_store;
EXPECT_CALL(mock_store, Store(_)).Times(0);
tested_controller_->SetDeviceLocalAccountPolicyStoreForTest(&mock_store);
tested_controller_->EnrollOffline(); tested_controller_->EnrollOffline(temp_dir.GetPath());
EXPECT_TRUE(delegate_->WaitResult(false));
} }
TEST_F(DemoSetupControllerTest, OnlineSuccess) { TEST_F(DemoSetupControllerTest, OnlineSuccess) {
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock( EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOnlineEnrollmentHelperCreator<SetupResult::SUCCESS>); &MockOnlineEnrollmentHelperCreator<SetupResult::SUCCESS>);
EXPECT_CALL(*delegate_, OnSetupSuccess()).Times(1);
tested_controller_->EnrollOnline(); tested_controller_->EnrollOnline();
EXPECT_TRUE(delegate_->WaitResult(true));
} }
TEST_F(DemoSetupControllerTest, OnlineError) { TEST_F(DemoSetupControllerTest, OnlineError) {
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock( EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOnlineEnrollmentHelperCreator<SetupResult::ERROR>); &MockOnlineEnrollmentHelperCreator<SetupResult::ERROR>);
EXPECT_CALL(*delegate_, OnSetupError()).Times(1); tested_controller_->EnrollOnline();
EXPECT_TRUE(delegate_->WaitResult(false));
}
TEST_F(DemoSetupControllerTest, EnrollTwice) {
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOnlineEnrollmentHelperCreator<SetupResult::ERROR>);
tested_controller_->EnrollOnline();
EXPECT_TRUE(delegate_->WaitResult(false));
delegate_->Reset();
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockOnlineEnrollmentHelperCreator<SetupResult::SUCCESS>);
tested_controller_->EnrollOnline(); tested_controller_->EnrollOnline();
EXPECT_TRUE(delegate_->WaitResult(true));
} }
} // namespace chromeos } // namespace chromeos
...@@ -163,6 +163,8 @@ bool EnterpriseEnrollmentHelperImpl::ShouldCheckLicenseType() const { ...@@ -163,6 +163,8 @@ bool EnterpriseEnrollmentHelperImpl::ShouldCheckLicenseType() const {
void EnterpriseEnrollmentHelperImpl::DoEnroll(const std::string& token) { void EnterpriseEnrollmentHelperImpl::DoEnroll(const std::string& token) {
DCHECK(token == oauth_token_ || oauth_token_.empty()); DCHECK(token == oauth_token_ || oauth_token_.empty());
DCHECK(enrollment_config_.is_mode_attestation() || DCHECK(enrollment_config_.is_mode_attestation() ||
enrollment_config_.mode ==
policy::EnrollmentConfig::MODE_OFFLINE_DEMO ||
oauth_status_ == OAUTH_STARTED_WITH_AUTH_CODE || oauth_status_ == OAUTH_STARTED_WITH_AUTH_CODE ||
oauth_status_ == OAUTH_STARTED_WITH_TOKEN); oauth_status_ == OAUTH_STARTED_WITH_TOKEN);
oauth_token_ = token; oauth_token_ = token;
...@@ -493,6 +495,10 @@ void EnterpriseEnrollmentHelperImpl::ReportEnrollmentStatus( ...@@ -493,6 +495,10 @@ void EnterpriseEnrollmentHelperImpl::ReportEnrollmentStatus(
case policy::EnrollmentStatus::LICENSE_REQUEST_FAILED: case policy::EnrollmentStatus::LICENSE_REQUEST_FAILED:
UMA(policy::kMetricEnrollmentLicenseRequestFailed); UMA(policy::kMetricEnrollmentLicenseRequestFailed);
break; break;
case policy::EnrollmentStatus::OFFLINE_POLICY_LOAD_FAILED:
case policy::EnrollmentStatus::OFFLINE_POLICY_DECODING_FAILED:
UMA(policy::kMetricEnrollmentRegisterPolicyResponseInvalid);
break;
} }
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chrome/browser/chromeos/login/screens/demo_setup_screen.h" #include "chrome/browser/chromeos/login/screens/demo_setup_screen.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/login/screen_manager.h" #include "chrome/browser/chromeos/login/screen_manager.h"
#include "chrome/browser/chromeos/login/screens/base_screen_delegate.h" #include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
#include "chrome/browser/chromeos/policy/enrollment_config.h" #include "chrome/browser/chromeos/policy/enrollment_config.h"
...@@ -14,6 +16,11 @@ constexpr const char kUserActionOnlineSetup[] = "online-setup"; ...@@ -14,6 +16,11 @@ constexpr const char kUserActionOnlineSetup[] = "online-setup";
constexpr const char kUserActionOfflineSetup[] = "offline-setup"; constexpr const char kUserActionOfflineSetup[] = "offline-setup";
constexpr const char kUserActionClose[] = "close-setup"; constexpr const char kUserActionClose[] = "close-setup";
// The policy blob data for offline demo-mode is embedded into the filesystem.
// TODO(mukai, agawronska): fix this when switching to dm-verity image.
constexpr const base::FilePath::CharType kOfflineDemoModeDir[] =
FILE_PATH_LITERAL("/usr/share/chromeos-assets/demo_mode_resources/policy");
} // namespace } // namespace
namespace chromeos { namespace chromeos {
...@@ -46,7 +53,7 @@ void DemoSetupScreen::OnUserAction(const std::string& action_id) { ...@@ -46,7 +53,7 @@ void DemoSetupScreen::OnUserAction(const std::string& action_id) {
if (action_id == kUserActionOnlineSetup) { if (action_id == kUserActionOnlineSetup) {
demo_controller_->EnrollOnline(); demo_controller_->EnrollOnline();
} else if (action_id == kUserActionOfflineSetup) { } else if (action_id == kUserActionOfflineSetup) {
demo_controller_->EnrollOffline(); demo_controller_->EnrollOffline(base::FilePath(kOfflineDemoModeDir));
} else if (action_id == kUserActionClose) { } else if (action_id == kUserActionClose) {
Finish(ScreenExitCode::DEMO_MODE_SETUP_CANCELED); Finish(ScreenExitCode::DEMO_MODE_SETUP_CANCELED);
} else { } else {
...@@ -54,8 +61,9 @@ void DemoSetupScreen::OnUserAction(const std::string& action_id) { ...@@ -54,8 +61,9 @@ void DemoSetupScreen::OnUserAction(const std::string& action_id) {
} }
} }
void DemoSetupScreen::OnSetupError() { void DemoSetupScreen::OnSetupError(const std::string& message) {
NOTIMPLEMENTED(); LOG(ERROR) << "Failure on setting up demo mode: " << message;
// TODO(mukai): show the error messages on screen.
} }
void DemoSetupScreen::OnSetupSuccess() { void DemoSetupScreen::OnSetupSuccess() {
......
...@@ -30,7 +30,7 @@ class DemoSetupScreen : public BaseScreen, ...@@ -30,7 +30,7 @@ class DemoSetupScreen : public BaseScreen,
void OnUserAction(const std::string& action_id) override; void OnUserAction(const std::string& action_id) override;
// DemoSetupManager::Delegate: // DemoSetupManager::Delegate:
void OnSetupError() override; void OnSetupError(const std::string& message) override;
void OnSetupSuccess() override; void OnSetupSuccess() override;
// Called when view is being destroyed. If Screen is destroyed earlier // Called when view is being destroyed. If Screen is destroyed earlier
......
// Copyright 2018 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/enrollment_config.h"
namespace policy {
EnrollmentConfig::EnrollmentConfig() = default;
EnrollmentConfig::EnrollmentConfig(const EnrollmentConfig& other) = default;
EnrollmentConfig::~EnrollmentConfig() = default;
} // namespace policy
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <string> #include <string>
#include "base/files/file_path.h"
namespace policy { namespace policy {
// A container keeping all parameters relevant to whether and how enterprise // A container keeping all parameters relevant to whether and how enterprise
...@@ -62,6 +64,10 @@ struct EnrollmentConfig { ...@@ -62,6 +64,10 @@ struct EnrollmentConfig {
AUTH_MECHANISM_BEST_AVAILABLE, AUTH_MECHANISM_BEST_AVAILABLE,
}; };
EnrollmentConfig();
EnrollmentConfig(const EnrollmentConfig& config);
~EnrollmentConfig();
// Whether enrollment should be triggered. // Whether enrollment should be triggered.
bool should_enroll() const { bool should_enroll() const {
return should_enroll_with_attestation() || should_enroll_interactively(); return should_enroll_with_attestation() || should_enroll_interactively();
...@@ -118,6 +124,10 @@ struct EnrollmentConfig { ...@@ -118,6 +124,10 @@ struct EnrollmentConfig {
// The authentication mechanism to use. // The authentication mechanism to use.
// TODO(drcrash): Change to best available once ZTE is everywhere. // TODO(drcrash): Change to best available once ZTE is everywhere.
AuthMechanism auth_mechanism = AUTH_MECHANISM_INTERACTIVE; AuthMechanism auth_mechanism = AUTH_MECHANISM_INTERACTIVE;
// The path for the device policy blob data for the offline demo mode. This
// should be empty and never used for other modes.
base::FilePath offline_policy_path;
}; };
} // namespace policy } // namespace policy
......
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/guid.h"
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h" #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
...@@ -112,6 +112,18 @@ bool GetBlockdevmodeFromPolicy( ...@@ -112,6 +112,18 @@ bool GetBlockdevmodeFromPolicy(
return block_devmode; return block_devmode;
} }
// A utility funciton of base::ReadFileToString which returns an optional
// string.
// TODO(mukai): move this to base/files.
base::Optional<std::string> ReadFileToOptionalString(
const base::FilePath& file_path) {
std::string content;
base::Optional<std::string> result;
if (base::ReadFileToString(file_path, &content))
result = std::move(content);
return result;
}
} // namespace } // namespace
EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS( EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS(
...@@ -146,6 +158,8 @@ EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS( ...@@ -146,6 +158,8 @@ EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS(
CHECK((enrollment_config_.is_mode_attestation() || CHECK((enrollment_config_.is_mode_attestation() ||
enrollment_config.mode == EnrollmentConfig::MODE_OFFLINE_DEMO) == enrollment_config.mode == EnrollmentConfig::MODE_OFFLINE_DEMO) ==
auth_token_.empty()); auth_token_.empty());
CHECK_NE(enrollment_config.mode == EnrollmentConfig::MODE_OFFLINE_DEMO,
enrollment_config.offline_policy_path.empty());
CHECK(enrollment_config_.auth_mechanism != CHECK(enrollment_config_.auth_mechanism !=
EnrollmentConfig::AUTH_MECHANISM_ATTESTATION || EnrollmentConfig::AUTH_MECHANISM_ATTESTATION ||
attestation_flow_); attestation_flow_);
...@@ -246,31 +260,20 @@ void EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) { ...@@ -246,31 +260,20 @@ void EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) {
return; return;
} }
auto validator = std::make_unique<DeviceCloudPolicyValidator>(
std::make_unique<em::PolicyFetchResponse>(*policy),
background_task_runner_);
validator->ValidateTimestamp(base::Time(),
CloudPolicyValidatorBase::TIMESTAMP_VALIDATED);
// If this is re-enrollment, make sure that the new policy matches the // If this is re-enrollment, make sure that the new policy matches the
// previously-enrolled domain. (Currently only implemented for cloud // previously-enrolled domain. (Currently only implemented for cloud
// management.) // management.)
std::string domain; std::string domain;
if (install_attributes_->IsCloudManaged()) { if (install_attributes_->IsCloudManaged())
domain = install_attributes_->GetDomain(); domain = install_attributes_->GetDomain();
auto validator = CreateValidator(
std::make_unique<em::PolicyFetchResponse>(*policy), domain);
if (install_attributes_->IsCloudManaged())
validator->ValidateDomain(domain); validator->ValidateDomain(domain);
}
validator->ValidateDMToken(client->dm_token(), validator->ValidateDMToken(client->dm_token(),
CloudPolicyValidatorBase::DM_TOKEN_REQUIRED); CloudPolicyValidatorBase::DM_TOKEN_REQUIRED);
validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType);
validator->ValidatePayload();
// If |domain| is empty here, the policy validation code will just use the
// domain from the username field in the policy itself to do key validation.
// TODO(mnissler): Plumb the enrolling user's username into this object so we
// can validate the username on the resulting policy, and use the domain from
// that username to validate the key below (http://crbug.com/343074).
validator->ValidateInitialKey(domain);
DeviceCloudPolicyValidator::StartValidation( DeviceCloudPolicyValidator::StartValidation(
std::move(validator), std::move(validator),
base::Bind(&EnrollmentHandlerChromeOS::HandlePolicyValidationResult, base::Bind(&EnrollmentHandlerChromeOS::HandlePolicyValidationResult,
...@@ -406,21 +409,90 @@ void EnrollmentHandlerChromeOS::HandleRegistrationCertificateResult( ...@@ -406,21 +409,90 @@ void EnrollmentHandlerChromeOS::HandleRegistrationCertificateResult(
} }
void EnrollmentHandlerChromeOS::StartOfflineDemoEnrollmentFlow() { void EnrollmentHandlerChromeOS::StartOfflineDemoEnrollmentFlow() {
// TODO(mukai): set |policy_| which are obtained offline to enforce the actual DCHECK(!enrollment_config_.offline_policy_path.empty());
// policy for offline-demo mode. https://crbug.com/827290
device_mode_ = policy::DeviceMode::DEVICE_MODE_ENTERPRISE; device_mode_ = policy::DeviceMode::DEVICE_MODE_ENTERPRISE;
domain_ = enrollment_config_.management_domain; domain_ = enrollment_config_.management_domain;
device_id_ = base::GenerateGUID();
skip_robot_auth_ = true; skip_robot_auth_ = true;
if (!policy_) { SetStep(STEP_POLICY_FETCH);
ReportResult(
EnrollmentStatus::ForStatus(EnrollmentStatus::POLICY_FETCH_FAILED)); base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&ReadFileToOptionalString,
enrollment_config_.offline_policy_path),
base::BindOnce(&EnrollmentHandlerChromeOS::OnOfflinePolicyBlobLoaded,
weak_ptr_factory_.GetWeakPtr()));
}
void EnrollmentHandlerChromeOS::OnOfflinePolicyBlobLoaded(
base::Optional<std::string> blob) {
DCHECK_EQ(EnrollmentConfig::MODE_OFFLINE_DEMO, enrollment_config_.mode);
DCHECK_EQ(STEP_POLICY_FETCH, enrollment_step_);
if (!blob.has_value()) {
ReportResult(EnrollmentStatus::ForStatus(
EnrollmentStatus::OFFLINE_POLICY_LOAD_FAILED));
return;
}
SetStep(STEP_VALIDATION);
// Validate the policy.
auto policy = std::make_unique<em::PolicyFetchResponse>();
if (!policy->ParseFromString(blob.value())) {
ReportResult(EnrollmentStatus::ForStatus(
EnrollmentStatus::OFFLINE_POLICY_DECODING_FAILED));
return; return;
} }
// Validate the device policy for the offline demo mode.
auto validator = CreateValidator(std::move(policy), domain_);
validator->ValidateDomain(domain_);
DeviceCloudPolicyValidator::StartValidation(
std::move(validator),
base::Bind(&EnrollmentHandlerChromeOS::OnOfflinePolicyValidated,
weak_ptr_factory_.GetWeakPtr()));
}
void EnrollmentHandlerChromeOS::OnOfflinePolicyValidated(
DeviceCloudPolicyValidator* validator) {
DCHECK_EQ(enrollment_config_.mode, EnrollmentConfig::MODE_OFFLINE_DEMO);
DCHECK_EQ(STEP_VALIDATION, enrollment_step_);
if (!validator->success()) {
ReportResult(EnrollmentStatus::ForValidationError(validator->status()));
return;
}
device_id_ = validator->policy_data()->device_id();
policy_ = std::move(validator->policy());
// The steps for OAuth2 token fetching is skipped for the OFFLINE_DEMO_MODE.
SetStep(STEP_SET_FWMP_DATA); SetStep(STEP_SET_FWMP_DATA);
SetFirmwareManagementParametersData(); SetFirmwareManagementParametersData();
} }
std::unique_ptr<DeviceCloudPolicyValidator>
EnrollmentHandlerChromeOS::CreateValidator(
std::unique_ptr<enterprise_management::PolicyFetchResponse> policy,
const std::string& domain) {
auto validator = std::make_unique<DeviceCloudPolicyValidator>(
std::move(policy), background_task_runner_);
validator->ValidateTimestamp(base::Time(),
CloudPolicyValidatorBase::TIMESTAMP_VALIDATED);
validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType);
validator->ValidatePayload();
// If |domain| is empty here, the policy validation code will just use the
// domain from the username field in the policy itself to do key validation.
// TODO(mnissler): Plumb the enrolling user's username into this object so we
// can validate the username on the resulting policy, and use the domain from
// that username to validate the key below (http://crbug.com/343074).
validator->ValidateInitialKey(domain);
return validator;
}
void EnrollmentHandlerChromeOS::HandlePolicyValidationResult( void EnrollmentHandlerChromeOS::HandlePolicyValidationResult(
DeviceCloudPolicyValidator* validator) { DeviceCloudPolicyValidator* validator) {
DCHECK_EQ(STEP_VALIDATION, enrollment_step_); DCHECK_EQ(STEP_VALIDATION, enrollment_step_);
......
...@@ -204,6 +204,16 @@ class EnrollmentHandlerChromeOS : public CloudPolicyClient::Observer, ...@@ -204,6 +204,16 @@ class EnrollmentHandlerChromeOS : public CloudPolicyClient::Observer,
// Handles result from device policy refresh via authpolicyd. // Handles result from device policy refresh via authpolicyd.
void HandleActiveDirectoryPolicyRefreshed(authpolicy::ErrorType error); void HandleActiveDirectoryPolicyRefreshed(authpolicy::ErrorType error);
// Handles the blob for the device policy for the offline demo mode.
void OnOfflinePolicyBlobLoaded(base::Optional<std::string> blob);
// Handles the policy validation result for the offline demo mode.
void OnOfflinePolicyValidated(DeviceCloudPolicyValidator* validator);
std::unique_ptr<DeviceCloudPolicyValidator> CreateValidator(
std::unique_ptr<enterprise_management::PolicyFetchResponse> policy,
const std::string& domain);
// Drops any ongoing actions. // Drops any ongoing actions.
void Stop(); void Stop();
......
...@@ -46,6 +46,10 @@ class EnrollmentStatus { ...@@ -46,6 +46,10 @@ class EnrollmentStatus {
DM_TOKEN_STORE_FAILED = 18, // Failed to store DM token into the DM_TOKEN_STORE_FAILED = 18, // Failed to store DM token into the
// local state. // local state.
LICENSE_REQUEST_FAILED = 19, // Failed to get available license types. LICENSE_REQUEST_FAILED = 19, // Failed to get available license types.
OFFLINE_POLICY_LOAD_FAILED = 20, // Failed to load the policy data for the
// offline demo mode.
OFFLINE_POLICY_DECODING_FAILED = 21, // Failed when the policy data fails
// to be decoded.
}; };
// Helpers for constructing errors for relevant cases. // Helpers for constructing errors for relevant cases.
......
...@@ -474,6 +474,12 @@ void EnrollmentScreenHandler::ShowEnrollmentStatus( ...@@ -474,6 +474,12 @@ void EnrollmentScreenHandler::ShowEnrollmentStatus(
case policy::EnrollmentStatus::LICENSE_REQUEST_FAILED: case policy::EnrollmentStatus::LICENSE_REQUEST_FAILED:
ShowError(IDS_ENTERPRISE_ENROLLMENT_ERROR_LICENSE_REQUEST, false); ShowError(IDS_ENTERPRISE_ENROLLMENT_ERROR_LICENSE_REQUEST, false);
return; return;
case policy::EnrollmentStatus::OFFLINE_POLICY_LOAD_FAILED:
case policy::EnrollmentStatus::OFFLINE_POLICY_DECODING_FAILED:
// OFFLINE_POLICY_LOAD_FAILED and OFFLINE_POLICY_DECODING_FAILED happen
// only within MODE_OFFLINE_DEMO flow, which shouldn't happen here.
NOTREACHED();
return;
} }
NOTREACHED(); NOTREACHED();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment