Commit 45c4ef83 authored by Xiaoling Bao's avatar Xiaoling Bao Committed by Commit Bot

Add policy fetch support.

Bug: 1068797
Change-Id: Iaf56825d95fdb1ba502dfb2d8538f288192e3c28
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2332572
Commit-Queue: Xiaoling Bao <xiaolingbao@chromium.org>
Reviewed-by: default avatarSorin Jianu <sorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#794656}
parent 02b24a76
...@@ -262,6 +262,21 @@ if (is_win || is_mac) { ...@@ -262,6 +262,21 @@ if (is_win || is_mac) {
} }
} }
source_set("updater_tests_support") {
testonly = true
sources = [
"unittest_util.cc",
"unittest_util.h",
]
deps = [
":base",
":lib",
"//base",
]
}
test("updater_tests") { test("updater_tests") {
testonly = true testonly = true
...@@ -277,8 +292,6 @@ if (is_win || is_mac) { ...@@ -277,8 +292,6 @@ if (is_win || is_mac) {
"tag_unittest.cc", "tag_unittest.cc",
"test/integration_tests.cc", "test/integration_tests.cc",
"test/integration_tests.h", "test/integration_tests.h",
"unittest_util.cc",
"unittest_util.h",
"unittest_util_unittest.cc", "unittest_util_unittest.cc",
"updater_unittest.cc", "updater_unittest.cc",
] ]
...@@ -287,6 +300,7 @@ if (is_win || is_mac) { ...@@ -287,6 +300,7 @@ if (is_win || is_mac) {
":base", ":base",
":lib", ":lib",
":updater", ":updater",
":updater_tests_support",
":version_header", ":version_header",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
......
...@@ -69,6 +69,7 @@ source_set("unittest") { ...@@ -69,6 +69,7 @@ source_set("unittest") {
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//chrome/updater:base", "//chrome/updater:base",
"//chrome/updater:updater_tests_support",
"//chrome/updater/protos:omaha_proto", "//chrome/updater/protos:omaha_proto",
"//components/update_client:update_client", "//components/update_client:update_client",
"//net:test_support", "//net:test_support",
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/updater/constants.h" #include "chrome/updater/constants.h"
#include "chrome/updater/device_management/dm_cached_policy_info.h"
#include "chrome/updater/device_management/dm_storage.h" #include "chrome/updater/device_management/dm_storage.h"
#include "chrome/updater/updater_version.h" #include "chrome/updater/updater_version.h"
#include "chrome/updater/util.h" #include "chrome/updater/util.h"
...@@ -46,6 +47,11 @@ constexpr char kAuthorizationHeader[] = "Authorization"; ...@@ -46,6 +47,11 @@ constexpr char kAuthorizationHeader[] = "Authorization";
constexpr char kRegistrationRequestType[] = "register_policy_agent"; constexpr char kRegistrationRequestType[] = "register_policy_agent";
constexpr char kRegistrationTokenType[] = "GoogleEnrollmentToken"; constexpr char kRegistrationTokenType[] = "GoogleEnrollmentToken";
// Constants for policy fetch requests.
constexpr char kPolicyFetchRequestType[] = "policy";
constexpr char kPolicyFetchTokenType[] = "GoogleDMToken";
constexpr char kGoogleUpdateMachineLevelApps[] = "google/machine-level-apps";
constexpr int kHTTPStatusOK = 200; constexpr int kHTTPStatusOK = 200;
constexpr int kHTTPStatusGone = 410; constexpr int kHTTPStatusGone = 410;
...@@ -154,18 +160,19 @@ void DMClient::PostRegisterRequest(DMRequestCallback request_callback) { ...@@ -154,18 +160,19 @@ void DMClient::PostRegisterRequest(DMRequestCallback request_callback) {
policy::GetOSVersion()); policy::GetOSVersion());
// Authorization token is the enrollment token for device registration. // Authorization token is the enrollment token for device registration.
base::flat_map<std::string, std::string> additional_headers; const base::flat_map<std::string, std::string> additional_headers = {
additional_headers.emplace( {kAuthorizationHeader,
kAuthorizationHeader,
base::StringPrintf("%s token=%s", kRegistrationTokenType, base::StringPrintf("%s token=%s", kRegistrationTokenType,
enrollment_token.c_str())); enrollment_token.c_str())},
};
network_fetcher_->PostRequest( network_fetcher_->PostRequest(
BuildURL(kRegistrationRequestType), data, kDMContentType, BuildURL(kRegistrationRequestType), data, kDMContentType,
additional_headers, additional_headers,
base::BindOnce(&DMClient::OnRequestStarted, base::Unretained(this)), base::BindOnce(&DMClient::OnRequestStarted, base::Unretained(this)),
base::BindRepeating(&DMClient::OnRequestProgress, base::Unretained(this)), base::BindRepeating(&DMClient::OnRequestProgress, base::Unretained(this)),
base::BindOnce(&DMClient::OnRequestComplete, base::Unretained(this))); base::BindOnce(&DMClient::OnRegisterRequestComplete,
base::Unretained(this)));
} }
void DMClient::OnRequestStarted(int response_code, int64_t content_length) { void DMClient::OnRequestStarted(int response_code, int64_t content_length) {
...@@ -180,7 +187,8 @@ void DMClient::OnRequestProgress(int64_t current) { ...@@ -180,7 +187,8 @@ void DMClient::OnRequestProgress(int64_t current) {
VLOG(1) << "POST request progess made, current bytes: " << current; VLOG(1) << "POST request progess made, current bytes: " << current;
} }
void DMClient::OnRequestComplete(std::unique_ptr<std::string> response_body, void DMClient::OnRegisterRequestComplete(
std::unique_ptr<std::string> response_body,
int net_error, int net_error,
const std::string& header_etag, const std::string& header_etag,
const std::string& header_x_cup_server_proof, const std::string& header_x_cup_server_proof,
...@@ -206,7 +214,91 @@ void DMClient::OnRequestComplete(std::unique_ptr<std::string> response_body, ...@@ -206,7 +214,91 @@ void DMClient::OnRequestComplete(std::unique_ptr<std::string> response_body,
request_result = RequestResult::kUnexpectedResponse; request_result = RequestResult::kUnexpectedResponse;
} else { } else {
VLOG(1) << "Register request completed, got DM token: " << dm_token; VLOG(1) << "Register request completed, got DM token: " << dm_token;
storage_->StoreDmToken(dm_token); if (!storage_->StoreDmToken(dm_token))
request_result = RequestResult::kSerializationError;
}
}
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(request_callback_), request_result));
}
void DMClient::PostPolicyFetchRequest(DMRequestCallback request_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
RequestResult result = RequestResult::kSuccess;
const std::string dm_token = storage_->GetDmToken();
network_fetcher_ = config_->CreateNetworkFetcher();
request_callback_ = std::move(request_callback);
if (storage_->IsDeviceDeregistered()) {
result = RequestResult::kDeregistered;
} else if (dm_token.empty()) {
result = RequestResult::kNoDMToken;
} else if (storage_->GetDeviceID().empty()) {
result = RequestResult::kNoDeviceID;
} else if (!network_fetcher_) {
result = RequestResult::kFetcherError;
}
if (result != RequestResult::kSuccess) {
LOG(ERROR) << "Policy fetch skipped with DM error: "
<< static_cast<int>(result);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(request_callback_), result));
return;
}
cached_info_ = storage_->GetCachedPolicyInfo();
const std::string data =
GetPolicyFetchRequestData(kGoogleUpdateMachineLevelApps, *cached_info_);
// Authorization token is the DM token for policy fetch
const base::flat_map<std::string, std::string> additional_headers = {
{kAuthorizationHeader,
base::StringPrintf("%s token=%s", kPolicyFetchTokenType,
dm_token.c_str())},
};
network_fetcher_->PostRequest(
BuildURL(kPolicyFetchRequestType), data, kDMContentType,
additional_headers,
base::BindOnce(&DMClient::OnRequestStarted, base::Unretained(this)),
base::BindRepeating(&DMClient::OnRequestProgress, base::Unretained(this)),
base::BindOnce(&DMClient::OnPolicyFetchRequestComplete,
base::Unretained(this)));
}
void DMClient::OnPolicyFetchRequestComplete(
std::unique_ptr<std::string> response_body,
int net_error,
const std::string& header_etag,
const std::string& header_x_cup_server_proof,
int64_t xheader_retry_after_sec) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
RequestResult request_result = RequestResult::kSuccess;
if (net_error != 0) {
LOG(ERROR) << "DM policy fetch failed due to net error: " << net_error;
request_result = RequestResult::kNetworkError;
} else if (http_status_code_ == kHTTPStatusGone) {
VLOG(1) << "Device is now de-registered.";
storage_->DeregisterDevice();
} else if (http_status_code_ != kHTTPStatusOK) {
LOG(ERROR) << "DM policy fetch failed due to http error: "
<< http_status_code_;
request_result = RequestResult::kHttpError;
} else {
DMPolicyMap policies = ParsePolicyFetchResponse(
*response_body, *cached_info_, storage_->GetDmToken(),
storage_->GetDeviceID());
if (policies.empty()) {
request_result = RequestResult::kUnexpectedResponse;
} else {
VLOG(1) << "Policy fetch request completed, got " << policies.size()
<< " new policies.";
if (!storage_->PersistPolicies(policies))
request_result = RequestResult::kSerializationError;
} }
} }
......
...@@ -22,6 +22,7 @@ class NetworkFetcher; ...@@ -22,6 +22,7 @@ class NetworkFetcher;
namespace updater { namespace updater {
class CachedPolicyInfo;
class DMStorage; class DMStorage;
// This class is responsible for everything related to communication with the // This class is responsible for everything related to communication with the
...@@ -63,6 +64,9 @@ class DMClient { ...@@ -63,6 +64,9 @@ class DMClient {
// Request is not sent because the device is de-registered. // Request is not sent because the device is de-registered.
kDeregistered, kDeregistered,
// Policy fetch request is not sent because there's no DM token.
kNoDMToken,
// Request is not sent because network fetcher fails to create. // Request is not sent because network fetcher fails to create.
kFetcherError, kFetcherError,
...@@ -72,6 +76,9 @@ class DMClient { ...@@ -72,6 +76,9 @@ class DMClient {
// Request failed with an HTTP error from server. // Request failed with an HTTP error from server.
kHttpError, kHttpError,
// Failed to persist the response into storage.
kSerializationError,
// Got an unexpected response for the request. // Got an unexpected response for the request.
kUnexpectedResponse, kUnexpectedResponse,
}; };
...@@ -92,6 +99,10 @@ class DMClient { ...@@ -92,6 +99,10 @@ class DMClient {
// token is saved into the storage before |request_callback| is called. // token is saved into the storage before |request_callback| is called.
void PostRegisterRequest(DMRequestCallback request_callback); void PostRegisterRequest(DMRequestCallback request_callback);
// Posts a policy fetch request to the server. Upon success, new polices
// are saved into the storage before |request_callback| is called.
void PostPolicyFetchRequest(DMRequestCallback request_callback);
private: private:
// Gets the full request URL to DM server for the given request type. // Gets the full request URL to DM server for the given request type.
// Additional device specific values, such as device ID, platform etc. will // Additional device specific values, such as device ID, platform etc. will
...@@ -101,7 +112,13 @@ class DMClient { ...@@ -101,7 +112,13 @@ class DMClient {
// Callback functions for the URLFetcher. // Callback functions for the URLFetcher.
void OnRequestStarted(int response_code, int64_t content_length); void OnRequestStarted(int response_code, int64_t content_length);
void OnRequestProgress(int64_t current); void OnRequestProgress(int64_t current);
void OnRequestComplete(std::unique_ptr<std::string> response_body, void OnRegisterRequestComplete(std::unique_ptr<std::string> response_body,
int net_error,
const std::string& header_etag,
const std::string& header_x_cup_server_proof,
int64_t xheader_retry_after_sec);
void OnPolicyFetchRequestComplete(
std::unique_ptr<std::string> response_body,
int net_error, int net_error,
const std::string& header_etag, const std::string& header_etag,
const std::string& header_x_cup_server_proof, const std::string& header_x_cup_server_proof,
...@@ -109,6 +126,7 @@ class DMClient { ...@@ -109,6 +126,7 @@ class DMClient {
std::unique_ptr<Configurator> config_; std::unique_ptr<Configurator> config_;
scoped_refptr<DMStorage> storage_; scoped_refptr<DMStorage> storage_;
std::unique_ptr<CachedPolicyInfo> cached_info_;
std::unique_ptr<update_client::NetworkFetcher> network_fetcher_; std::unique_ptr<update_client::NetworkFetcher> network_fetcher_;
DMRequestCallback request_callback_; DMRequestCallback request_callback_;
......
...@@ -14,7 +14,12 @@ ...@@ -14,7 +14,12 @@
#include "base/test/gmock_callback_support.h" #include "base/test/gmock_callback_support.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/device_management/dm_cached_policy_info.h"
#include "chrome/updater/device_management/dm_policy_builder_for_testing.h"
#include "chrome/updater/device_management/dm_storage.h" #include "chrome/updater/device_management/dm_storage.h"
#include "chrome/updater/policy_manager.h"
#include "chrome/updater/unittest_util.h"
#include "components/policy/proto/device_management_backend.pb.h" #include "components/policy/proto/device_management_backend.pb.h"
#include "components/update_client/network.h" #include "components/update_client/network.h"
#include "net/base/url_util.h" #include "net/base/url_util.h"
...@@ -44,7 +49,7 @@ class TestTokenService : public TokenServiceInterface { ...@@ -44,7 +49,7 @@ class TestTokenService : public TokenServiceInterface {
~TestTokenService() override = default; ~TestTokenService() override = default;
// Overrides for TokenServiceInterface. // Overrides for TokenServiceInterface.
std::string GetDeviceID() const override { return "TestDeviceID"; } std::string GetDeviceID() const override { return "test-device-id"; }
bool StoreEnrollmentToken(const std::string& enrollment_token) override { bool StoreEnrollmentToken(const std::string& enrollment_token) override {
enrollment_token_ = enrollment_token; enrollment_token_ = enrollment_token;
...@@ -91,6 +96,117 @@ TestConfigurator::TestConfigurator(const GURL& url) ...@@ -91,6 +96,117 @@ TestConfigurator::TestConfigurator(const GURL& url)
: network_fetcher_factory_(base::MakeRefCounted<NetworkFetcherFactory>()), : network_fetcher_factory_(base::MakeRefCounted<NetworkFetcherFactory>()),
server_url_(url.spec()) {} server_url_(url.spec()) {}
class DMRequestCallbackHandler
: public base::RefCountedThreadSafe<DMRequestCallbackHandler> {
public:
DMRequestCallbackHandler() = default;
void OnRegisterRequestComplete(DMClient::RequestResult result) {
EXPECT_EQ(result, expected_result_);
if (result == DMClient::RequestResult::kSuccess ||
result == DMClient::RequestResult::kAleadyRegistered) {
EXPECT_EQ(storage_->GetDmToken(), "test-dm-token");
} else {
EXPECT_TRUE(storage_->GetDmToken().empty());
}
PostRequestCompleted();
}
void OnPolicyFetchRequestComplete(DMClient::RequestResult result) {
EXPECT_EQ(result, expected_result_);
if (expected_http_status_ == net::HTTP_GONE)
EXPECT_TRUE(storage_->IsDeviceDeregistered());
if (expected_http_status_ != net::HTTP_OK) {
PostRequestCompleted();
return;
}
std::unique_ptr<CachedPolicyInfo> info = storage_->GetCachedPolicyInfo();
EXPECT_FALSE(info->public_key().empty());
if (expect_new_public_key_)
EXPECT_EQ(info->public_key(), GetTestKey2()->GetPublicKeyString());
else
EXPECT_EQ(info->public_key(), GetTestKey1()->GetPublicKeyString());
if (result == DMClient::RequestResult::kSuccess) {
std::unique_ptr<PolicyManagerInterface> policy_manager =
storage_->GetOmahaPolicyManager();
EXPECT_NE(policy_manager, nullptr);
// Sample some of the policy values and check they are expected.
EXPECT_TRUE(policy_manager->IsManaged());
std::string proxy_mode;
EXPECT_TRUE(policy_manager->GetProxyMode(&proxy_mode));
EXPECT_EQ(proxy_mode, "test_proxy_mode");
int update_policy = 0;
EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppUpdates(
kChromeAppId, &update_policy));
EXPECT_EQ(update_policy, kPolicyAutomaticUpdatesOnly);
std::string target_version_prefix;
EXPECT_TRUE(policy_manager->GetTargetVersionPrefix(
kChromeAppId, &target_version_prefix));
EXPECT_EQ(target_version_prefix, "81.");
}
PostRequestCompleted();
}
void OnDeregisterRequestComplete(DMClient::RequestResult result) {
EXPECT_EQ(result, DMClient::RequestResult::kSuccess);
EXPECT_TRUE(storage_->IsDeviceDeregistered());
PostRequestCompleted();
}
MOCK_METHOD0(PostRequestCompleted, void(void));
void CreateStorage(bool init_dm_token, bool init_cache_info) {
ASSERT_TRUE(storage_dir_.CreateUniqueTempDir());
constexpr char kEnrollmentToken[] = "TestEnrollmentToken";
constexpr char kDmToken[] = "test-dm-token";
storage_ = base::MakeRefCounted<DMStorage>(
storage_dir_.GetPath(),
std::make_unique<TestTokenService>(kEnrollmentToken,
init_dm_token ? kDmToken : ""));
if (init_cache_info) {
std::unique_ptr<::enterprise_management::DeviceManagementResponse>
dm_response = GetDefaultTestingPolicyFetchDMResponse(
/*first_request=*/true, /*rotate_to_new_key=*/false,
DMPolicyBuilderForTesting::SigningOption::kSignNormally);
std::unique_ptr<CachedPolicyInfo> info = storage_->GetCachedPolicyInfo();
DMPolicyMap policies = ParsePolicyFetchResponse(
dm_response->SerializeAsString(), *info.get(), storage_->GetDmToken(),
storage_->GetDeviceID());
ASSERT_FALSE(policies.empty());
ASSERT_TRUE(storage_->PersistPolicies(policies));
}
}
void SetExpectedHttpStatus(net::HttpStatusCode expected_http_status) {
expected_http_status_ = expected_http_status;
}
void SetExpectedRequestResult(DMClient::RequestResult expected_result) {
expected_result_ = expected_result;
}
void SetExpectNewPublicKey(bool expect_new_key) {
expect_new_public_key_ = expect_new_key;
}
scoped_refptr<DMStorage> GetStorage() { return storage_; }
private:
friend class base::RefCountedThreadSafe<DMRequestCallbackHandler>;
~DMRequestCallbackHandler() = default;
base::ScopedTempDir storage_dir_;
scoped_refptr<DMStorage> storage_;
net::HttpStatusCode expected_http_status_ = net::HTTP_OK;
DMClient::RequestResult expected_result_ = DMClient::RequestResult::kSuccess;
bool expect_new_public_key_ = false;
};
} // namespace } // namespace
class DMClientTest : public ::testing::Test { class DMClientTest : public ::testing::Test {
...@@ -112,27 +228,27 @@ class DMClientTest : public ::testing::Test { ...@@ -112,27 +228,27 @@ class DMClientTest : public ::testing::Test {
std::string device_id; std::string device_id;
EXPECT_TRUE( EXPECT_TRUE(
net::GetValueForKeyInQuery(request.GetURL(), "deviceid", &device_id)); net::GetValueForKeyInQuery(request.GetURL(), "deviceid", &device_id));
EXPECT_EQ(device_id, "TestDeviceID"); EXPECT_EQ(device_id, "test-device-id");
EXPECT_EQ(request.headers.at("Content-Type"), "application/x-protobuf"); EXPECT_EQ(request.headers.at("Content-Type"), "application/x-protobuf");
std::string request_type; std::string request_type;
EXPECT_TRUE( EXPECT_TRUE(
net::GetValueForKeyInQuery(request.GetURL(), "request", &request_type)); net::GetValueForKeyInQuery(request.GetURL(), "request", &request_type));
if (request_type == "register_policy_agent") if (request_type == "register_policy_agent") {
return HandleRegisterRequest(request); std::string authorization = request.headers.at("Authorization");
EXPECT_EQ(authorization,
"GoogleEnrollmentToken token=TestEnrollmentToken");
} else if (request_type == "policy") {
std::string authorization = request.headers.at("Authorization");
EXPECT_EQ(authorization, "GoogleDMToken token=test-dm-token");
} else {
auto http_response = auto http_response =
std::make_unique<net::test_server::BasicHttpResponse>(); std::make_unique<net::test_server::BasicHttpResponse>();
http_response->set_code(net::HTTP_BAD_REQUEST); http_response->set_code(net::HTTP_BAD_REQUEST);
return http_response; return http_response;
} }
std::unique_ptr<net::test_server::HttpResponse> HandleRegisterRequest(
const net::test_server::HttpRequest& request) {
std::string authorization = request.headers.at("Authorization");
EXPECT_EQ(authorization, "GoogleEnrollmentToken token=TestEnrollmentToken");
auto http_response = auto http_response =
std::make_unique<net::test_server::BasicHttpResponse>(); std::make_unique<net::test_server::BasicHttpResponse>();
http_response->set_code(response_http_status_); http_response->set_code(response_http_status_);
...@@ -141,33 +257,6 @@ class DMClientTest : public ::testing::Test { ...@@ -141,33 +257,6 @@ class DMClientTest : public ::testing::Test {
return http_response; return http_response;
} }
void OnRegisterRequestComplete(DMClient::RequestResult result) {
EXPECT_EQ(result, expected_result_);
if (result == DMClient::RequestResult::kSuccess ||
result == DMClient::RequestResult::kAleadyRegistered) {
EXPECT_EQ(storage_->GetDmToken(), "TestDMToken");
} else {
EXPECT_TRUE(storage_->GetDmToken().empty());
}
PostRequestCompleted();
}
void OnDeregisterRequestComplete(DMClient::RequestResult result) {
EXPECT_EQ(result, DMClient::RequestResult::kSuccess);
EXPECT_TRUE(storage_->IsDeviceDeregistered());
PostRequestCompleted();
}
MOCK_METHOD0(PostRequestCompleted, void(void));
void CreateStorage(const base::FilePath& root_path, bool initializeDMToken) {
constexpr char kEnrollmentToken[] = "TestEnrollmentToken";
constexpr char kDmToken[] = "TestDMToken";
storage_ = base::MakeRefCounted<DMStorage>(
root_path, std::make_unique<TestTokenService>(
kEnrollmentToken, initializeDMToken ? kDmToken : ""));
}
void StartTestServerWithResponse(net::HttpStatusCode http_status, void StartTestServerWithResponse(net::HttpStatusCode http_status,
const std::string& body) { const std::string& body) {
response_http_status_ = http_status; response_http_status_ = http_status;
...@@ -181,114 +270,307 @@ class DMClientTest : public ::testing::Test { ...@@ -181,114 +270,307 @@ class DMClientTest : public ::testing::Test {
auto dm_response = auto dm_response =
std::make_unique<enterprise_management::DeviceManagementResponse>(); std::make_unique<enterprise_management::DeviceManagementResponse>();
dm_response->mutable_register_response()->set_device_management_token( dm_response->mutable_register_response()->set_device_management_token(
"TestDMToken"); "test-dm-token");
return dm_response->SerializeAsString(); return dm_response->SerializeAsString();
} }
std::unique_ptr<DMClient> CreateDMClient() const { void CreateDMClient() {
const GURL url = test_server_.GetURL("/dm_api"); const GURL url = test_server_.GetURL("/dm_api");
auto test_config = std::make_unique<TestConfigurator>(url); auto test_config = std::make_unique<TestConfigurator>(url);
return std::make_unique<DMClient>(std::move(test_config), storage_); client_ = std::make_unique<DMClient>(std::move(test_config),
} callback_handler_->GetStorage());
void SetExpectedRequestResult(DMClient::RequestResult expected_result) {
expected_result_ = expected_result;
} }
scoped_refptr<DMStorage> storage_;
net::EmbeddedTestServer test_server_; net::EmbeddedTestServer test_server_;
net::HttpStatusCode response_http_status_ = net::HTTP_OK; net::HttpStatusCode response_http_status_ = net::HTTP_OK;
std::string response_body_; std::string response_body_;
DMClient::RequestResult expected_result_ = DMClient::RequestResult::kSuccess; std::unique_ptr<DMClient> client_;
scoped_refptr<DMRequestCallbackHandler> callback_handler_;
base::test::SingleThreadTaskEnvironment task_environment_; base::test::SingleThreadTaskEnvironment task_environment_;
}; };
TEST_F(DMClientTest, PostRegisterRequest_Success) { TEST_F(DMClientTest, PostRegisterRequest_Success) {
base::ScopedTempDir cache_root; callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); callback_handler_->CreateStorage(/*init_dm_token=*/false,
CreateStorage(cache_root.GetPath(), false /* init DM token */); /*init_cache_info=*/false);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kSuccess);
StartTestServerWithResponse(net::HTTP_OK, GetDefaultDeviceRegisterResponse()); StartTestServerWithResponse(net::HTTP_OK, GetDefaultDeviceRegisterResponse());
SetExpectedRequestResult(DMClient::RequestResult::kSuccess);
base::RunLoop run_loop; base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure(); base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*this, PostRequestCompleted()).WillOnce(RunClosure(quit_closure)); EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
std::unique_ptr<DMClient> test_client = CreateDMClient(); CreateDMClient();
test_client->PostRegisterRequest(base::BindOnce( client_->PostRegisterRequest(base::BindOnce(
&DMClientTest::OnRegisterRequestComplete, base::Unretained(this))); &DMRequestCallbackHandler::OnRegisterRequestComplete, callback_handler_));
run_loop.Run(); run_loop.Run();
} }
TEST_F(DMClientTest, PostRegisterRequest_Deregister) { TEST_F(DMClientTest, PostRegisterRequest_Deregister) {
base::ScopedTempDir cache_root; callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); callback_handler_->CreateStorage(/*init_dm_token=*/false,
CreateStorage(cache_root.GetPath(), false /* init DM token */); /*init_cache_info=*/false);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kSuccess);
StartTestServerWithResponse(net::HTTP_GONE, "" /* response body */); StartTestServerWithResponse(net::HTTP_GONE, "" /* response body */);
SetExpectedRequestResult(DMClient::RequestResult::kSuccess);
base::RunLoop run_loop; base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure(); base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*this, PostRequestCompleted()).WillOnce(RunClosure(quit_closure)); EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
std::unique_ptr<DMClient> test_client = CreateDMClient(); CreateDMClient();
test_client->PostRegisterRequest(base::BindOnce( client_->PostRegisterRequest(
&DMClientTest::OnDeregisterRequestComplete, base::Unretained(this))); base::BindOnce(&DMRequestCallbackHandler::OnDeregisterRequestComplete,
callback_handler_));
run_loop.Run(); run_loop.Run();
} }
TEST_F(DMClientTest, PostRegisterRequest_BadRequest) { TEST_F(DMClientTest, PostRegisterRequest_BadRequest) {
base::ScopedTempDir cache_root; callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); callback_handler_->CreateStorage(/*init_dm_token=*/false,
CreateStorage(cache_root.GetPath(), false /* init DM token */); /*init_cache_info=*/false);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kHttpError);
StartTestServerWithResponse(net::HTTP_BAD_REQUEST, "" /* response body */); StartTestServerWithResponse(net::HTTP_BAD_REQUEST, "" /* response body */);
SetExpectedRequestResult(DMClient::RequestResult::kHttpError);
base::RunLoop run_loop; base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure(); base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*this, PostRequestCompleted()).WillOnce(RunClosure(quit_closure)); EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
std::unique_ptr<DMClient> test_client = CreateDMClient(); CreateDMClient();
test_client->PostRegisterRequest(base::BindOnce( client_->PostRegisterRequest(base::BindOnce(
&DMClientTest::OnRegisterRequestComplete, base::Unretained(this))); &DMRequestCallbackHandler::OnRegisterRequestComplete, callback_handler_));
run_loop.Run(); run_loop.Run();
} }
TEST_F(DMClientTest, PostRegisterRequest_AlreadyRegistered) { TEST_F(DMClientTest, PostRegisterRequest_AlreadyRegistered) {
base::ScopedTempDir cache_root; callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); callback_handler_->CreateStorage(/*init_dm_token=*/true,
CreateStorage(cache_root.GetPath(), true /* init DM token */); /*init_cache_info=*/false);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kAleadyRegistered);
StartTestServerWithResponse(net::HTTP_OK, GetDefaultDeviceRegisterResponse()); StartTestServerWithResponse(net::HTTP_OK, GetDefaultDeviceRegisterResponse());
SetExpectedRequestResult(DMClient::RequestResult::kAleadyRegistered);
base::RunLoop run_loop; base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure(); base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*this, PostRequestCompleted()).WillOnce(RunClosure(quit_closure)); EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
std::unique_ptr<DMClient> test_client = CreateDMClient(); CreateDMClient();
test_client->PostRegisterRequest(base::BindOnce( client_->PostRegisterRequest(base::BindOnce(
&DMClientTest::OnRegisterRequestComplete, base::Unretained(this))); &DMRequestCallbackHandler::OnRegisterRequestComplete, callback_handler_));
run_loop.Run(); run_loop.Run();
} }
TEST_F(DMClientTest, PostRegisterRequest_BadResponseData) { TEST_F(DMClientTest, PostRegisterRequest_BadResponseData) {
base::ScopedTempDir cache_root; callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); callback_handler_->CreateStorage(/*init_dm_token=*/false,
CreateStorage(cache_root.GetPath(), false /* init DM token */); /*init_cache_info=*/false);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kUnexpectedResponse);
StartTestServerWithResponse(net::HTTP_OK, "BadResponseData"); StartTestServerWithResponse(net::HTTP_OK, "BadResponseData");
SetExpectedRequestResult(DMClient::RequestResult::kUnexpectedResponse);
base::RunLoop run_loop; base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure(); base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*this, PostRequestCompleted()).WillOnce(RunClosure(quit_closure)); EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostRegisterRequest(base::BindOnce(
&DMRequestCallbackHandler::OnRegisterRequestComplete, callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch_FirstRequest) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/false);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kSuccess);
std::unique_ptr<::enterprise_management::DeviceManagementResponse>
dm_response = GetDefaultTestingPolicyFetchDMResponse(
/*first_request=*/true, /*rotate_to_new_key=*/false,
DMPolicyBuilderForTesting::SigningOption::kSignNormally);
StartTestServerWithResponse(net::HTTP_OK, dm_response->SerializeAsString());
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostPolicyFetchRequest(
base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch_NoRotateKey) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/true);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kSuccess);
std::unique_ptr<::enterprise_management::DeviceManagementResponse>
dm_response = GetDefaultTestingPolicyFetchDMResponse(
/*first_request=*/false, /*rotate_to_new_key=*/false,
DMPolicyBuilderForTesting::SigningOption::kSignNormally);
StartTestServerWithResponse(net::HTTP_OK, dm_response->SerializeAsString());
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostPolicyFetchRequest(
base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch_RotateKey) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/true);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kSuccess);
callback_handler_->SetExpectNewPublicKey(true);
std::unique_ptr<::enterprise_management::DeviceManagementResponse>
dm_response = GetDefaultTestingPolicyFetchDMResponse(
/*first_request=*/false, /*rotate_to_new_key=*/true,
DMPolicyBuilderForTesting::SigningOption::kSignNormally);
StartTestServerWithResponse(net::HTTP_OK, dm_response->SerializeAsString());
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostPolicyFetchRequest(
base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch_RejectKeyWithBadSignature) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/true);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kUnexpectedResponse);
callback_handler_->SetExpectNewPublicKey(false);
std::unique_ptr<::enterprise_management::DeviceManagementResponse>
dm_response = GetDefaultTestingPolicyFetchDMResponse(
/*first_request=*/false, /*rotate_to_new_key=*/true,
DMPolicyBuilderForTesting::SigningOption::kTamperKeySignature);
StartTestServerWithResponse(net::HTTP_OK, dm_response->SerializeAsString());
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostPolicyFetchRequest(
base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch_RejectDataWithBadSignature) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/true);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kUnexpectedResponse);
callback_handler_->SetExpectNewPublicKey(false);
std::unique_ptr<::enterprise_management::DeviceManagementResponse>
dm_response = GetDefaultTestingPolicyFetchDMResponse(
/*first_request=*/false, /*rotate_to_new_key=*/false,
DMPolicyBuilderForTesting::SigningOption::kTamperDataSignature);
StartTestServerWithResponse(net::HTTP_OK, dm_response->SerializeAsString());
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostPolicyFetchRequest(
base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch__Deregister) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/true);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kSuccess);
callback_handler_->SetExpectedHttpStatus(net::HTTP_GONE);
StartTestServerWithResponse(net::HTTP_GONE, "" /* response body */);
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostPolicyFetchRequest(
base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch__BadResponse) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/true);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kUnexpectedResponse);
StartTestServerWithResponse(net::HTTP_OK, "Unexpected response data");
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
CreateDMClient();
client_->PostPolicyFetchRequest(
base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run();
}
TEST_F(DMClientTest, PostPolicyFetch__BadRequest) {
callback_handler_ = base::MakeRefCounted<DMRequestCallbackHandler>();
callback_handler_->CreateStorage(/*init_dm_token=*/true,
/*init_cache_info=*/true);
callback_handler_->SetExpectedRequestResult(
DMClient::RequestResult::kHttpError);
StartTestServerWithResponse(net::HTTP_BAD_REQUEST, "" /* response body */);
base::RunLoop run_loop;
base::RepeatingClosure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(*callback_handler_, PostRequestCompleted())
.WillOnce(RunClosure(quit_closure));
std::unique_ptr<DMClient> test_client = CreateDMClient(); CreateDMClient();
test_client->PostRegisterRequest(base::BindOnce( client_->PostPolicyFetchRequest(
&DMClientTest::OnRegisterRequestComplete, base::Unretained(this))); base::BindOnce(&DMRequestCallbackHandler::OnPolicyFetchRequestComplete,
callback_handler_));
run_loop.Run(); run_loop.Run();
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "chrome/updater/device_management/dm_cached_policy_info.h" #include "chrome/updater/device_management/dm_cached_policy_info.h"
#include "chrome/updater/protos/omaha_settings.pb.h" #include "chrome/updater/protos/omaha_settings.pb.h"
#include "chrome/updater/unittest_util.h"
#include "components/policy/proto/device_management_backend.pb.h" #include "components/policy/proto/device_management_backend.pb.h"
#include "crypto/rsa_private_key.h" #include "crypto/rsa_private_key.h"
#include "crypto/signature_creator.h" #include "crypto/signature_creator.h"
...@@ -136,6 +137,8 @@ const uint8_t kSigningKey2Signature[] = { ...@@ -136,6 +137,8 @@ const uint8_t kSigningKey2Signature[] = {
0xDD, 0x6F, 0x80, 0xC3, 0xDD, 0x6F, 0x80, 0xC3,
}; };
} // namespace
std::unique_ptr<DMSigningKeyForTesting> GetTestKey1() { std::unique_ptr<DMSigningKeyForTesting> GetTestKey1() {
constexpr int kFakeKeyVersion = 5; constexpr int kFakeKeyVersion = 5;
return std::make_unique<DMSigningKeyForTesting>( return std::make_unique<DMSigningKeyForTesting>(
...@@ -150,8 +153,6 @@ std::unique_ptr<DMSigningKeyForTesting> GetTestKey2() { ...@@ -150,8 +153,6 @@ std::unique_ptr<DMSigningKeyForTesting> GetTestKey2() {
sizeof(kSigningKey2Signature), kFakeKeyVersion, "example.com"); sizeof(kSigningKey2Signature), kFakeKeyVersion, "example.com");
} }
} // namespace
std::unique_ptr< std::unique_ptr<
::wireless_android_enterprise_devicemanagement::OmahaSettingsClientProto> ::wireless_android_enterprise_devicemanagement::OmahaSettingsClientProto>
GetDefaultTestingOmahaPolicyProto() { GetDefaultTestingOmahaPolicyProto() {
...@@ -172,7 +173,7 @@ GetDefaultTestingOmahaPolicyProto() { ...@@ -172,7 +173,7 @@ GetDefaultTestingOmahaPolicyProto() {
::wireless_android_enterprise_devicemanagement::MANUAL_UPDATES_ONLY); ::wireless_android_enterprise_devicemanagement::MANUAL_UPDATES_ONLY);
::wireless_android_enterprise_devicemanagement::ApplicationSettings app; ::wireless_android_enterprise_devicemanagement::ApplicationSettings app;
app.set_app_guid("{8A69D345-D564-463C-AFF1-A69D9E530F96}"); app.set_app_guid(kChromeAppId);
app.set_install( app.set_install(
::wireless_android_enterprise_devicemanagement::INSTALL_DISABLED); ::wireless_android_enterprise_devicemanagement::INSTALL_DISABLED);
app.set_update( app.set_update(
......
...@@ -61,6 +61,9 @@ class DMSigningKeyForTesting { ...@@ -61,6 +61,9 @@ class DMSigningKeyForTesting {
std::string key_signature_domain_; std::string key_signature_domain_;
}; };
std::unique_ptr<DMSigningKeyForTesting> GetTestKey1();
std::unique_ptr<DMSigningKeyForTesting> GetTestKey2();
// Builds DM policy response. // Builds DM policy response.
class DMPolicyBuilderForTesting { class DMPolicyBuilderForTesting {
public: public:
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/updater/constants.h" #include "chrome/updater/constants.h"
#include "chrome/updater/unittest_util.h"
#include "components/policy/proto/device_management_backend.pb.h" #include "components/policy/proto/device_management_backend.pb.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -138,19 +139,18 @@ TEST(DMPolicyManager, PolicyManagerFromEmptyProto) { ...@@ -138,19 +139,18 @@ TEST(DMPolicyManager, PolicyManagerFromEmptyProto) {
EXPECT_FALSE(policy_manager->GetPackageCacheExpirationTimeDays(&time_limit)); EXPECT_FALSE(policy_manager->GetPackageCacheExpirationTimeDays(&time_limit));
// Verify app-specific polices. // Verify app-specific polices.
const std::string chrome_guid = "{8A69D345-D564-463C-AFF1-A69D9E530F96}";
int install_policy = -1; int install_policy = -1;
EXPECT_FALSE(policy_manager->GetEffectivePolicyForAppInstalls( EXPECT_FALSE(policy_manager->GetEffectivePolicyForAppInstalls(
chrome_guid, &install_policy)); kChromeAppId, &install_policy));
int update_policy = -1; int update_policy = -1;
EXPECT_FALSE(policy_manager->GetEffectivePolicyForAppUpdates(chrome_guid, EXPECT_FALSE(policy_manager->GetEffectivePolicyForAppUpdates(kChromeAppId,
&update_policy)); &update_policy));
bool rollback_allowed = false; bool rollback_allowed = false;
EXPECT_FALSE(policy_manager->IsRollbackToTargetVersionAllowed( EXPECT_FALSE(policy_manager->IsRollbackToTargetVersionAllowed(
chrome_guid, &rollback_allowed)); kChromeAppId, &rollback_allowed));
std::string target_version_prefix; std::string target_version_prefix;
EXPECT_FALSE(policy_manager->GetTargetVersionPrefix(chrome_guid, EXPECT_FALSE(policy_manager->GetTargetVersionPrefix(kChromeAppId,
&target_version_prefix)); &target_version_prefix));
} }
...@@ -171,7 +171,7 @@ TEST(DMPolicyManager, PolicyManagerFromProto) { ...@@ -171,7 +171,7 @@ TEST(DMPolicyManager, PolicyManagerFromProto) {
::wireless_android_enterprise_devicemanagement::MANUAL_UPDATES_ONLY); ::wireless_android_enterprise_devicemanagement::MANUAL_UPDATES_ONLY);
::wireless_android_enterprise_devicemanagement::ApplicationSettings app; ::wireless_android_enterprise_devicemanagement::ApplicationSettings app;
app.set_app_guid("{8A69D345-D564-463C-AFF1-A69D9E530F96}"); app.set_app_guid(kChromeAppId);
app.set_install( app.set_install(
::wireless_android_enterprise_devicemanagement::INSTALL_DISABLED); ::wireless_android_enterprise_devicemanagement::INSTALL_DISABLED);
app.set_update( app.set_update(
...@@ -223,22 +223,21 @@ TEST(DMPolicyManager, PolicyManagerFromProto) { ...@@ -223,22 +223,21 @@ TEST(DMPolicyManager, PolicyManagerFromProto) {
EXPECT_FALSE(policy_manager->GetPackageCacheExpirationTimeDays(&time_limit)); EXPECT_FALSE(policy_manager->GetPackageCacheExpirationTimeDays(&time_limit));
// Verify app-specific polices. // Verify app-specific polices.
const std::string chrome_guid = "{8A69D345-D564-463C-AFF1-A69D9E530F96}";
int install_policy = -1; int install_policy = -1;
EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppInstalls( EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppInstalls(
chrome_guid, &install_policy)); kChromeAppId, &install_policy));
EXPECT_EQ(install_policy, kPolicyDisabled); EXPECT_EQ(install_policy, kPolicyDisabled);
int update_policy = -1; int update_policy = -1;
EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppUpdates(chrome_guid, EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppUpdates(kChromeAppId,
&update_policy)); &update_policy));
EXPECT_EQ(update_policy, kPolicyAutomaticUpdatesOnly); EXPECT_EQ(update_policy, kPolicyAutomaticUpdatesOnly);
bool rollback_allowed = false; bool rollback_allowed = false;
EXPECT_TRUE(policy_manager->IsRollbackToTargetVersionAllowed( EXPECT_TRUE(policy_manager->IsRollbackToTargetVersionAllowed(
chrome_guid, &rollback_allowed)); kChromeAppId, &rollback_allowed));
EXPECT_TRUE(rollback_allowed); EXPECT_TRUE(rollback_allowed);
std::string target_version_prefix; std::string target_version_prefix;
EXPECT_TRUE(policy_manager->GetTargetVersionPrefix(chrome_guid, EXPECT_TRUE(policy_manager->GetTargetVersionPrefix(kChromeAppId,
&target_version_prefix)); &target_version_prefix));
EXPECT_EQ(target_version_prefix, "81."); EXPECT_EQ(target_version_prefix, "81.");
......
...@@ -95,17 +95,26 @@ bool DMStorage::IsDeviceDeregistered() const { ...@@ -95,17 +95,26 @@ bool DMStorage::IsDeviceDeregistered() const {
return GetDmToken() == kInvalidTokenValue; return GetDmToken() == kInvalidTokenValue;
} }
bool DMStorage::PersistPolicies(const std::string& policy_info_data, bool DMStorage::PersistPolicies(const DMPolicyMap& policy_map) const {
const DMPolicyMap& policy_map) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (policy_map.empty())
// Persists policy cached info return true;
// Each policy in the map should be signed in the same way. If a policy
// in the map contains a public key, normally it means the server rotates the
// key. In this case, we persists the policy into the cached policy info file
// for future policy fetch.
const std::string policy_info_data = policy_map.cbegin()->second;
CachedPolicyInfo cached_info;
if (cached_info.Populate(policy_info_data) &&
!cached_info.public_key().empty()) {
base::FilePath policy_info_file = base::FilePath policy_info_file =
policy_cache_root_.AppendASCII(kPolicyInfoFileName); policy_cache_root_.AppendASCII(kPolicyInfoFileName);
if (!base::ImportantFileWriter::WriteFileAtomically(policy_info_file, if (!base::ImportantFileWriter::WriteFileAtomically(policy_info_file,
policy_info_data)) { policy_info_data)) {
return false; return false;
} }
}
// Persists individual policies. // Persists individual policies.
std::set<std::string> policy_types_base64; std::set<std::string> policy_types_base64;
...@@ -135,18 +144,18 @@ bool DMStorage::PersistPolicies(const std::string& policy_info_data, ...@@ -135,18 +144,18 @@ bool DMStorage::PersistPolicies(const std::string& policy_info_data,
std::unique_ptr<CachedPolicyInfo> DMStorage::GetCachedPolicyInfo() { std::unique_ptr<CachedPolicyInfo> DMStorage::GetCachedPolicyInfo() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto cached_info = std::make_unique<CachedPolicyInfo>();
if (!IsValidDMToken()) if (!IsValidDMToken())
return nullptr; return cached_info;
base::FilePath policy_info_file = base::FilePath policy_info_file =
policy_cache_root_.AppendASCII(kPolicyInfoFileName); policy_cache_root_.AppendASCII(kPolicyInfoFileName);
std::string policy_info_data; std::string policy_info_data;
auto cached_info = std::make_unique<CachedPolicyInfo>();
if (!base::PathExists(policy_info_file) || if (!base::PathExists(policy_info_file) ||
!base::ReadFileToString(policy_info_file, &policy_info_data) || !base::ReadFileToString(policy_info_file, &policy_info_data) ||
!cached_info->Populate(policy_info_data)) { !cached_info->Populate(policy_info_data)) {
return nullptr; return cached_info;
} }
return cached_info; return cached_info;
......
...@@ -88,11 +88,11 @@ class DMStorage : public base::RefCountedThreadSafe<DMStorage> { ...@@ -88,11 +88,11 @@ class DMStorage : public base::RefCountedThreadSafe<DMStorage> {
// Persists DM policies. // Persists DM policies.
// //
// |policy_info_data| is the serialized data of a PolicyFetchResponse. It will // If the first policy in the map contains a valid public key, its serialized
// be saved into a fixed file named "CachedPolicyInfo" in cache root. The // data will be saved into a fixed file named "CachedPolicyInfo" in the cache
// file content will be used to construct an updater::CachedPolicyInfo object // root. The file content will be used to construct an
// to get public key, its version, and signing timestamp. The values will // updater::CachedPolicyInfo object to get public key, its version, and
// be used in subsequent policy fetches. // signing timestamp. The values will be used in subsequent policy fetches.
// //
// Each entry in |policy_map| will be stored within a sub-directory named // Each entry in |policy_map| will be stored within a sub-directory named
// {Base64Encoded{policy_type}}, with a fixed file name of // {Base64Encoded{policy_type}}, with a fixed file name of
...@@ -113,8 +113,7 @@ class DMStorage : public base::RefCountedThreadSafe<DMStorage> { ...@@ -113,8 +113,7 @@ class DMStorage : public base::RefCountedThreadSafe<DMStorage> {
// ('Z29vZ2xlL21hY2hpbmUtbGV2ZWwtb21haGE=' is base64 encoding of // ('Z29vZ2xlL21hY2hpbmUtbGV2ZWwtb21haGE=' is base64 encoding of
// "google/machine-level-omaha"). // "google/machine-level-omaha").
// //
bool PersistPolicies(const std::string& policy_info_data, bool PersistPolicies(const DMPolicyMap& policy_map) const;
const DMPolicyMap& policy_map) const;
// Creates a CachedPolicyInfo object and populates it with the public key // Creates a CachedPolicyInfo object and populates it with the public key
// information loaded from file |policy_cache_root_|\CachedPolicyInfo. // information loaded from file |policy_cache_root_|\CachedPolicyInfo.
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "chrome/updater/device_management/dm_storage.h" #include "chrome/updater/device_management/dm_storage.h"
#include "chrome/updater/policy_manager.h" #include "chrome/updater/policy_manager.h"
#include "chrome/updater/protos/omaha_settings.pb.h" #include "chrome/updater/protos/omaha_settings.pb.h"
#include "chrome/updater/unittest_util.h"
#include "components/policy/proto/device_management_backend.pb.h" #include "components/policy/proto/device_management_backend.pb.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -63,7 +64,7 @@ std::string CannedOmahaPolicyFetchResponse() { ...@@ -63,7 +64,7 @@ std::string CannedOmahaPolicyFetchResponse() {
::wireless_android_enterprise_devicemanagement::MANUAL_UPDATES_ONLY); ::wireless_android_enterprise_devicemanagement::MANUAL_UPDATES_ONLY);
::wireless_android_enterprise_devicemanagement::ApplicationSettings app; ::wireless_android_enterprise_devicemanagement::ApplicationSettings app;
app.set_app_guid("{8A69D345-D564-463C-AFF1-A69D9E530F96}"); app.set_app_guid(kChromeAppId);
app.set_install( app.set_install(
::wireless_android_enterprise_devicemanagement::INSTALL_DISABLED); ::wireless_android_enterprise_devicemanagement::INSTALL_DISABLED);
...@@ -111,13 +112,10 @@ TEST(DMStorage, PersistPolicies) { ...@@ -111,13 +112,10 @@ TEST(DMStorage, PersistPolicies) {
EXPECT_TRUE(base::DirectoryExists(stale_poliy)); EXPECT_TRUE(base::DirectoryExists(stale_poliy));
auto storage = base::MakeRefCounted<DMStorage>(cache_root.GetPath()); auto storage = base::MakeRefCounted<DMStorage>(cache_root.GetPath());
EXPECT_TRUE(storage->PersistPolicies("policy-meta-data", policies)); EXPECT_TRUE(storage->PersistPolicies(policies));
base::FilePath policy_info_file = base::FilePath policy_info_file =
cache_root.GetPath().AppendASCII("CachedPolicyInfo"); cache_root.GetPath().AppendASCII("CachedPolicyInfo");
EXPECT_TRUE(base::PathExists(policy_info_file)); EXPECT_FALSE(base::PathExists(policy_info_file));
std::string policy_info_data;
EXPECT_TRUE(base::ReadFileToString(policy_info_file, &policy_info_data));
EXPECT_EQ(policy_info_data, "policy-meta-data");
base::FilePath omaha_policy_file = base::FilePath omaha_policy_file =
cache_root.GetPath() cache_root.GetPath()
...@@ -164,8 +162,9 @@ TEST(DMStorage, GetCachedPolicyInfo) { ...@@ -164,8 +162,9 @@ TEST(DMStorage, GetCachedPolicyInfo) {
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); ASSERT_TRUE(cache_root.CreateUniqueTempDir());
auto storage = base::MakeRefCounted<DMStorage>( auto storage = base::MakeRefCounted<DMStorage>(
cache_root.GetPath(), std::make_unique<TestTokenService>()); cache_root.GetPath(), std::make_unique<TestTokenService>());
EXPECT_TRUE(storage->PersistPolicies(response.SerializeAsString(), EXPECT_TRUE(storage->PersistPolicies({
/* policies map */ {})); {"sample-policy-type", response.SerializeAsString()},
}));
auto policy_info = storage->GetCachedPolicyInfo(); auto policy_info = storage->GetCachedPolicyInfo();
ASSERT_NE(policy_info, nullptr); ASSERT_NE(policy_info, nullptr);
...@@ -176,17 +175,14 @@ TEST(DMStorage, GetCachedPolicyInfo) { ...@@ -176,17 +175,14 @@ TEST(DMStorage, GetCachedPolicyInfo) {
} }
TEST(DMStorage, ReadCachedOmahaPolicy) { TEST(DMStorage, ReadCachedOmahaPolicy) {
// Persist the default testing omaha policy.
std::string omaha_policy_data = CannedOmahaPolicyFetchResponse();
DMPolicyMap policies({ DMPolicyMap policies({
{"google/machine-level-omaha", omaha_policy_data}, {"google/machine-level-omaha", CannedOmahaPolicyFetchResponse()},
}); });
base::ScopedTempDir cache_root; base::ScopedTempDir cache_root;
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); ASSERT_TRUE(cache_root.CreateUniqueTempDir());
auto storage = base::MakeRefCounted<DMStorage>( auto storage = base::MakeRefCounted<DMStorage>(
cache_root.GetPath(), std::make_unique<TestTokenService>()); cache_root.GetPath(), std::make_unique<TestTokenService>());
EXPECT_TRUE(storage->PersistPolicies(omaha_policy_data, policies)); EXPECT_TRUE(storage->PersistPolicies(policies));
auto policy_manager = storage->GetOmahaPolicyManager(); auto policy_manager = storage->GetOmahaPolicyManager();
ASSERT_NE(policy_manager, nullptr); ASSERT_NE(policy_manager, nullptr);
...@@ -228,22 +224,21 @@ TEST(DMStorage, ReadCachedOmahaPolicy) { ...@@ -228,22 +224,21 @@ TEST(DMStorage, ReadCachedOmahaPolicy) {
EXPECT_FALSE(policy_manager->GetPackageCacheExpirationTimeDays(&cache_life)); EXPECT_FALSE(policy_manager->GetPackageCacheExpirationTimeDays(&cache_life));
// Chrome policies. // Chrome policies.
const std::string chrome_appid = "{8A69D345-D564-463C-AFF1-A69D9E530F96}";
int chrome_install_policy = -1; int chrome_install_policy = -1;
EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppInstalls( EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppInstalls(
chrome_appid, &chrome_install_policy)); kChromeAppId, &chrome_install_policy));
EXPECT_EQ(chrome_install_policy, kPolicyDisabled); EXPECT_EQ(chrome_install_policy, kPolicyDisabled);
int chrome_update_policy = -1; int chrome_update_policy = -1;
EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppUpdates( EXPECT_TRUE(policy_manager->GetEffectivePolicyForAppUpdates(
chrome_appid, &chrome_update_policy)); kChromeAppId, &chrome_update_policy));
EXPECT_EQ(chrome_update_policy, kPolicyAutomaticUpdatesOnly); EXPECT_EQ(chrome_update_policy, kPolicyAutomaticUpdatesOnly);
std::string target_version_prefix; std::string target_version_prefix;
EXPECT_TRUE(policy_manager->GetTargetVersionPrefix(chrome_appid, EXPECT_TRUE(policy_manager->GetTargetVersionPrefix(kChromeAppId,
&target_version_prefix)); &target_version_prefix));
EXPECT_EQ(target_version_prefix, "3.6.55"); EXPECT_EQ(target_version_prefix, "3.6.55");
bool rollback_allowed = false; bool rollback_allowed = false;
EXPECT_TRUE(policy_manager->IsRollbackToTargetVersionAllowed( EXPECT_TRUE(policy_manager->IsRollbackToTargetVersionAllowed(
chrome_appid, &rollback_allowed)); kChromeAppId, &rollback_allowed));
EXPECT_TRUE(rollback_allowed); EXPECT_TRUE(rollback_allowed);
// No app-specific policy should fallback to global. // No app-specific policy should fallback to global.
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include "chrome/updater/tag.h" #include "chrome/updater/tag.h"
namespace updater { namespace updater {
const char kChromeAppId[] = "{8A69D345-D564-463C-AFF1-A69D9E530F96}";
namespace tagging { namespace tagging {
std::ostream& operator<<(std::ostream& os, const ErrorCode& error_code) { std::ostream& operator<<(std::ostream& os, const ErrorCode& error_code) {
......
...@@ -29,6 +29,8 @@ std::ostream& operator<<(std::ostream& os, const base::Optional<T>& opt) { ...@@ -29,6 +29,8 @@ std::ostream& operator<<(std::ostream& os, const base::Optional<T>& opt) {
// Externally-defined printers for chrome/updater-related types. // Externally-defined printers for chrome/updater-related types.
namespace updater { namespace updater {
extern const char kChromeAppId[];
namespace tagging { namespace tagging {
std::ostream& operator<<(std::ostream&, const ErrorCode&); std::ostream& operator<<(std::ostream&, const ErrorCode&);
std::ostream& operator<<(std::ostream&, const AppArgs::NeedsAdmin&); std::ostream& operator<<(std::ostream&, const AppArgs::NeedsAdmin&);
......
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