Index: chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc |
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc |
index 1d3f181105534a696b7bb272fa34f7ab0f87d5aa..6fdf303ce10d48c28822945ae401df7808b9d952 100644 |
--- a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc |
+++ b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc |
@@ -5,15 +5,20 @@ |
#include <cryptohi.h> |
#include "base/macros.h" |
+#include "base/memory/scoped_ptr.h" |
#include "base/strings/stringprintf.h" |
+#include "base/json/json_writer.h" |
#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" |
#include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" |
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" |
#include "chrome/browser/extensions/extension_apitest.h" |
#include "chrome/browser/net/nss_context.h" |
+#include "chrome/browser/policy/profile_policy_connector.h" |
+#include "chrome/browser/policy/profile_policy_connector_factory.h" |
+#include "chrome/browser/profiles/profile.h" |
#include "chromeos/chromeos_switches.h" |
#include "chromeos/login/user_names.h" |
-#include "components/policy/core/browser/browser_policy_connector.h" |
+#include "components/policy/core/common/mock_configuration_policy_provider.h" |
#include "components/policy/core/common/policy_map.h" |
#include "content/public/browser/notification_service.h" |
#include "content/public/common/content_switches.h" |
@@ -27,51 +32,91 @@ |
#include "net/cert/nss_cert_database.h" |
#include "net/cert/test_root_certs.h" |
#include "net/test/cert_test_util.h" |
-#include "net/test/url_request/url_request_mock_http_job.h" |
#include "policy/policy_constants.h" |
#include "testing/gmock/include/gmock/gmock.h" |
+#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" |
+#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" |
+#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" |
+#include "components/policy/core/common/cloud/cloud_policy_manager.h" |
+#include "components/policy/core/common/cloud/cloud_policy_core.h" |
+#include "components/policy/core/common/cloud/cloud_policy_store.h" |
+#include "chrome/browser/chromeos/profiles/profile_helper.h" |
+#include "chrome/browser/chromeos/policy/login_policy_test_base.h" |
+ |
namespace { |
enum DeviceStatus { DEVICE_STATUS_ENROLLED, DEVICE_STATUS_NOT_ENROLLED }; |
-enum UserAffiliation { |
- USER_AFFILIATION_ENROLLED_DOMAIN, |
- USER_AFFILIATION_UNRELATED |
+enum UserStatus { |
+ USER_STATUS_MANAGED_AFFILIATED_DOMAIN, |
+ USER_STATUS_MANAGED_OTHER_DOMAIN, |
+ USER_STATUS_UNMANAGED |
}; |
-struct Params { |
- Params(DeviceStatus device_status, UserAffiliation user_affiliation) |
- : device_status_(device_status), user_affiliation_(user_affiliation) {} |
+class PlatformKeysTest : public ExtensionApiTest { |
+ public: |
+ PlatformKeysTest(DeviceStatus device_status, |
+ UserStatus user_status, |
+ bool key_permission_policy) |
+ : device_status_(device_status), |
+ user_status_(user_status), |
+ key_permission_policy_(key_permission_policy) { |
+ if (user_status_ != USER_STATUS_UNMANAGED) { |
+ SetupInitialEmptyPolicy(); |
+ } |
+ } |
- DeviceStatus device_status_; |
- UserAffiliation user_affiliation_; |
-}; |
+ void SetupInitialEmptyPolicy() { |
+ policy_helper_.reset(new policy::PolicyTestHelper( |
+ chromeos::login::kStubUser, |
+ base::DictionaryValue() /* empty mandatory policy */, |
+ base::DictionaryValue() /* empty recommended policy */)); |
+ } |
-class PlatformKeysTest : public ExtensionApiTest, |
- public ::testing::WithParamInterface<Params> { |
- public: |
- PlatformKeysTest() {} |
+ void SetupKeyPermissionPolicy() { |
+ // Set up the test policy that gives |extension_| the permission to access |
+ // corporate keys. |
+ base::DictionaryValue key_permissions_policy; |
+ { |
+ scoped_ptr<base::DictionaryValue> cert1_key_permission( |
+ new base::DictionaryValue); |
+ cert1_key_permission->SetBooleanWithoutPathExpansion( |
+ "allowCorporateKeyUsage", true); |
+ key_permissions_policy.SetWithoutPathExpansion( |
+ extension_->id(), cert1_key_permission.release()); |
+ } |
+ |
+ std::string key_permissions_policy_str; |
+ base::JSONWriter::Write(key_permissions_policy, &key_permissions_policy_str); |
+ |
+ base::DictionaryValue user_policy; |
+ user_policy.SetStringWithoutPathExpansion(policy::key::kKeyPermissions, |
+ key_permissions_policy_str); |
+ |
+ policy_helper_->UpdatePolicy( |
+ browser()->profile(), user_policy, |
+ base::DictionaryValue() /* empty recommended policy */); |
+ } |
void SetUpCommandLine(base::CommandLine* command_line) override { |
ExtensionApiTest::SetUpCommandLine(command_line); |
- std::string user_email = "someuser@anydomain.com"; |
- |
- // The command line flag kLoginUser determines the user's email and thus |
- // his affiliation to the domain that the device is enrolled to. |
- if (GetParam().user_affiliation_ == USER_AFFILIATION_ENROLLED_DOMAIN) |
- user_email = chromeos::login::kStubUser; |
+ if (policy_helper_) |
+ policy_helper_->UpdateCommandLine(command_line); |
- command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, user_email); |
+ command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, |
+ chromeos::login::kStubUser); |
} |
void SetUpInProcessBrowserTestFixture() override { |
ExtensionApiTest::SetUpInProcessBrowserTestFixture(); |
- if (GetParam().device_status_ == DEVICE_STATUS_ENROLLED) { |
+ if (device_status_ == DEVICE_STATUS_ENROLLED) { |
device_policy_test_helper_.device_policy()->policy_data().set_username( |
- chromeos::login::kStubUser); |
+ user_status_ == USER_STATUS_MANAGED_AFFILIATED_DOMAIN |
+ ? chromeos::login::kStubUser |
+ : "someuser@anydomain.com"); |
device_policy_test_helper_.device_policy()->Build(); |
device_policy_test_helper_.MarkAsEnterpriseOwned(); |
@@ -79,6 +124,9 @@ class PlatformKeysTest : public ExtensionApiTest, |
} |
void SetUpOnMainThread() override { |
+ if (policy_helper_) |
+ policy_helper_->WaitForInitialPolicy(browser()->profile()); |
+ |
{ |
base::RunLoop loop; |
content::BrowserThread::PostTask( |
@@ -103,6 +151,9 @@ class PlatformKeysTest : public ExtensionApiTest, |
base::FilePath extension_path = test_data_dir_.AppendASCII("platform_keys"); |
extension_ = LoadExtension(extension_path); |
+ |
+ if (key_permission_policy_) |
+ SetupKeyPermissionPolicy(); |
} |
void TearDownOnMainThread() override { |
@@ -127,23 +178,58 @@ class PlatformKeysTest : public ExtensionApiTest, |
// Only if the current user is of the same domain as the device is enrolled |
// to, the system token is available to the extension. |
- if (GetParam().device_status_ == DEVICE_STATUS_ENROLLED && |
- GetParam().user_affiliation_ == USER_AFFILIATION_ENROLLED_DOMAIN) { |
+ if (device_status_ == DEVICE_STATUS_ENROLLED && |
+ user_status_ == USER_STATUS_MANAGED_AFFILIATED_DOMAIN) { |
system_token_availability = "systemTokenEnabled"; |
} |
GURL url = extension_->GetResourceURL(base::StringPrintf( |
"basic.html?%s#%s", system_token_availability.c_str(), |
test_suite_name.c_str())); |
- return RunExtensionSubtest("platform_keys", url.spec()); |
+ return RunExtensionSubtest("", url.spec()); |
+ } |
+ |
+ void RegisterClient1AsCorporateKey() { |
+ const extensions::Extension* const fake_gen_extension = |
+ LoadExtension(test_data_dir_.AppendASCII("platform_keys_genkey")); |
+ |
+ policy::ProfilePolicyConnector* const policy_connector = |
+ policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile()); |
+ |
+ extensions::StateStore* const state_store = |
+ extensions::ExtensionSystem::Get(profile())->state_store(); |
+ |
+ chromeos::KeyPermissions permissions(profile()->GetPrefs(), true, |
+ policy_connector->policy_service(), |
+ state_store); |
+ |
+ base::RunLoop run_loop; |
+ permissions.GetPermissionsForExtension( |
+ fake_gen_extension->id(), |
+ base::Bind(&PlatformKeysTest::GotPermissionsForExtension, |
+ base::Unretained(this), run_loop.QuitClosure())); |
+ run_loop.Run(); |
} |
protected: |
+ const DeviceStatus device_status_; |
+ const UserStatus user_status_; |
+ |
scoped_refptr<net::X509Certificate> client_cert1_; |
scoped_refptr<net::X509Certificate> client_cert2_; |
const extensions::Extension* extension_; |
private: |
+ void GotPermissionsForExtension( |
+ const base::Closure& done_callback, |
+ scoped_ptr<chromeos::KeyPermissions::PermissionsForExtension> |
+ permissions_for_ext) { |
+ std::string client_cert1_spki = |
+ chromeos::platform_keys::GetSubjectPublicKeyInfo(client_cert1_); |
+ permissions_for_ext->RegisterKeyForCorporateUsage(client_cert1_spki ); |
+ done_callback.Run(); |
+ } |
+ |
void SetupTestCerts(const base::Closure& done_callback, |
net::NSSCertDatabase* cert_db) { |
SetupTestClientCerts(cert_db); |
@@ -192,6 +278,8 @@ class PlatformKeysTest : public ExtensionApiTest, |
done_callback); |
} |
+ const bool key_permission_policy_; |
+ scoped_ptr<policy::PolicyTestHelper> policy_helper_; |
policy::DevicePolicyCrosTestHelper device_policy_test_helper_; |
scoped_ptr<crypto::ScopedTestSystemNSSKeySlot> test_system_slot_; |
}; |
@@ -199,11 +287,12 @@ class PlatformKeysTest : public ExtensionApiTest, |
class TestSelectDelegate |
: public chromeos::PlatformKeysService::SelectDelegate { |
public: |
- // On each Select call, selects the next entry in |cert_to_select| from back |
+ // On each Select call, selects the next entry in |certs_to_select| from back |
// to front. Once the first entry is reached, that one will be selected |
// repeatedly. |
// Entries of |certs_to_select| can be null in which case no certificate will |
// be selected. |
+ // If |certs_to_select| is empty, any invocation of |Select| will fail. |
explicit TestSelectDelegate(net::CertificateList certs_to_select) |
: certs_to_select_(certs_to_select) {} |
@@ -235,13 +324,51 @@ class TestSelectDelegate |
net::CertificateList certs_to_select_; |
}; |
+class UnmanagedPlatformKeysTest |
+ : public PlatformKeysTest, |
+ public ::testing::WithParamInterface<DeviceStatus> { |
+ public: |
+ UnmanagedPlatformKeysTest() |
+ : PlatformKeysTest(GetParam(), |
+ USER_STATUS_UNMANAGED, |
+ false /* unused */) {} |
+}; |
+ |
+struct Params { |
+ Params(DeviceStatus device_status, UserStatus user_status) |
+ : device_status_(device_status), user_status_(user_status) {} |
+ |
+ DeviceStatus device_status_; |
+ UserStatus user_status_; |
+}; |
+ |
+class ManagedWithPermissionPlatformKeysTest |
+ : public PlatformKeysTest, |
+ public ::testing::WithParamInterface<Params> { |
+ public: |
+ ManagedWithPermissionPlatformKeysTest() |
+ : PlatformKeysTest(GetParam().device_status_, |
+ GetParam().user_status_, |
+ true /* grant the extension key permission */) {} |
+}; |
+ |
+class ManagedWithoutPermissionPlatformKeysTest |
+ : public PlatformKeysTest, |
+ public ::testing::WithParamInterface<Params> { |
+ public: |
+ ManagedWithoutPermissionPlatformKeysTest() |
+ : PlatformKeysTest(GetParam().device_status_, |
+ GetParam().user_status_, |
+ false /* do not grant key permission */) {} |
+}; |
+ |
} // namespace |
// At first interactively selects |client_cert1_| and |client_cert2_| to grant |
// permissions and afterwards runs more basic tests. |
// After the initial two interactive calls, the simulated user does not select |
// any cert. |
-IN_PROC_BROWSER_TEST_P(PlatformKeysTest, Basic) { |
+IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, Basic) { |
net::CertificateList certs; |
certs.push_back(nullptr); |
certs.push_back(client_cert2_); |
@@ -255,7 +382,7 @@ IN_PROC_BROWSER_TEST_P(PlatformKeysTest, Basic) { |
// On interactive calls, the simulated user always selects |client_cert1_| if |
// matching. |
-IN_PROC_BROWSER_TEST_P(PlatformKeysTest, Permissions) { |
+IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, Permissions) { |
net::CertificateList certs; |
certs.push_back(client_cert1_); |
@@ -265,10 +392,74 @@ IN_PROC_BROWSER_TEST_P(PlatformKeysTest, Permissions) { |
ASSERT_TRUE(RunExtensionTest("permissionTests")) << message_; |
} |
+INSTANTIATE_TEST_CASE_P(Unmanaged, |
+ UnmanagedPlatformKeysTest, |
+ ::testing::Values(DEVICE_STATUS_ENROLLED, |
+ DEVICE_STATUS_NOT_ENROLLED)); |
+ |
+IN_PROC_BROWSER_TEST_P(ManagedWithoutPermissionPlatformKeysTest, |
+ UserPermissionsBlocked) { |
+ // To verify that the user is not prompted for any certificate selection, |
+ // set up a delegate that fails on any invocation. |
+ GetPlatformKeysService()->SetSelectDelegate( |
+ make_scoped_ptr(new TestSelectDelegate(net::CertificateList()))); |
+ |
+ ASSERT_TRUE(RunExtensionTest("managedProfile")) << message_; |
+} |
+ |
+// A corporate key must not be useable if there is no policy permitting it. |
+IN_PROC_BROWSER_TEST_P(ManagedWithoutPermissionPlatformKeysTest, |
+ CorporateKeyAccessBlocked) { |
+ RegisterClient1AsCorporateKey(); |
+ |
+ // To verify that the user is not prompted for any certificate selection, |
+ // set up a delegate that fails on any invocation. |
+ GetPlatformKeysService()->SetSelectDelegate( |
+ make_scoped_ptr(new TestSelectDelegate(net::CertificateList()))); |
+ |
+ ASSERT_TRUE(RunExtensionTest("corporateKeyWithoutPermissionTests")) |
+ << message_; |
+} |
+ |
+INSTANTIATE_TEST_CASE_P( |
+ ManagedWithoutPermission, |
+ ManagedWithoutPermissionPlatformKeysTest, |
+ ::testing::Values( |
+ Params(DEVICE_STATUS_ENROLLED, USER_STATUS_MANAGED_AFFILIATED_DOMAIN), |
+ Params(DEVICE_STATUS_ENROLLED, USER_STATUS_MANAGED_OTHER_DOMAIN), |
+ Params(DEVICE_STATUS_NOT_ENROLLED, USER_STATUS_MANAGED_OTHER_DOMAIN))); |
+ |
+IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest, |
+ PolicyGrantsAccessToCorporateKey) { |
+ RegisterClient1AsCorporateKey(); |
+ |
+ // Set up the test SelectDelegate to select |client_cert1_| if available for |
+ // selection. |
+ net::CertificateList certs; |
+ certs.push_back(client_cert1_); |
+ |
+ GetPlatformKeysService()->SetSelectDelegate( |
+ make_scoped_ptr(new TestSelectDelegate(certs))); |
+ |
+ ASSERT_TRUE(RunExtensionTest("corporateKeyWithPermissionTests")) << message_; |
+} |
+ |
+IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest, |
+ PolicyDoesGrantAccessToNonCorporateKey) { |
+ |
+ // As the profile is managed, the user must not be able to grant any |
+ // certificate permission. Set up a delegate that fails on any invocation. |
+ GetPlatformKeysService()->SetSelectDelegate( |
+ make_scoped_ptr(new TestSelectDelegate(net::CertificateList()))); |
+ |
+ ASSERT_TRUE(RunExtensionTest("untaggedKeyWithUnrelatedPermissionTests")) |
+ << message_; |
+} |
+ |
INSTANTIATE_TEST_CASE_P( |
- CheckSystemTokenAvailability, |
- PlatformKeysTest, |
+ ManagedWithPermission, |
+ ManagedWithPermissionPlatformKeysTest, |
::testing::Values( |
- Params(DEVICE_STATUS_ENROLLED, USER_AFFILIATION_ENROLLED_DOMAIN), |
- Params(DEVICE_STATUS_ENROLLED, USER_AFFILIATION_UNRELATED), |
- Params(DEVICE_STATUS_NOT_ENROLLED, USER_AFFILIATION_UNRELATED))); |
+ Params(DEVICE_STATUS_ENROLLED, USER_STATUS_MANAGED_AFFILIATED_DOMAIN), |
+ Params(DEVICE_STATUS_ENROLLED, USER_STATUS_MANAGED_OTHER_DOMAIN), |
+ Params(DEVICE_STATUS_NOT_ENROLLED, USER_STATUS_MANAGED_OTHER_DOMAIN))); |