Commit 6e095509 authored by Leo Lai's avatar Leo Lai Committed by Commit Bot

use AttestationClient to get key info in MachineCertificateUploader.

We are deprecating attestation methods by CryptohomeClient.

This CL also includes a simplied flow by consolidating
TpmAttestationDoesKeyExist and TpmAttestationGetCertificate, of which
results come from the same methods of attestation service anyway.

BUG=b:158955123
TEST=unit_tests.

Change-Id: I36933b4ee20e86fd6946644d957ab70459609482
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2515801
Commit-Queue: Leo Lai <cylai@google.com>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823899}
parent d90a3ba0
...@@ -44,51 +44,6 @@ const int kExpiryThresholdInDays = 30; ...@@ -44,51 +44,6 @@ const int kExpiryThresholdInDays = 30;
const int kRetryDelay = 5; // Seconds. const int kRetryDelay = 5; // Seconds.
const int kRetryLimit = 100; const int kRetryLimit = 100;
// A dbus callback which handles a boolean result.
//
// Parameters
// on_true - Called when status=success and value=true.
// on_false - Called when status=success and value=false.
// status - The dbus operation status.
// result - The value returned by the dbus operation.
void DBusBoolRedirectCallback(const base::RepeatingClosure& on_true,
const base::RepeatingClosure& on_false,
const base::RepeatingClosure& on_failure,
const base::Location& from_here,
base::Optional<bool> result) {
if (!result.has_value()) {
LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString();
if (!on_failure.is_null())
on_failure.Run();
return;
}
const base::RepeatingClosure& task = result.value() ? on_true : on_false;
if (!task.is_null())
task.Run();
}
// A dbus callback which handles a string result.
//
// Parameters
// on_success - Called when status=success and result=true.
// status - The dbus operation status.
// result - The result returned by the dbus operation.
// data - The data returned by the dbus operation.
void DBusStringCallback(
const base::RepeatingCallback<void(const std::string&)> on_success,
const base::RepeatingClosure& on_failure,
const base::Location& from_here,
base::Optional<chromeos::CryptohomeClient::TpmAttestationDataResult>
result) {
if (!result.has_value() || !result->success) {
LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString();
if (!on_failure.is_null())
on_failure.Run();
return;
}
on_success.Run(result->data);
}
void DBusPrivacyCACallback( void DBusPrivacyCACallback(
const base::RepeatingCallback<void(const std::string&)> on_success, const base::RepeatingCallback<void(const std::string&)> on_success,
const base::RepeatingCallback< const base::RepeatingCallback<
...@@ -181,22 +136,13 @@ void MachineCertificateUploaderImpl::Start() { ...@@ -181,22 +136,13 @@ void MachineCertificateUploaderImpl::Start() {
return; return;
} }
// Start a dbus call to check if an Enterprise Machine Key already exists. ::attestation::GetKeyInfoRequest request;
base::RepeatingClosure on_does_not_exist = request.set_username("");
base::BindRepeating(&MachineCertificateUploaderImpl::GetNewCertificate, request.set_key_label(kEnterpriseMachineKey);
weak_factory_.GetWeakPtr()); AttestationClient::Get()->GetKeyInfo(
base::RepeatingClosure on_does_exist = base::BindRepeating( request,
&MachineCertificateUploaderImpl::GetExistingCertificate, base::BindOnce(&MachineCertificateUploaderImpl::OnGetExistingCertificate,
weak_factory_.GetWeakPtr()); weak_factory_.GetWeakPtr()));
cryptohome_client_->TpmAttestationDoesKeyExist(
KEY_DEVICE,
cryptohome::AccountIdentifier(), // Not used.
kEnterpriseMachineKey,
base::BindOnce(
DBusBoolRedirectCallback, on_does_exist, on_does_not_exist,
base::BindRepeating(&MachineCertificateUploaderImpl::Reschedule,
weak_factory_.GetWeakPtr()),
FROM_HERE));
} }
void MachineCertificateUploaderImpl::GetNewCertificate() { void MachineCertificateUploaderImpl::GetNewCertificate() {
...@@ -224,23 +170,26 @@ void MachineCertificateUploaderImpl::GetNewCertificate() { ...@@ -224,23 +170,26 @@ void MachineCertificateUploaderImpl::GetNewCertificate() {
FROM_HERE)); FROM_HERE));
} }
void MachineCertificateUploaderImpl::GetExistingCertificate() { void MachineCertificateUploaderImpl::OnGetExistingCertificate(
cryptohome_client_->TpmAttestationGetCertificate( const ::attestation::GetKeyInfoReply& reply) {
KEY_DEVICE, if (reply.status() != ::attestation::STATUS_SUCCESS &&
cryptohome::AccountIdentifier(), // Not used. reply.status() != ::attestation::STATUS_INVALID_PARAMETER) {
kEnterpriseMachineKey, LOG(ERROR) << "Error getting the existing certificate; status: "
base::BindOnce( << reply.status();
DBusStringCallback, Reschedule();
base::BindRepeating( return;
&MachineCertificateUploaderImpl::CheckCertificateExpiry, }
weak_factory_.GetWeakPtr()), // Get a new certificate if not exists.
base::BindRepeating(&MachineCertificateUploaderImpl::Reschedule, if (reply.status() == ::attestation::STATUS_INVALID_PARAMETER) {
weak_factory_.GetWeakPtr()), GetNewCertificate();
FROM_HERE)); return;
}
CheckCertificateExpiry(reply);
} }
void MachineCertificateUploaderImpl::CheckCertificateExpiry( void MachineCertificateUploaderImpl::CheckCertificateExpiry(
const std::string& pem_certificate_chain) { const ::attestation::GetKeyInfoReply& reply) {
const std::string& pem_certificate_chain = reply.certificate();
int num_certificates = 0; int num_certificates = 0;
net::PEMTokenizer pem_tokenizer(pem_certificate_chain, {"CERTIFICATE"}); net::PEMTokenizer pem_tokenizer(pem_certificate_chain, {"CERTIFICATE"});
while (pem_tokenizer.GetNext()) { while (pem_tokenizer.GetNext()) {
...@@ -270,13 +219,7 @@ void MachineCertificateUploaderImpl::CheckCertificateExpiry( ...@@ -270,13 +219,7 @@ void MachineCertificateUploaderImpl::CheckCertificateExpiry(
if (num_certificates == 0) { if (num_certificates == 0) {
LOG(WARNING) << "Failed to parse certificate chain, cannot check expiry."; LOG(WARNING) << "Failed to parse certificate chain, cannot check expiry.";
} }
::attestation::GetKeyInfoRequest request; CheckIfUploaded(reply);
request.set_username("");
request.set_key_label(kEnterpriseMachineKey);
AttestationClient::Get()->GetKeyInfo(
request,
base::BindOnce(&MachineCertificateUploaderImpl::CheckIfUploaded,
weak_factory_.GetWeakPtr(), pem_certificate_chain));
} }
void MachineCertificateUploaderImpl::UploadCertificate( void MachineCertificateUploaderImpl::UploadCertificate(
...@@ -289,9 +232,12 @@ void MachineCertificateUploaderImpl::UploadCertificate( ...@@ -289,9 +232,12 @@ void MachineCertificateUploaderImpl::UploadCertificate(
} }
void MachineCertificateUploaderImpl::CheckIfUploaded( void MachineCertificateUploaderImpl::CheckIfUploaded(
const std::string& pem_certificate_chain,
const ::attestation::GetKeyInfoReply& reply) { const ::attestation::GetKeyInfoReply& reply) {
// The caller in the entire flow should have checked the reply status already.
if (reply.status() != ::attestation::STATUS_SUCCESS) { if (reply.status() != ::attestation::STATUS_SUCCESS) {
LOG(DFATAL) << "Checking key payload in a bad reply from attestation "
"service; status: "
<< reply.status();
Reschedule(); Reschedule();
return; return;
} }
...@@ -304,7 +250,7 @@ void MachineCertificateUploaderImpl::CheckIfUploaded( ...@@ -304,7 +250,7 @@ void MachineCertificateUploaderImpl::CheckIfUploaded(
RunCallbacks(certificate_uploaded_.value()); RunCallbacks(certificate_uploaded_.value());
return; return;
} }
UploadCertificate(pem_certificate_chain); UploadCertificate(reply.certificate());
} }
void MachineCertificateUploaderImpl::OnUploadComplete(bool status) { void MachineCertificateUploaderImpl::OnUploadComplete(bool status) {
...@@ -333,6 +279,10 @@ void MachineCertificateUploaderImpl::WaitForUploadComplete( ...@@ -333,6 +279,10 @@ void MachineCertificateUploaderImpl::WaitForUploadComplete(
void MachineCertificateUploaderImpl::MarkAsUploaded( void MachineCertificateUploaderImpl::MarkAsUploaded(
const ::attestation::GetKeyInfoReply& reply) { const ::attestation::GetKeyInfoReply& reply) {
if (reply.status() != ::attestation::STATUS_SUCCESS) {
LOG(WARNING) << "Failed to get existing payload.";
return;
}
AttestationKeyPayload payload_pb; AttestationKeyPayload payload_pb;
if (!reply.payload().empty()) if (!reply.payload().empty())
payload_pb.ParseFromString(reply.payload()); payload_pb.ParseFromString(reply.payload());
......
...@@ -67,19 +67,23 @@ class MachineCertificateUploaderImpl : public MachineCertificateUploader { ...@@ -67,19 +67,23 @@ class MachineCertificateUploaderImpl : public MachineCertificateUploader {
// Gets a new certificate for the Enterprise Machine Key (EMK). // Gets a new certificate for the Enterprise Machine Key (EMK).
void GetNewCertificate(); void GetNewCertificate();
// Gets the existing EMK certificate and sends it to CheckCertificateExpiry. // Called when `GetKeyInfo()` returned to check the existing certificate.
void GetExistingCertificate(); // There are 3 cases by the status replied from attestation service:
// 1. If the existing EMK is found, calls `CheckCertificateExpiry()`.
// 2. If the key does not exist, calls `GetNewCertificate()`.
// 3. Otherwise, there is an error and `Reschedule()` is called to retry.
void OnGetExistingCertificate(const ::attestation::GetKeyInfoReply& reply);
// Checks if any certificate in the given pem_certificate_chain is expired // Checks if any certificate in the given `reply` is expired and, if so, gets
// and, if so, gets a new one. If not renewing, calls CheckIfUploaded. // a new one. If not renewing, calls `CheckIfUploaded()`.
void CheckCertificateExpiry(const std::string& pem_certificate_chain); void CheckCertificateExpiry(const ::attestation::GetKeyInfoReply& reply);
// Uploads a machine certificate to the policy server. // Uploads a machine certificate to the policy server.
void UploadCertificate(const std::string& pem_certificate_chain); void UploadCertificate(const std::string& pem_certificate_chain);
// Checks if a certificate has already been uploaded and, if not, upload. // Checks if a certificate in `reply` has already been uploaded and, if not,
void CheckIfUploaded(const std::string& pem_certificate_chain, // upload.
const ::attestation::GetKeyInfoReply& reply); void CheckIfUploaded(const ::attestation::GetKeyInfoReply& reply);
// Called when a certificate upload operation completes. On success, |status| // Called when a certificate upload operation completes. On success, |status|
// will be true. // will be true.
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "chrome/browser/chromeos/attestation/machine_certificate_uploader_impl.h" #include "chrome/browser/chromeos/attestation/machine_certificate_uploader_impl.h"
#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
#include "chromeos/attestation/mock_attestation_flow.h" #include "chromeos/attestation/mock_attestation_flow.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/attestation/fake_attestation_client.h" #include "chromeos/dbus/attestation/fake_attestation_client.h"
#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
#include "chromeos/settings/cros_settings_names.h" #include "chromeos/settings/cros_settings_names.h"
...@@ -34,9 +35,11 @@ namespace attestation { ...@@ -34,9 +35,11 @@ namespace attestation {
namespace { namespace {
const int64_t kCertValid = 90; constexpr int64_t kCertValid = 90;
const int64_t kCertExpiringSoon = 20; constexpr int64_t kCertExpiringSoon = 20;
const int64_t kCertExpired = -20; constexpr int64_t kCertExpired = -20;
constexpr int kRetryLimit = 3;
constexpr char kFakeCertificate[] = "fake_cert";
void CertCallbackSuccess(AttestationFlow::CertificateCallback callback) { void CertCallbackSuccess(AttestationFlow::CertificateCallback callback) {
AttestationClient::Get() AttestationClient::Get()
...@@ -77,16 +80,50 @@ class CallbackObserver { ...@@ -77,16 +80,50 @@ class CallbackObserver {
} }
}; };
class MockableFakeAttestationFlow : public MockAttestationFlow {
public:
MockableFakeAttestationFlow() {
ON_CALL(*this, GetCertificate(_, _, _, _, _, _))
.WillByDefault(
Invoke(this, &MockableFakeAttestationFlow::GetCertificateInternal));
}
~MockableFakeAttestationFlow() override = default;
void set_status(AttestationStatus status) { status_ = status; }
private:
void GetCertificateInternal(AttestationCertificateProfile certificate_profile,
const AccountId& account_id,
const std::string& request_origin,
bool force_new_key,
const std::string& key_name,
CertificateCallback callback) {
std::string certificate;
if (status_ == ATTESTATION_SUCCESS) {
certificate = certificate_;
AttestationClient::Get()
->GetTestInterface()
->GetMutableKeyInfoReply(cryptohome::Identification(account_id).id(),
kEnterpriseMachineKey)
->set_certificate(certificate_);
}
std::move(callback).Run(status_, certificate);
}
AttestationStatus status_ = ATTESTATION_SUCCESS;
const std::string certificate_ = kFakeCertificate;
};
} // namespace } // namespace
class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> { class MachineCertificateUploaderTestBase : public ::testing::Test {
public: public:
MachineCertificateUploaderTest() { MachineCertificateUploaderTestBase() {
AttestationClient::InitializeFake(); AttestationClient::InitializeFake();
settings_helper_.ReplaceDeviceSettingsProviderWithStub(); settings_helper_.ReplaceDeviceSettingsProviderWithStub();
policy_client_.SetDMToken("fake_dm_token"); policy_client_.SetDMToken("fake_dm_token");
} }
~MachineCertificateUploaderTest() override { AttestationClient::Shutdown(); } ~MachineCertificateUploaderTestBase() override {
AttestationClient::Shutdown();
}
protected: protected:
enum MockOptions { enum MockOptions {
...@@ -95,7 +132,9 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> { ...@@ -95,7 +132,9 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> {
MOCK_NEW_KEY = (1 << 2) // Configure expecting new key generation. MOCK_NEW_KEY = (1 << 2) // Configure expecting new key generation.
}; };
bool GetShouldRefreshCert() { return GetParam(); } // The derived fixture has different needs to control this function's
// behavior.
virtual bool GetShouldRefreshCert() const = 0;
// Configures mock expectations according to |mock_options|. If options // Configures mock expectations according to |mock_options|. If options
// require that a certificate exists, |certificate| will be used. // require that a certificate exists, |certificate| will be used.
...@@ -103,8 +142,6 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> { ...@@ -103,8 +142,6 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> {
bool key_exists = (mock_options & MOCK_KEY_EXISTS); bool key_exists = (mock_options & MOCK_KEY_EXISTS);
// Setup expected key / cert queries. // Setup expected key / cert queries.
if (key_exists) { if (key_exists) {
cryptohome_client_.SetTpmAttestationDeviceCertificate(
kEnterpriseMachineKey, certificate);
::attestation::GetKeyInfoReply* key_info = ::attestation::GetKeyInfoReply* key_info =
AttestationClient::Get()->GetTestInterface()->GetMutableKeyInfoReply( AttestationClient::Get()->GetTestInterface()->GetMutableKeyInfoReply(
/*username=*/"", kEnterpriseMachineKey); /*username=*/"", kEnterpriseMachineKey);
...@@ -112,8 +149,7 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> { ...@@ -112,8 +149,7 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> {
} }
// Setup expected key payload queries. // Setup expected key payload queries.
bool key_uploaded = bool key_uploaded = (mock_options & MOCK_KEY_UPLOADED);
GetShouldRefreshCert() || (mock_options & MOCK_KEY_UPLOADED);
if (key_uploaded) { if (key_uploaded) {
::attestation::GetKeyInfoReply* key_info = ::attestation::GetKeyInfoReply* key_info =
AttestationClient::Get()->GetTestInterface()->GetMutableKeyInfoReply( AttestationClient::Get()->GetTestInterface()->GetMutableKeyInfoReply(
...@@ -128,8 +164,9 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> { ...@@ -128,8 +164,9 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> {
// status in the key payload matches the upload operation. // status in the key payload matches the upload operation.
bool new_key = GetShouldRefreshCert() || (mock_options & MOCK_NEW_KEY); bool new_key = GetShouldRefreshCert() || (mock_options & MOCK_NEW_KEY);
if (new_key || !key_uploaded) { if (new_key || !key_uploaded) {
EXPECT_CALL(policy_client_, UploadEnterpriseMachineCertificate( EXPECT_CALL(policy_client_,
new_key ? "fake_cert" : certificate, _)) UploadEnterpriseMachineCertificate(
new_key ? kFakeCertificate : certificate, _))
.WillOnce(WithArgs<1>(Invoke(StatusCallbackSuccess))); .WillOnce(WithArgs<1>(Invoke(StatusCallbackSuccess)));
} }
...@@ -137,15 +174,14 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> { ...@@ -137,15 +174,14 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> {
// another costly operation and if it gets triggered more than once during // another costly operation and if it gets triggered more than once during
// a single pass this indicates a logical problem in the observer. // a single pass this indicates a logical problem in the observer.
if (new_key) { if (new_key) {
EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _, _)) EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _, _));
.WillOnce(WithArgs<5>(Invoke(CertCallbackSuccess)));
} }
} }
void Run() { void RunUploader() {
MachineCertificateUploaderImpl uploader( MachineCertificateUploaderImpl uploader(
&policy_client_, &cryptohome_client_, &attestation_flow_); &policy_client_, &cryptohome_client_, &attestation_flow_);
uploader.set_retry_limit(3); uploader.set_retry_limit(kRetryLimit);
uploader.set_retry_delay(0); uploader.set_retry_delay(0);
if (GetShouldRefreshCert()) if (GetShouldRefreshCert())
uploader.RefreshAndUploadCertificate(base::DoNothing()); uploader.RefreshAndUploadCertificate(base::DoNothing());
...@@ -166,30 +202,37 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> { ...@@ -166,30 +202,37 @@ class MachineCertificateUploaderTest : public ::testing::TestWithParam<bool> {
content::BrowserTaskEnvironment task_environment_; content::BrowserTaskEnvironment task_environment_;
ScopedCrosSettingsTestHelper settings_helper_; ScopedCrosSettingsTestHelper settings_helper_;
FakeCryptohomeClient cryptohome_client_; FakeCryptohomeClient cryptohome_client_;
StrictMock<MockAttestationFlow> attestation_flow_; StrictMock<MockableFakeAttestationFlow> attestation_flow_;
StrictMock<policy::MockCloudPolicyClient> policy_client_; StrictMock<policy::MockCloudPolicyClient> policy_client_;
}; };
class MachineCertificateUploaderTest
: public MachineCertificateUploaderTestBase,
public ::testing::WithParamInterface<bool> {
public:
bool GetShouldRefreshCert() const final { return GetParam(); }
};
TEST_P(MachineCertificateUploaderTest, UnregisteredPolicyClient) { TEST_P(MachineCertificateUploaderTest, UnregisteredPolicyClient) {
policy_client_.SetDMToken(""); policy_client_.SetDMToken("");
Run(); RunUploader();
} }
TEST_P(MachineCertificateUploaderTest, GetCertificateUnspecifiedFailure) { TEST_P(MachineCertificateUploaderTest, GetCertificateUnspecifiedFailure) {
EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _, _)) EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _, _))
.WillRepeatedly(WithArgs<5>(Invoke(CertCallbackUnspecifiedFailure))); .WillRepeatedly(WithArgs<5>(Invoke(CertCallbackUnspecifiedFailure)));
Run(); RunUploader();
} }
TEST_P(MachineCertificateUploaderTest, GetCertificateBadRequestFailure) { TEST_P(MachineCertificateUploaderTest, GetCertificateBadRequestFailure) {
EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _, _)) EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _, _))
.WillOnce(WithArgs<5>(Invoke(CertCallbackBadRequestFailure))); .WillOnce(WithArgs<5>(Invoke(CertCallbackBadRequestFailure)));
Run(); RunUploader();
} }
TEST_P(MachineCertificateUploaderTest, NewCertificate) { TEST_P(MachineCertificateUploaderTest, NewCertificate) {
SetupMocks(MOCK_NEW_KEY, ""); SetupMocks(MOCK_NEW_KEY, "");
Run(); RunUploader();
EXPECT_EQ(CreatePayload(), EXPECT_EQ(CreatePayload(),
AttestationClient::Get() AttestationClient::Get()
->GetTestInterface() ->GetTestInterface()
...@@ -266,7 +309,7 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsNotUploaded) { ...@@ -266,7 +309,7 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsNotUploaded) {
ASSERT_TRUE(GetFakeCertificatePEM(base::TimeDelta::FromDays(kCertValid), ASSERT_TRUE(GetFakeCertificatePEM(base::TimeDelta::FromDays(kCertValid),
&certificate)); &certificate));
SetupMocks(MOCK_KEY_EXISTS, certificate); SetupMocks(MOCK_KEY_EXISTS, certificate);
Run(); RunUploader();
EXPECT_EQ(CreatePayload(), EXPECT_EQ(CreatePayload(),
AttestationClient::Get() AttestationClient::Get()
->GetTestInterface() ->GetTestInterface()
...@@ -279,7 +322,7 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsAlreadyUploaded) { ...@@ -279,7 +322,7 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsAlreadyUploaded) {
ASSERT_TRUE(GetFakeCertificatePEM(base::TimeDelta::FromDays(kCertValid), ASSERT_TRUE(GetFakeCertificatePEM(base::TimeDelta::FromDays(kCertValid),
&certificate)); &certificate));
SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED, certificate); SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED, certificate);
Run(); RunUploader();
} }
TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpiringSoon) { TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpiringSoon) {
...@@ -287,7 +330,7 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpiringSoon) { ...@@ -287,7 +330,7 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpiringSoon) {
ASSERT_TRUE(GetFakeCertificatePEM( ASSERT_TRUE(GetFakeCertificatePEM(
base::TimeDelta::FromDays(kCertExpiringSoon), &certificate)); base::TimeDelta::FromDays(kCertExpiringSoon), &certificate));
SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED | MOCK_NEW_KEY, certificate); SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED | MOCK_NEW_KEY, certificate);
Run(); RunUploader();
} }
TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpired) { TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpired) {
...@@ -295,41 +338,38 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpired) { ...@@ -295,41 +338,38 @@ TEST_P(MachineCertificateUploaderTest, KeyExistsCertExpired) {
ASSERT_TRUE(GetFakeCertificatePEM(base::TimeDelta::FromDays(kCertExpired), ASSERT_TRUE(GetFakeCertificatePEM(base::TimeDelta::FromDays(kCertExpired),
&certificate)); &certificate));
SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED | MOCK_NEW_KEY, certificate); SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED | MOCK_NEW_KEY, certificate);
Run(); RunUploader();
} }
TEST_P(MachineCertificateUploaderTest, IgnoreUnknownCertFormat) { TEST_P(MachineCertificateUploaderTest, IgnoreUnknownCertFormat) {
SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED, "unsupported"); SetupMocks(MOCK_KEY_EXISTS | MOCK_KEY_UPLOADED, "unsupported");
Run(); RunUploader();
} }
TEST_P(MachineCertificateUploaderTest, DBusFailureRetry) { INSTANTIATE_TEST_SUITE_P(All,
MachineCertificateUploaderTest,
testing::Values(false, true));
class MachineCertificateUploaderTestNoRefresh
: public MachineCertificateUploaderTestBase {
public:
bool GetShouldRefreshCert() const final { return false; }
};
TEST_F(MachineCertificateUploaderTestNoRefresh, DBusFailureRetry) {
SetupMocks(MOCK_NEW_KEY, ""); SetupMocks(MOCK_NEW_KEY, "");
// Simulate a DBus failure. AttestationClient::Get()->GetTestInterface()->set_key_info_dbus_error_count(
cryptohome_client_.SetServiceIsAvailable(false); kRetryLimit - 1);
RunUploader();
// Emulate delayed service initialization.
// Run() instantiates an Observer, which synchronously calls
// TpmAttestationDoesKeyExist() and fails. During this call, we make the
// service available in the next run, so on retry, it will successfully
// return the result.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(
[](FakeCryptohomeClient* cryptohome_client) {
cryptohome_client->SetServiceIsAvailable(true);
},
base::Unretained(&cryptohome_client_)));
Run();
EXPECT_EQ(CreatePayload(), EXPECT_EQ(CreatePayload(),
AttestationClient::Get() AttestationClient::Get()
->GetTestInterface() ->GetTestInterface()
->GetMutableKeyInfoReply(/*username=*/"", kEnterpriseMachineKey) ->GetMutableKeyInfoReply(/*username=*/"", kEnterpriseMachineKey)
->payload()); ->payload());
EXPECT_EQ(
AttestationClient::Get()->GetTestInterface()->key_info_dbus_error_count(),
0);
} }
INSTANTIATE_TEST_SUITE_P(All,
MachineCertificateUploaderTest,
testing::Values(false, true));
} // namespace attestation } // namespace attestation
} // namespace chromeos } // namespace chromeos
...@@ -135,6 +135,11 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) AttestationClient { ...@@ -135,6 +135,11 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) AttestationClient {
virtual ::attestation::GetKeyInfoReply* GetMutableKeyInfoReply( virtual ::attestation::GetKeyInfoReply* GetMutableKeyInfoReply(
const std::string& username, const std::string& username,
const std::string& label) = 0; const std::string& label) = 0;
// Sets the returned status of `GetKeyInfo()` to be D-Bus error for
// `count` times to emulate D-Bus late availability.
virtual void set_key_info_dbus_error_count(int count) = 0;
// Gets the remaining count of `GetKeyInfo()` replying D-Bus error.
virtual int key_info_dbus_error_count() const = 0;
// Verifies if `signed_data` is signed against `challenge`. // Verifies if `signed_data` is signed against `challenge`.
virtual bool VerifySimpleChallengeResponse( virtual bool VerifySimpleChallengeResponse(
......
...@@ -76,12 +76,17 @@ void FakeAttestationClient::GetKeyInfo( ...@@ -76,12 +76,17 @@ void FakeAttestationClient::GetKeyInfo(
const ::attestation::GetKeyInfoRequest& request, const ::attestation::GetKeyInfoRequest& request,
GetKeyInfoCallback callback) { GetKeyInfoCallback callback) {
::attestation::GetKeyInfoReply reply; ::attestation::GetKeyInfoReply reply;
if (key_info_dbus_error_count_ > 0) {
reply.set_status(::attestation::STATUS_DBUS_ERROR);
key_info_dbus_error_count_--;
} else {
auto iter = key_info_database_.find(request); auto iter = key_info_database_.find(request);
if (iter != key_info_database_.end()) { if (iter != key_info_database_.end()) {
reply = iter->second; reply = iter->second;
} else { } else {
reply.set_status(::attestation::STATUS_INVALID_PARAMETER); reply.set_status(::attestation::STATUS_INVALID_PARAMETER);
} }
}
PostProtoResponse(std::move(callback), reply); PostProtoResponse(std::move(callback), reply);
} }
...@@ -413,6 +418,14 @@ void FakeAttestationClient::set_enrollment_id_dbus_error_count(int count) { ...@@ -413,6 +418,14 @@ void FakeAttestationClient::set_enrollment_id_dbus_error_count(int count) {
return &(key_info_database_[request]); return &(key_info_database_[request]);
} }
void FakeAttestationClient::set_key_info_dbus_error_count(int count) {
key_info_dbus_error_count_ = count;
}
int FakeAttestationClient::key_info_dbus_error_count() const {
return key_info_dbus_error_count_;
}
bool FakeAttestationClient::VerifySimpleChallengeResponse( bool FakeAttestationClient::VerifySimpleChallengeResponse(
const std::string& challenge, const std::string& challenge,
const ::attestation::SignedData& signed_data) { const ::attestation::SignedData& signed_data) {
......
...@@ -121,6 +121,8 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient ...@@ -121,6 +121,8 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient
::attestation::GetKeyInfoReply* GetMutableKeyInfoReply( ::attestation::GetKeyInfoReply* GetMutableKeyInfoReply(
const std::string& username, const std::string& username,
const std::string& label) override; const std::string& label) override;
void set_key_info_dbus_error_count(int count) override;
int key_info_dbus_error_count() const override;
bool VerifySimpleChallengeResponse( bool VerifySimpleChallengeResponse(
const std::string& challenge, const std::string& challenge,
const ::attestation::SignedData& signed_data) override; const ::attestation::SignedData& signed_data) override;
...@@ -189,6 +191,7 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient ...@@ -189,6 +191,7 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient
::attestation::GetKeyInfoReply, ::attestation::GetKeyInfoReply,
GetKeyInfoRequestComparator> GetKeyInfoRequestComparator>
key_info_database_; key_info_database_;
int key_info_dbus_error_count_ = 0;
// The status returned by `SignSimpleChallenge()`. // The status returned by `SignSimpleChallenge()`.
::attestation::AttestationStatus sign_simple_challenge_status_ = ::attestation::AttestationStatus sign_simple_challenge_status_ =
......
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