Commit a9db061a authored by Owen Min's avatar Owen Min Committed by Commit Bot

Add a command line policy loader

It will create an easy workaround for developers when testing policy
on platforms that have need complicated policy management tools.

Bug: 1113792
Change-Id: Ie0431022a3aba1d5356afb32a9987a91d6ba7929
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2353397
Commit-Queue: Owen Min <zmin@chromium.org>
Reviewed-by: default avatarYann Dago <ydago@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797781}
parent 6731c83b
......@@ -47,6 +47,8 @@ em::Policy_PolicySource GetSource(const base::Value& policy) {
switch (static_cast<policy::PolicySource>(*policy.FindIntKey("source"))) {
case policy::POLICY_SOURCE_ENTERPRISE_DEFAULT:
return em::Policy_PolicySource_SOURCE_ENTERPRISE_DEFAULT;
case policy::POLICY_SOURCE_COMMAND_LINE:
return em::Policy_PolicySource_SOURCE_COMMAND_LINE;
case policy::POLICY_SOURCE_CLOUD:
return em::Policy_PolicySource_SOURCE_CLOUD;
case policy::POLICY_SOURCE_ACTIVE_DIRECTORY:
......
......@@ -18,6 +18,7 @@ namespace policy {
const webui::LocalizedString kPolicySources[POLICY_SOURCE_COUNT] = {
{"sourceEnterpriseDefault", IDS_POLICY_SOURCE_ENTERPRISE_DEFAULT},
{"commandLine", IDS_POLICY_SOURCE_COMMAND_LINE},
{"cloud", IDS_POLICY_SOURCE_CLOUD},
{"sourceActiveDirectory", IDS_POLICY_SOURCE_ACTIVE_DIRECTORY},
{"sourceDeviceLocalAccountOverride",
......
......@@ -116,6 +116,8 @@ source_set("internal") {
"policy_details.h",
"policy_load_status.cc",
"policy_load_status.h",
"policy_loader_command_line.cc",
"policy_loader_command_line.h",
"policy_loader_common.cc",
"policy_loader_common.h",
"policy_map.cc",
......@@ -402,6 +404,7 @@ source_set("unit_tests") {
"management/management_service_unittest.cc",
"plist_writer_unittest.cc",
"policy_bundle_unittest.cc",
"policy_loader_command_line_unittest.cc",
"policy_map_unittest.cc",
"policy_service_impl_unittest.cc",
"policy_statistics_collector_unittest.cc",
......
// 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 "components/policy/core/common/policy_loader_command_line.h"
#include "base/json/json_reader.h"
#include "base/sequenced_task_runner.h"
#include "base/values.h"
#include "components/policy/core/common/policy_bundle.h"
#include "components/policy/core/common/policy_switches.h"
#include "components/policy/core/common/policy_types.h"
namespace policy {
PolicyLoaderCommandLine::PolicyLoaderCommandLine(
scoped_refptr<base::SequencedTaskRunner> task_runner,
const base::CommandLine& command_line)
: AsyncPolicyLoader(task_runner), command_line_(command_line) {}
PolicyLoaderCommandLine::~PolicyLoaderCommandLine() = default;
void PolicyLoaderCommandLine::InitOnBackgroundThread() {}
std::unique_ptr<PolicyBundle> PolicyLoaderCommandLine::Load() {
std::unique_ptr<PolicyBundle> bundle = std::make_unique<PolicyBundle>();
if (!command_line_.HasSwitch(switches::kChromePolicy))
return bundle;
base::Optional<base::Value> policies = base::JSONReader::Read(
command_line_.GetSwitchValueASCII(switches::kChromePolicy));
if (!policies || !policies->is_dict())
return bundle;
bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
.LoadFrom(&base::Value::AsDictionaryValue(*policies),
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_COMMAND_LINE);
return bundle;
}
} // 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.
#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_LOADER_COMMAND_LINE_H_
#define COMPONENTS_POLICY_CORE_COMMON_POLICY_LOADER_COMMAND_LINE_H_
#include "base/command_line.h"
#include "base/memory/ref_counted.h"
#include "components/policy/core/common/async_policy_loader.h"
#include "components/policy/policy_export.h"
namespace base {
class SequencedTaskRunner;
}
namespace policy {
// Loads policy value from command line switch for development and testing
// purposes. It can be only used with strict limitation. For example, on
// Android, the device must be rooted.
class POLICY_EXPORT PolicyLoaderCommandLine : public AsyncPolicyLoader {
public:
PolicyLoaderCommandLine(scoped_refptr<base::SequencedTaskRunner> task_runner,
const base::CommandLine& command_line);
PolicyLoaderCommandLine(const PolicyLoaderCommandLine&) = delete;
PolicyLoaderCommandLine& operator=(const PolicyLoaderCommandLine&) = delete;
~PolicyLoaderCommandLine() override;
// AsumcPolicyLoader implementation.
void InitOnBackgroundThread() override;
std::unique_ptr<PolicyBundle> Load() override;
private:
const base::CommandLine command_line_;
};
} // namespace policy
#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_LOADER_COMMAND_LINE_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 "components/policy/core/common/policy_loader_command_line.h"
#include "base/sequenced_task_runner.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "components/policy/core/common/policy_bundle.h"
#include "components/policy/core/common/policy_switches.h"
#include "components/policy/core/common/policy_types.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
class PolicyLoaderCommandLineTest : public ::testing::Test {
public:
void SetCommandLinePolicy(const std::string& policies) {
command_line_.AppendSwitchASCII(switches::kChromePolicy, policies);
}
void LoadAndVerifyPolicies(PolicyLoaderCommandLine* loader,
const base::Value& expected_policies) {
DCHECK(expected_policies.is_dict());
std::unique_ptr<PolicyBundle> bundle = loader->Load();
PolicyMap& map =
bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
EXPECT_EQ(expected_policies.DictSize(), map.size());
for (const auto& expected_policy : expected_policies.DictItems()) {
const PolicyMap::Entry* actual_policy = map.Get(expected_policy.first);
ASSERT_TRUE(actual_policy);
EXPECT_EQ(POLICY_LEVEL_MANDATORY, actual_policy->level);
EXPECT_EQ(POLICY_SCOPE_MACHINE, actual_policy->scope);
EXPECT_EQ(POLICY_SOURCE_COMMAND_LINE, actual_policy->source);
ASSERT_TRUE(actual_policy->value());
EXPECT_EQ(expected_policy.second, *(actual_policy->value()));
}
}
std::unique_ptr<PolicyLoaderCommandLine> CreatePolicyLoader() {
return std::make_unique<PolicyLoaderCommandLine>(
task_environment_.GetMainThreadTaskRunner(), command_line_);
}
private:
base::CommandLine command_line_{base::CommandLine::NO_PROGRAM};
base::test::TaskEnvironment task_environment_;
};
TEST_F(PolicyLoaderCommandLineTest, NoSwitch) {
LoadAndVerifyPolicies(CreatePolicyLoader().get(),
base::Value(base::Value::Type::DICTIONARY));
}
TEST_F(PolicyLoaderCommandLineTest, InvalidSwitch) {
SetCommandLinePolicy("a");
LoadAndVerifyPolicies(CreatePolicyLoader().get(),
base::Value(base::Value::Type::DICTIONARY));
SetCommandLinePolicy("a:b");
LoadAndVerifyPolicies(CreatePolicyLoader().get(),
base::Value(base::Value::Type::DICTIONARY));
SetCommandLinePolicy("[a]");
LoadAndVerifyPolicies(CreatePolicyLoader().get(),
base::Value(base::Value::Type::DICTIONARY));
}
TEST_F(PolicyLoaderCommandLineTest, ParseSwitchValue) {
SetCommandLinePolicy(R"({
"int_policy": 42,
"string_policy": "string",
"bool_policy": true,
"list_policy": [1,2],
"dict_policy": {"k1":1, "k2": {"k3":true}}
})");
base::Value policies(base::Value::Type::DICTIONARY);
policies.SetIntKey("int_policy", 42);
policies.SetStringKey("string_policy", "string");
policies.SetBoolKey("bool_policy", true);
// list policy
base::Value::ListStorage list_storage;
list_storage.emplace_back(1);
list_storage.emplace_back(2);
policies.SetKey("list_policy", base::Value(list_storage));
// dict policy
policies.SetIntPath({"dict_policy.k1"}, 1);
policies.SetBoolPath({"dict_policy.k2.k3"}, true);
LoadAndVerifyPolicies(CreatePolicyLoader().get(), policies);
}
} // namespace policy
......@@ -21,5 +21,8 @@ const char kRealtimeReportingUrl[] = "realtime-reporting-url";
// TODO(antrim): Remove once test servers correctly produce affiliation ids.
const char kUserAlwaysAffiliated[] = "user-always-affiliated";
// Set policy value by command line.
const char kChromePolicy[] = "policy";
} // namespace switches
} // namespace policy
......@@ -16,6 +16,7 @@ POLICY_EXPORT extern const char kDeviceManagementUrl[];
POLICY_EXPORT extern const char kDisableComponentCloudPolicy[];
POLICY_EXPORT extern const char kRealtimeReportingUrl[];
POLICY_EXPORT extern const char kUserAlwaysAffiliated[];
POLICY_EXPORT extern const char kChromePolicy[];
} // namespace switches
} // namespace policy
......
......@@ -36,6 +36,9 @@ enum PolicySource {
// The policy was set because we are running in an enterprise environment.
POLICY_SOURCE_ENTERPRISE_DEFAULT,
// The policy was set by command line flag for testing purpose.
POLICY_SOURCE_COMMAND_LINE,
// The policy was set by a cloud source.
POLICY_SOURCE_CLOUD,
......
......@@ -1757,6 +1757,9 @@ message Policy {
// A policy is set by multiple sources and value has been merged.
SOURCE_MERGED = 7;
// A policy is set by command line switch for testing purpose.
SOURCE_COMMAND_LINE = 8;
}
optional PolicySource source = 4;
......
......@@ -441,6 +441,9 @@ Additional details:
<message name="IDS_POLICY_SOURCE_ENTERPRISE_DEFAULT" desc="Indicates that a policy is set by default in an enterprise environment and can be overridden (for Chrome OS only).">
Enterprise default
</message>
<message name="IDS_POLICY_SOURCE_COMMAND_LINE" desc="Indicates that a policy is set by command line switch for testing purpose.">
Command line
</message>
<message name="IDS_POLICY_SOURCE_CLOUD" desc="Indicates that the policy originates from the cloud.">
Cloud
</message>
......
79b7b3e68d4a22c58db43965d542aebd04d83c12
\ No newline at end of file
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