// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cryptohi.h>
#include <pk11pub.h>
#include <memory>
#include <string>
#include <utility>
#include "ash/constants/ash_features.h"
#include "base/functional/bind.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/gtest_tags.h"
#include "chrome/browser/ash/platform_keys/key_permissions/key_permissions_service.h"
#include "chrome/browser/ash/platform_keys/key_permissions/key_permissions_service_factory.h"
#include "chrome/browser/chromeos/platform_keys/extension_key_permissions_service.h"
#include "chrome/browser/chromeos/platform_keys/extension_key_permissions_service_factory.h"
#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h"
#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
#include "chrome/browser/extensions/api/platform_keys/platform_keys_test_base.h"
#include "chrome/browser/net/nss_service.h"
#include "chrome/browser/net/nss_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "components/policy/policy_constants.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test.h"
#include "crypto/nss_util_internal.h"
#include "crypto/scoped_nss_types.h"
#include "crypto/scoped_test_nss_db.h"
#include "crypto/scoped_test_system_nss_key_slot.h"
#include "net/cert/cert_database.h"
#include "net/cert/nss_cert_database.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"
#include "net/test/cert_test_util.h"
namespace {
constexpr char kExtensionId[] = "knldjmfmopnpolahpmmgbagdohdnhkik";
using ContextType = extensions::ExtensionBrowserTest::ContextType;
class PlatformKeysTest : public PlatformKeysTestBase {
public:
enum class UserClientCertSlot { kPrivateSlot, kPublicSlot };
PlatformKeysTest(EnrollmentStatus enrollment_status,
UserStatus user_status,
bool key_permission_policy,
UserClientCertSlot user_client_cert_slot,
ContextType context_type)
: PlatformKeysTestBase(SystemTokenStatus::EXISTS,
enrollment_status,
user_status),
key_permission_policy_(key_permission_policy),
user_client_cert_slot_(user_client_cert_slot),
context_type_(context_type) {
// Most tests require this to be true. Those that don't can reset
// it to false if necessary. This is always reset in the destructor.
extensions::PlatformKeysInternalSelectClientCertificatesFunction::
SetSkipInteractiveCheckForTest(true);
}
~PlatformKeysTest() override {
extensions::PlatformKeysInternalSelectClientCertificatesFunction::
SetSkipInteractiveCheckForTest(false);
}
PlatformKeysTest(const PlatformKeysTest&) = delete;
PlatformKeysTest& operator=(const PlatformKeysTest&) = delete;
void SetUpOnMainThread() override {
if (ash::features::IsCopyClientKeysCertsToChapsEnabled() &&
(user_client_cert_slot_ == UserClientCertSlot::kPublicSlot)) {
// There's an active effort to deprecate the public slot. Some components
// (e.g. Kcer) don't take it into account, which breaks tests, but they
// also don't have to consider it because with the
// CopyClientKeysCertsToChaps feature enabled all the necessary data is
// automatically copied from the public slot into the private slot.
GTEST_SKIP();
}
base::AddTagToTestResult("feature_id",
"screenplay-63f95a00-bff8-4d81-9cf9-ccf5fdacbef0");
if (!IsPreTest()) {
// Set up the private slot before
// |PlatformKeysTestBase::SetUpOnMainThread| triggers the user sign-in.
ASSERT_TRUE(user_private_slot_db_.is_open());
base::RunLoop loop;
content::GetIOThreadTaskRunner({})->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&PlatformKeysTest::SetPrivateSoftwareSlotOnIO,
base::Unretained(this),
crypto::ScopedPK11Slot(
PK11_ReferenceSlot(user_private_slot_db_.slot()))),
loop.QuitClosure());
loop.Run();
}
PlatformKeysTestBase::SetUpOnMainThread();
if (IsPreTest())
return;
{
base::RunLoop loop;
NssServiceFactory::GetForContext(profile())
->UnsafelyGetNSSCertDatabaseForTesting(
base::BindOnce(&PlatformKeysTest::SetupTestCerts,
base::Unretained(this), loop.QuitClosure()));
loop.Run();
}
if (user_status() != UserStatus::UNMANAGED && key_permission_policy_)
SetupKeyPermissionUserPolicy();
}
void SetupKeyPermissionUserPolicy() {
policy::PolicyMap policy;
// Set up the test policy that gives |extension_| the permission to access
// corporate keys.
base::Value::Dict key_permissions_policy;
{
base::Value::Dict cert1_key_permission;
cert1_key_permission.Set("allowCorporateKeyUsage", true);
key_permissions_policy.Set(kExtensionId, std::move(cert1_key_permission));
}
policy.Set(policy::key::kKeyPermissions, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(key_permissions_policy)), nullptr);
mock_policy_provider()->UpdateChromePolicy(policy);
}
chromeos::ExtensionPlatformKeysService* GetExtensionPlatformKeysService() {
return chromeos::ExtensionPlatformKeysServiceFactory::GetForBrowserContext(
profile());
}
bool RunPlatformKeysTest(const char* test_suite_name) {
// By default, the system token is not available.
const char* system_token_availability = "false";
// 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 (system_token_status() == SystemTokenStatus::EXISTS &&
enrollment_status() == EnrollmentStatus::ENROLLED &&
user_status() == UserStatus::MANAGED_AFFILIATED_DOMAIN) {
system_token_availability = "true";
}
// The test gets configuration values from the custom arg.
const std::string custom_arg = base::StringPrintf(
R"({ "testSuiteName": "%s", "systemTokenEnabled": %s })",
test_suite_name, system_token_availability);
return RunExtensionTest("platform_keys", {.custom_arg = custom_arg.c_str()},
{.context_type = context_type_});
}
void RegisterClient1AsCorporateKey() {
const extensions::Extension* const fake_gen_extension =
LoadExtension(test_data_dir_.AppendASCII("platform_keys_genkey"));
base::RunLoop run_loop;
chromeos::platform_keys::ExtensionKeyPermissionsServiceFactory::
GetForBrowserContextAndExtension(
base::BindOnce(&PlatformKeysTest::GotPermissionsForExtension,
base::Unretained(this), run_loop.QuitClosure()),
profile(), fake_gen_extension->id());
run_loop.Run();
}
protected:
// Imported into user's private or public slot, depending on the value of
// |user_client_cert_slot_|.
scoped_refptr<net::X509Certificate> client_cert1_;
// Imported into system slot.
scoped_refptr<net::X509Certificate> client_cert2_;
// Signed using an elliptic curve (ECDSA) algorithm.
// Imported in the same slot as |client_cert1_|.
scoped_refptr<net::X509Certificate> client_cert3_;
private:
base::FilePath extension_path() const {
return test_data_dir_.AppendASCII("platform_keys");
}
void SetPrivateSoftwareSlotOnIO(crypto::ScopedPK11Slot slot) {
crypto::SetPrivateSoftwareSlotForChromeOSUserForTesting(std::move(slot));
}
void OnKeyRegisteredForCorporateUsage(
std::unique_ptr<chromeos::platform_keys::ExtensionKeyPermissionsService>
extension_key_permissions_service,
base::OnceClosure done_callback,
bool is_error,
crosapi::mojom::KeystoreError error) {
ASSERT_FALSE(is_error) << static_cast<int>(error);
std::move(done_callback).Run();
}
void GotPermissionsForExtension(
base::OnceClosure done_callback,
std::unique_ptr<chromeos::platform_keys::ExtensionKeyPermissionsService>
extension_key_permissions_service) {
auto* extension_key_permissions_service_unowned =
extension_key_permissions_service.get();
extension_key_permissions_service_unowned->RegisterKeyForCorporateUsage(
chromeos::platform_keys::GetSubjectPublicKeyInfoBlob(client_cert1_),
base::BindOnce(&PlatformKeysTest::OnKeyRegisteredForCorporateUsage,
base::Unretained(this),
std::move(extension_key_permissions_service),
std::move(done_callback)));
}
void SetupTestCerts(base::OnceClosure done_callback,
net::NSSCertDatabase* cert_db) {
SetupTestClientCerts(cert_db);
SetupTestCACerts();
std::move(done_callback).Run();
}
void SetupTestClientCerts(net::NSSCertDatabase* cert_db) {
// Sanity check to ensure that
// SetPrivateSoftwareSlotForChromeOSUserForTesting took effect.
EXPECT_EQ(user_private_slot_db_.slot(), cert_db->GetPrivateSlot().get());
EXPECT_NE(cert_db->GetPrivateSlot().get(), cert_db->GetPublicSlot().get());
crypto::ScopedPK11Slot slot =
user_client_cert_slot_ == UserClientCertSlot::kPrivateSlot
? cert_db->GetPrivateSlot()
: cert_db->GetPublicSlot();
client_cert1_ = net::ImportClientCertAndKeyFromFile(
extension_path(), "client_1.pem", "client_1.pk8", slot.get());
ASSERT_TRUE(client_cert1_.get());
// Import a second client cert signed by another CA than client_1 into the
// system wide key slot.
client_cert2_ = net::ImportClientCertAndKeyFromFile(
extension_path(), "client_2.pem", "client_2.pk8",
test_system_slot()->slot());
ASSERT_TRUE(client_cert2_.get());
client_cert3_ = net::ImportClientCertAndKeyFromFile(
extension_path(), "client_3.pem", "client_3.pk8", slot.get());
ASSERT_TRUE(client_cert3_.get());
// The main important observer for these tests is Kcer.
net::CertDatabase::GetInstance()->NotifyObserversClientCertStoreChanged();
}
void SetupTestCACerts() {
// "root.pem" is the issuer of the "l1_leaf.pem" and (transitively)
// "l1_leaf.pem" certs which are loaded on the JS side. Generated by
// create_test_certs.sh .
scoped_refptr<net::X509Certificate> root =
net::ImportCertFromFile(extension_path().AppendASCII("root.pem"));
ASSERT_TRUE(root);
scoped_test_root_.Reset({root});
}
const bool key_permission_policy_;
const UserClientCertSlot user_client_cert_slot_;
crypto::ScopedTestNSSDB user_private_slot_db_;
const ContextType context_type_;
net::ScopedTestRoot scoped_test_root_;
};
class TestSelectDelegate
: public chromeos::ExtensionPlatformKeysService::SelectDelegate {
public:
// 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) {}
~TestSelectDelegate() override {}
void Select(const std::string& extension_id,
const net::CertificateList& certs,
CertificateSelectedCallback callback,
content::WebContents* web_contents,
content::BrowserContext* context) override {
ASSERT_TRUE(context);
ASSERT_FALSE(certs_to_select_.empty());
scoped_refptr<net::X509Certificate> selection;
if (certs_to_select_.back()) {
for (scoped_refptr<net::X509Certificate> cert : certs) {
if (cert->EqualsExcludingChain(certs_to_select_.back().get())) {
selection = cert;
break;
}
}
}
if (certs_to_select_.size() > 1)
certs_to_select_.pop_back();
std::move(callback).Run(selection);
}
private:
net::CertificateList certs_to_select_;
};
struct UnmanagedPlatformKeysTestParams {
UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus enrollment_status,
PlatformKeysTest::UserClientCertSlot user_client_cert_slot,
ContextType context_type)
: enrollment_status_(enrollment_status),
user_client_cert_slot_(user_client_cert_slot),
context_type_(context_type) {}
PlatformKeysTestBase::EnrollmentStatus enrollment_status_;
PlatformKeysTest::UserClientCertSlot user_client_cert_slot_;
ContextType context_type_;
};
class UnmanagedPlatformKeysTest
: public PlatformKeysTest,
public ::testing::WithParamInterface<UnmanagedPlatformKeysTestParams> {
public:
UnmanagedPlatformKeysTest()
: PlatformKeysTest(GetParam().enrollment_status_,
UserStatus::UNMANAGED,
false /* unused */,
GetParam().user_client_cert_slot_,
GetParam().context_type_) {}
};
struct ManagedPlatformKeysTestParams {
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus enrollment_status,
PlatformKeysTestBase::UserStatus user_status,
ContextType context_type)
: enrollment_status_(enrollment_status),
user_status_(user_status),
context_type_(context_type) {}
PlatformKeysTestBase::EnrollmentStatus enrollment_status_;
PlatformKeysTestBase::UserStatus user_status_;
ContextType context_type_;
};
class ManagedWithPermissionPlatformKeysTest
: public PlatformKeysTest,
public ::testing::WithParamInterface<ManagedPlatformKeysTestParams> {
public:
ManagedWithPermissionPlatformKeysTest()
: PlatformKeysTest(GetParam().enrollment_status_,
GetParam().user_status_,
true /* grant the extension key permission */,
UserClientCertSlot::kPrivateSlot,
GetParam().context_type_) {}
};
class ManagedWithoutPermissionPlatformKeysTest
: public PlatformKeysTest,
public ::testing::WithParamInterface<ManagedPlatformKeysTestParams> {
public:
ManagedWithoutPermissionPlatformKeysTest()
: PlatformKeysTest(GetParam().enrollment_status_,
GetParam().user_status_,
false /* do not grant key permission */,
UserClientCertSlot::kPrivateSlot,
GetParam().context_type_) {}
};
} // namespace
IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, PRE_Basic) {
RunPreTest();
}
// At first interactively selects |client_cert1_|, |client_cert2_| and
// |client_cert3_| 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(UnmanagedPlatformKeysTest, Basic) {
net::CertificateList certs;
certs.push_back(nullptr);
certs.push_back(client_cert3_);
certs.push_back(client_cert2_);
certs.push_back(client_cert1_);
GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunPlatformKeysTest("basicTests")) << message_;
}
IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest,
PRE_BackgroundInteractiveTest) {
RunPreTest();
}
// Tests that interactive calls are not allowed from the extension's
// background page. This test is simple and requires no certs or any
// particular setup.
IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, BackgroundInteractiveTest) {
// This needs to be set to false, since we're testing the actual error.
extensions::PlatformKeysInternalSelectClientCertificatesFunction::
SetSkipInteractiveCheckForTest(false);
net::CertificateList certs;
certs.push_back(nullptr);
GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunPlatformKeysTest("backgroundInteractiveTest")) << message_;
}
IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, PRE_Permissions) {
RunPreTest();
}
// On interactive calls, the simulated user always selects |client_cert1_| if
// matching.
IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, Permissions) {
net::CertificateList certs;
certs.push_back(client_cert1_);
GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunPlatformKeysTest("permissionTests")) << message_;
}
INSTANTIATE_TEST_SUITE_P(
PersistentBackground,
UnmanagedPlatformKeysTest,
::testing::Values(UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPrivateSlot,
ContextType::kPersistentBackground),
UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPrivateSlot,
ContextType::kPersistentBackground),
UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPublicSlot,
ContextType::kPersistentBackground),
UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPublicSlot,
ContextType::kPersistentBackground)));
INSTANTIATE_TEST_SUITE_P(
ServiceWorker,
UnmanagedPlatformKeysTest,
::testing::Values(UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPrivateSlot,
ContextType::kServiceWorker),
UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPrivateSlot,
ContextType::kServiceWorker),
UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPublicSlot,
ContextType::kServiceWorker),
UnmanagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTest::UserClientCertSlot::kPublicSlot,
ContextType::kServiceWorker)));
IN_PROC_BROWSER_TEST_P(ManagedWithoutPermissionPlatformKeysTest,
PRE_UserPermissionsBlocked) {
RunPreTest();
}
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.
GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(net::CertificateList()));
ASSERT_TRUE(RunPlatformKeysTest("managedProfile")) << message_;
}
IN_PROC_BROWSER_TEST_P(ManagedWithoutPermissionPlatformKeysTest,
PRE_CorporateKeyAccessBlocked) {
RunPreTest();
}
// 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.
GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(net::CertificateList()));
ASSERT_TRUE(RunPlatformKeysTest("corporateKeyWithoutPermissionTests"))
<< message_;
}
INSTANTIATE_TEST_SUITE_P(
PersistentBackground,
ManagedWithoutPermissionPlatformKeysTest,
::testing::Values(
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN,
ContextType::kPersistentBackground),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kPersistentBackground),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kPersistentBackground)));
INSTANTIATE_TEST_SUITE_P(
ServiceWorker,
ManagedWithoutPermissionPlatformKeysTest,
::testing::Values(
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN,
ContextType::kServiceWorker),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kServiceWorker),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kServiceWorker)));
IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest,
PRE_PolicyGrantsAccessToCorporateKey) {
RunPreTest();
}
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_);
GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunPlatformKeysTest("corporateKeyWithPermissionTests"))
<< message_;
}
IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest,
PRE_PolicyDoesGrantAccessToNonCorporateKey) {
RunPreTest();
}
IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest,
PolicyDoesGrantAccessToNonCorporateKey) {
// The policy grants access to corporate keys.
// As the profile is managed, the user must not be able to grant any
// certificate permission.
// If the user is not affilited, no corporate keys are available. Set up a
// delegate that fails on any invocation. If the user is affiliated, client_2
// on the system token will be avialable for selection, as it is implicitly
// corporate.
net::CertificateList certs;
if (user_status() == UserStatus::MANAGED_AFFILIATED_DOMAIN)
certs.push_back(nullptr);
GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunPlatformKeysTest("policyDoesGrantAccessToNonCorporateKey"))
<< message_;
}
INSTANTIATE_TEST_SUITE_P(
PersistentBackground,
ManagedWithPermissionPlatformKeysTest,
::testing::Values(
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN,
ContextType::kPersistentBackground),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kPersistentBackground),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kPersistentBackground)));
INSTANTIATE_TEST_SUITE_P(
ServiceWorker,
ManagedWithPermissionPlatformKeysTest,
::testing::Values(
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN,
ContextType::kServiceWorker),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kServiceWorker),
ManagedPlatformKeysTestParams(
PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED,
PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN,
ContextType::kServiceWorker)));