Commit 2fa5e2d1 authored by Andreea Costinas's avatar Andreea Costinas Committed by Commit Bot

Add System-proxy client

Adds a real and a fake implementation of a D-Bus client that talks to
the the System-proxy daemon in Chrome OS.

BUG=chromium:1042621
TEST=unit_tests  --gtest_filter=*SystemProxySettingsPolicyHandlerTest*
     manually tested on a device

Change-Id: I456be37c7e540ec30afa2e4d5d5832e33112867e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2051847Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarPavol Marko <pmarko@chromium.org>
Commit-Queue: Andreea-Elena Costinas <acostinas@google.com>
Cr-Commit-Position: refs/heads/master@{#744212}
parent f313a9a5
......@@ -142,6 +142,8 @@ source_set("chromeos") {
"//chromeos/dbus/session_manager",
"//chromeos/dbus/session_manager:login_manager_proto",
"//chromeos/dbus/system_clock",
"//chromeos/dbus/system_proxy",
"//chromeos/dbus/system_proxy:system_proxy_proto",
"//chromeos/dbus/upstart",
"//chromeos/disks",
"//chromeos/geolocation",
......
......@@ -27,6 +27,7 @@
#include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/dbus/session_manager/session_manager_client.h"
#include "chromeos/dbus/system_clock/system_clock_client.h"
#include "chromeos/dbus/system_proxy/system_proxy_client.h"
#include "chromeos/dbus/upstart/upstart_client.h"
#include "chromeos/tpm/install_attributes.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
......@@ -73,6 +74,7 @@ void InitializeDBus() {
InitializeDBusClient<PowerManagerClient>(bus);
InitializeDBusClient<SessionManagerClient>(bus);
InitializeDBusClient<SystemClockClient>(bus);
InitializeDBusClient<SystemProxyClient>(bus);
InitializeDBusClient<UpstartClient>(bus);
// Initialize the device settings service so that we'll take actions per
......@@ -96,6 +98,7 @@ void ShutdownDBus() {
// Other D-Bus clients are shut down, also in reverse order of initialization.
UpstartClient::Shutdown();
SystemProxyClient::Shutdown();
SystemClockClient::Shutdown();
SessionManagerClient::Shutdown();
PowerManagerClient::Shutdown();
......
......@@ -636,6 +636,15 @@ void DecodeNetworkPolicies(const em::ChromeDeviceSettingsProto& policy,
}
}
}
if (policy.has_system_proxy_settings()) {
const em::SystemProxySettingsProto& settings_proto(
policy.system_proxy_settings());
if (settings_proto.has_system_proxy_settings()) {
SetJsonDevicePolicy(key::kSystemProxySettings,
settings_proto.system_proxy_settings(), policies);
}
}
}
void DecodeReportingPolicies(const em::ChromeDeviceSettingsProto& policy,
......
......@@ -6,9 +6,16 @@
#include "base/bind.h"
#include "base/values.h"
#include "chromeos/dbus/system_proxy/system_proxy_client.h"
#include "chromeos/dbus/system_proxy/system_proxy_service.pb.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/settings/cros_settings_names.h"
#include "chromeos/settings/cros_settings_provider.h"
namespace {
const char kSystemProxyService[] = "system-proxy-service";
}
namespace policy {
SystemProxySettingsPolicyHandler::SystemProxySettingsPolicyHandler(
......@@ -39,8 +46,63 @@ void SystemProxySettingsPolicyHandler::OnSystemProxySettingsPolicyChanged() {
if (!proxy_settings)
return;
// TODO(acostinas, chromium:1042626) Start/stop and configure system traffic
// credentials for System-proxy daemon according to policy.
bool enabled =
proxy_settings->FindBoolKey(chromeos::kSystemProxySettingsKeyEnabled)
.value_or(false);
// System-proxy is inactive by default.
if (!enabled) {
// Send a shut-down command to the daemon. Since System-proxy is started via
// dbus activation, if the daemon is inactive, this command will start the
// daemon and tell it to exit.
// TODO(crbug.com/1055245,acostinas): Do not send shut-down command if
// System-proxy is inactive.
chromeos::SystemProxyClient::Get()->ShutDownDaemon(
base::BindOnce(&SystemProxySettingsPolicyHandler::OnDaemonShutDown,
weak_factory_.GetWeakPtr()));
return;
}
const std::string* username = proxy_settings->FindStringKey(
chromeos::kSystemProxySettingsKeySystemServicesUsername);
const std::string* password = proxy_settings->FindStringKey(
chromeos::kSystemProxySettingsKeySystemServicesPassword);
if (!username || username->empty() || !password || password->empty()) {
NET_LOG_ERROR("Proxy credentials for system traffic not set.",
kSystemProxyService);
return;
}
system_proxy::SetSystemTrafficCredentialsRequest request;
request.set_system_services_username(*username);
request.set_system_services_password(*password);
chromeos::SystemProxyClient::Get()->SetSystemTrafficCredentials(
request,
base::BindOnce(
&SystemProxySettingsPolicyHandler::OnSetSystemTrafficCredentials,
weak_factory_.GetWeakPtr()));
}
void SystemProxySettingsPolicyHandler::OnSetSystemTrafficCredentials(
const system_proxy::SetSystemTrafficCredentialsResponse& response) {
if (response.has_error_message()) {
NET_LOG_ERROR(
"Failed to set system traffic credentials for system proxy with "
"error: " +
response.error_message(),
kSystemProxyService);
}
}
void SystemProxySettingsPolicyHandler::OnDaemonShutDown(
const system_proxy::ShutDownResponse& response) {
if (response.has_error_message() && !response.error_message().empty()) {
NET_LOG_ERROR("Failed to shutdown system proxy with error: " +
response.error_message(),
kSystemProxyService);
}
}
} // namespace policy
......@@ -10,6 +10,11 @@
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
namespace system_proxy {
class SetSystemTrafficCredentialsResponse;
class ShutDownResponse;
} // namespace system_proxy
namespace policy {
// This class observes the device setting |SystemProxySettings|, and controls
......@@ -28,6 +33,10 @@ class SystemProxySettingsPolicyHandler {
~SystemProxySettingsPolicyHandler();
private:
void OnSetSystemTrafficCredentials(
const system_proxy::SetSystemTrafficCredentialsResponse& response);
void OnDaemonShutDown(const system_proxy::ShutDownResponse& response);
// Once a trusted set of policies is established, this function calls
// the System-proxy dbus client to start/shutdown the daemon and, if
// necessary, to configure the web proxy credentials for system services.
......
......@@ -7,19 +7,22 @@
#include "base/test/task_environment.h"
#include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
#include "chromeos/dbus/system_proxy/system_proxy_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
class SystemProxySettingsPolicyHandlerTest : public testing::Test {
protected:
public:
SystemProxySettingsPolicyHandlerTest() = default;
~SystemProxySettingsPolicyHandlerTest() override = default;
// testing::Test
void SetUp() override { testing::Test::SetUp(); }
void SetUp() override {
testing::Test::SetUp();
chromeos::SystemProxyClient::InitializeFake();
}
void TearDown() override {}
void TearDown() override { chromeos::SystemProxyClient::Shutdown(); }
protected:
void SetPolicy(bool system_proxy_enabled,
......@@ -35,22 +38,50 @@ class SystemProxySettingsPolicyHandlerTest : public testing::Test {
chromeos::kSystemProxySettings, dict);
}
chromeos::SystemProxyClient::TestInterface* client_test_interface() {
return chromeos::SystemProxyClient::Get()->GetTestInterface();
}
base::test::TaskEnvironment task_environment_;
chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_;
};
// Verifies that System-proxy is started and shutdown according to the
// |kSystemProxySettings| policy.
TEST_F(SystemProxySettingsPolicyHandlerTest, SystemProxyStartShutdown) {
// Verifies that System-proxy is configured with the system traffic credentials
// set by |kSystemProxySettings| policy.
TEST_F(SystemProxySettingsPolicyHandlerTest, SetSystemTrafficCredentials) {
SystemProxySettingsPolicyHandler proxy_policy_handler(
chromeos::CrosSettings::Get());
EXPECT_EQ(0,
client_test_interface()->GetSetSystemTrafficCredentialsCallCount());
// TODO(acostinas, chromium:1042626) Add test logic when the dbus client for
// System-proxy is implemented.
SetPolicy(true /* system_proxy_enabled */, "" /* system_services_username */,
"" /* system_services_password */);
task_environment_.RunUntilIdle();
// Don't send empty credentials.
EXPECT_EQ(0,
client_test_interface()->GetSetSystemTrafficCredentialsCallCount());
SetPolicy(true /* system_proxy_enabled */,
"test" /* system_services_username */,
"test" /* system_services_password */);
task_environment_.RunUntilIdle();
EXPECT_EQ(1,
client_test_interface()->GetSetSystemTrafficCredentialsCallCount());
}
// Verifies requests to shut down are sent to System-proxy according to the
// |kSystemProxySettings| policy.
TEST_F(SystemProxySettingsPolicyHandlerTest, ShutDownDaemon) {
SystemProxySettingsPolicyHandler proxy_policy_handler(
chromeos::CrosSettings::Get());
EXPECT_EQ(0, client_test_interface()->GetShutDownCallCount());
SetPolicy(false /* system_proxy_enabled */, "" /* system_services_username */,
"" /* system_services_password */);
task_environment_.RunUntilIdle();
// Don't send empty credentials.
EXPECT_EQ(1, client_test_interface()->GetShutDownCallCount());
}
} // namespace policy
# Copyright 2020 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.
import("//third_party/protobuf/proto_library.gni")
assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
component("system_proxy") {
defines = [ "IS_SYSTEM_PROXY_IMPL" ]
deps = [
":system_proxy_proto",
"//base",
"//dbus",
]
sources = [
"fake_system_proxy_client.cc",
"fake_system_proxy_client.h",
"system_proxy_client.cc",
"system_proxy_client.h",
]
}
proto_library("system_proxy_proto") {
sources = [ "//third_party/cros_system_api/dbus/system_proxy/system_proxy_service.proto" ]
proto_out_dir = "chromeos/dbus/system_proxy"
}
acostinas@google.com
pmarko@google.com
// Copyright 2020 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 "chromeos/dbus/system_proxy/fake_system_proxy_client.h"
#include "base/bind.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chromeos/dbus/system_proxy/system_proxy_service.pb.h"
namespace chromeos {
FakeSystemProxyClient::FakeSystemProxyClient() = default;
FakeSystemProxyClient::~FakeSystemProxyClient() = default;
void FakeSystemProxyClient::SetSystemTrafficCredentials(
const system_proxy::SetSystemTrafficCredentialsRequest& request,
SetSystemTrafficCredentialsCallback callback) {
++set_credentials_call_count_;
system_proxy::SetSystemTrafficCredentialsResponse response;
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), response));
}
void FakeSystemProxyClient::ShutDownDaemon(ShutDownDaemonCallback callback) {
++shut_down_call_count_;
system_proxy::ShutDownResponse response;
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), response));
}
SystemProxyClient::TestInterface* FakeSystemProxyClient::GetTestInterface() {
return this;
}
int FakeSystemProxyClient::GetSetSystemTrafficCredentialsCallCount() const {
return set_credentials_call_count_;
}
int FakeSystemProxyClient::GetShutDownCallCount() const {
return shut_down_call_count_;
}
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_DBUS_SYSTEM_PROXY_FAKE_SYSTEM_PROXY_CLIENT_H_
#define CHROMEOS_DBUS_SYSTEM_PROXY_FAKE_SYSTEM_PROXY_CLIENT_H_
#include "chromeos/dbus/system_proxy/system_proxy_client.h"
#include "chromeos/dbus/system_proxy/system_proxy_service.pb.h"
#include "dbus/object_proxy.h"
namespace chromeos {
class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeSystemProxyClient
: public SystemProxyClient,
public SystemProxyClient::TestInterface {
public:
FakeSystemProxyClient();
FakeSystemProxyClient(const FakeSystemProxyClient&) = delete;
FakeSystemProxyClient& operator=(const FakeSystemProxyClient&) = delete;
~FakeSystemProxyClient() override;
// SystemProxyClient implementation.
void SetSystemTrafficCredentials(
const system_proxy::SetSystemTrafficCredentialsRequest& request,
SetSystemTrafficCredentialsCallback callback) override;
void ShutDownDaemon(ShutDownDaemonCallback callback) override;
SystemProxyClient::TestInterface* GetTestInterface() override;
// SystemProxyClient::TestInterface implementation.
int GetSetSystemTrafficCredentialsCallCount() const override;
int GetShutDownCallCount() const override;
private:
int set_credentials_call_count_ = 0;
int shut_down_call_count_ = 0;
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_SYSTEM_PROXY_FAKE_SYSTEM_PROXY_CLIENT_H_
// Copyright 2020 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 "chromeos/dbus/system_proxy/system_proxy_client.h"
#include <utility>
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/dbus/system_proxy/fake_system_proxy_client.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "third_party/cros_system_api/dbus/system_proxy/dbus-constants.h"
namespace chromeos {
namespace {
SystemProxyClient* g_instance = nullptr;
const char kDbusCallFailure[] = "Failed to call system_proxy.";
const char kProtoMessageParsingFailure[] =
"Failed to parse response message from system_proxy.";
// Tries to parse a proto message from |response| into |proto| and returns null
// if successful. If |response| is nullptr or the message cannot be parsed it
// will return an appropriate error message.
const char* DeserializeProto(dbus::Response* response,
google::protobuf::MessageLite* proto) {
if (!response)
return kDbusCallFailure;
dbus::MessageReader reader(response);
if (!reader.PopArrayOfBytesAsProto(proto))
return kProtoMessageParsingFailure;
return nullptr;
}
// "Real" implementation of SystemProxyClient talking to the SystemProxy daemon
// on the Chrome OS side.
class SystemProxyClientImpl : public SystemProxyClient {
public:
SystemProxyClientImpl() = default;
SystemProxyClientImpl(const SystemProxyClientImpl&) = delete;
SystemProxyClientImpl& operator=(const SystemProxyClientImpl&) = delete;
~SystemProxyClientImpl() override = default;
// SystemProxyClient overrides:
void SetSystemTrafficCredentials(
const system_proxy::SetSystemTrafficCredentialsRequest& request,
SetSystemTrafficCredentialsCallback callback) override {
CallProtoMethodWithRequest(system_proxy::kSetSystemTrafficCredentialsMethod,
request, std::move(callback));
}
void ShutDownDaemon(ShutDownDaemonCallback callback) override {
CallProtoMethod(system_proxy::kShutDownMethod, std::move(callback));
}
void Init(dbus::Bus* bus) {
proxy_ = bus->GetObjectProxy(
system_proxy::kSystemProxyServiceName,
dbus::ObjectPath(system_proxy::kSystemProxyServicePath));
}
private:
TestInterface* GetTestInterface() override { return nullptr; }
// Calls System-proxy's |method_name| method. Once the (asynchronous) call
// finishes, |callback| is called with the response proto (on the same thread
// as this call).
template <class TResponse>
void CallProtoMethod(const char* method_name,
base::OnceCallback<void(const TResponse&)> callback) {
dbus::MethodCall method_call(system_proxy::kSystemProxyInterface,
method_name);
dbus::MessageWriter writer(&method_call);
proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&SystemProxyClientImpl::HandleResponse<TResponse>,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
// Same as |CallProtoMethod| but passes in |request| as input.
template <class TRequest, class TResponse>
void CallProtoMethodWithRequest(
const char* method_name,
const TRequest& request,
base::OnceCallback<void(const TResponse&)> callback) {
dbus::MethodCall method_call(system_proxy::kSystemProxyInterface,
method_name);
dbus::MessageWriter writer(&method_call);
if (!writer.AppendProtoAsArrayOfBytes(request)) {
TResponse response;
response.set_error_message(
base::StrCat({"Failure to call d-bus method: ", method_name}));
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), response));
return;
}
proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&SystemProxyClientImpl::HandleResponse<TResponse>,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
// Parses the response proto message from |response| and calls |callback| with
// the decoded message. Calls |callback| with an |ERROR_DBUS_FAILURE| message
// on error.
template <class TProto>
void HandleResponse(base::OnceCallback<void(const TProto&)> callback,
dbus::Response* response) {
TProto response_proto;
const char* error_message = DeserializeProto(response, &response_proto);
if (error_message) {
response_proto.set_error_message(error_message);
}
std::move(callback).Run(response_proto);
}
// D-Bus proxy for the SystemProxy daemon, not owned.
dbus::ObjectProxy* proxy_ = nullptr;
base::WeakPtrFactory<SystemProxyClientImpl> weak_factory_{this};
};
} // namespace
SystemProxyClient::SystemProxyClient() {
CHECK(!g_instance);
g_instance = this;
}
SystemProxyClient::~SystemProxyClient() {
CHECK_EQ(this, g_instance);
g_instance = nullptr;
}
// static
void SystemProxyClient::Initialize(dbus::Bus* bus) {
CHECK(bus);
(new SystemProxyClientImpl())->Init(bus);
}
// static
void SystemProxyClient::InitializeFake() {
new FakeSystemProxyClient();
}
// static
void SystemProxyClient::Shutdown() {
CHECK(g_instance);
delete g_instance;
}
// static
SystemProxyClient* SystemProxyClient::Get() {
return g_instance;
}
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_DBUS_SYSTEM_PROXY_SYSTEM_PROXY_CLIENT_H_
#define CHROMEOS_DBUS_SYSTEM_PROXY_SYSTEM_PROXY_CLIENT_H_
#include "base/callback.h"
#include "base/component_export.h"
#include "chromeos/dbus/system_proxy/system_proxy_service.pb.h"
#include "dbus/object_proxy.h"
namespace dbus {
class Bus;
}
namespace chromeos {
// SystemProxyClient is used to communicate with the org.chromium.SystemProxy
// service. All method should be called from the origin thread (UI thread) which
// initializes the DBusThreadManager instance.
class COMPONENT_EXPORT(SYSTEM_PROXY) SystemProxyClient {
public:
using SetSystemTrafficCredentialsCallback = base::OnceCallback<void(
const system_proxy::SetSystemTrafficCredentialsResponse& response)>;
using ShutDownDaemonCallback =
base::OnceCallback<void(const system_proxy::ShutDownResponse& response)>;
// Interface with testing functionality. Accessed through GetTestInterface(),
// only implemented in the fake implementation.
class TestInterface {
public:
// Returns how many times |SetSystemTrafficCredentials| was called.
virtual int GetSetSystemTrafficCredentialsCallCount() const = 0;
// Returns how many times |ShutDownDaemon| was called.
virtual int GetShutDownCallCount() const = 0;
protected:
virtual ~TestInterface() {}
};
SystemProxyClient(const SystemProxyClient&) = delete;
SystemProxyClient& operator=(const SystemProxyClient&) = delete;
// Creates and initializes the global instance. |bus| must not be null.
static void Initialize(dbus::Bus* bus);
// Creates and initializes a fake global instance if not already created.
static void InitializeFake();
// Destroys the global instance.
static void Shutdown();
// Returns the global instance which may be null if not initialized.
static SystemProxyClient* Get();
// SystemProxy daemon D-Bus method calls. See org.chromium.SystemProxy.xml and
// system_proxy_service.proto in Chromium OS code for the documentation of the
// methods and request/response messages.
virtual void SetSystemTrafficCredentials(
const system_proxy::SetSystemTrafficCredentialsRequest& request,
SetSystemTrafficCredentialsCallback callback) = 0;
// When receiving a shut-down call, System-proxy will schedule a shut-down
// task and reply. |callback| is called when the daemon starts to shut-down.
virtual void ShutDownDaemon(ShutDownDaemonCallback callback) = 0;
// Returns an interface for testing (fake only), or returns nullptr.
virtual TestInterface* GetTestInterface() = 0;
protected:
// Initialize/Shutdown should be used instead.
SystemProxyClient();
virtual ~SystemProxyClient();
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_SYSTEM_PROXY_SYSTEM_PROXY_CLIENT_H_
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