Commit 048f5308 authored by Denis Kuznetsov's avatar Denis Kuznetsov Committed by Commit Bot

Add support to perform enrollment using enrollment token.

This flow is using attestation-based flow, but provides extra
EnrollmentToken along with Register request.

TBR: alemate@chromium.org
Bug: 854101
Change-Id: I9a0710dcffc7a2f68fe43097a9e0d321769ddf35
Reviewed-on: https://chromium-review.googlesource.com/c/1327211
Commit-Queue: Denis Kuznetsov <antrim@chromium.org>
Reviewed-by: default avatarJesse Doherty <jwd@chromium.org>
Reviewed-by: default avatarSergey Poromov <poromov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610171}
parent beb23137
......@@ -24,6 +24,8 @@ const char* const kMetricEnrollmentForcedManualFallback =
const char* const kMetricEnrollmentForcedInitialManualFallback =
"Enterprise.EnrollmentForcedInitialManualFallback";
const char* const kMetricEnrollmentRecovery = "Enterprise.EnrollmentRecovery";
const char* const kMetricEnrollmentConfiguration =
"Enterprise.EnrollmentConfiguration";
} // namespace
......@@ -68,6 +70,9 @@ void EnrollmentUMA(policy::MetricEnrollment sample,
case policy::EnrollmentConfig::MODE_ENROLLED_ROLLBACK:
base::UmaHistogramSparse(kMetricEnrollmentRecovery, sample);
break;
case policy::EnrollmentConfig::MODE_ATTESTATION_ENROLLMENT_TOKEN:
base::UmaHistogramSparse(kMetricEnrollmentConfiguration, sample);
break;
case policy::EnrollmentConfig::MODE_NONE:
NOTREACHED();
break;
......
......@@ -115,10 +115,17 @@ class EnterpriseEnrollmentHelper {
bool fetch_additional_token) = 0;
// Starts enterprise enrollment using |token|.
// This flow is used when enrollment is controlled by the paired device.
// EnrollUsingToken can be called only once during this object's lifetime, and
// only if none of the EnrollUsing* was called before.
virtual void EnrollUsingToken(const std::string& token) = 0;
// Starts enterprise enrollment using enrollment |token| for authentication.
// This flow is used in OOBE configuration flow.
// EnrollUsingWorkflowToken can be called only once during this object's
// lifetime, and only if none of the EnrollUsing* was called before.
virtual void EnrollUsingEnrollmentToken(const std::string& token) = 0;
// Starts enterprise enrollment using PCA attestation.
// EnrollUsingAttestation can be called only once during the object's
// lifetime, and only if none of the EnrollUsing* was called before.
......
......@@ -122,6 +122,13 @@ void EnterpriseEnrollmentHelperImpl::EnrollUsingAttestation() {
DoEnroll(policy::DMAuth::NoAuth());
}
void EnterpriseEnrollmentHelperImpl::EnrollUsingEnrollmentToken(
const std::string& token) {
CHECK_EQ(enrollment_config_.mode,
policy::EnrollmentConfig::MODE_ATTESTATION_ENROLLMENT_TOKEN);
DoEnroll(policy::DMAuth::FromEnrollmentToken(token));
}
void EnterpriseEnrollmentHelperImpl::EnrollForOfflineDemo() {
CHECK_EQ(enrollment_config_.mode,
policy::EnrollmentConfig::MODE_OFFLINE_DEMO);
......
......@@ -42,6 +42,7 @@ class EnterpriseEnrollmentHelperImpl
void EnrollUsingAuthCode(const std::string& auth_code,
bool fetch_additional_token) override;
void EnrollUsingToken(const std::string& token) override;
void EnrollUsingEnrollmentToken(const std::string& token) override;
void EnrollUsingAttestation() override;
void EnrollForOfflineDemo() override;
void RestoreAfterRollback() override;
......
......@@ -25,6 +25,7 @@ class EnterpriseEnrollmentHelperMock : public EnterpriseEnrollmentHelper {
MOCK_METHOD2(EnrollUsingAuthCode,
void(const std::string& auth_code, bool fetch_additional_token));
MOCK_METHOD1(EnrollUsingToken, void(const std::string& token));
MOCK_METHOD1(EnrollUsingEnrollmentToken, void(const std::string& token));
MOCK_METHOD0(EnrollUsingAttestation, void());
MOCK_METHOD0(EnrollForOfflineDemo, void());
MOCK_METHOD0(RestoreAfterRollback, void());
......
......@@ -62,6 +62,10 @@ struct EnrollmentConfig {
// Forced enrollment triggered as a fallback to attestation initial
// enrollment, user can't skip.
MODE_ATTESTATION_INITIAL_MANUAL_FALLBACK,
// Attestation-based enrollment with enrollment token, used in configuration
// based OOBE.
MODE_ATTESTATION_ENROLLMENT_TOKEN,
};
// An enumeration of authentication mechanisms that can be used for
......@@ -122,6 +126,7 @@ struct EnrollmentConfig {
// Whether this configuration is in attestation mode.
bool is_mode_attestation() const {
return mode == MODE_ATTESTATION || mode == MODE_ATTESTATION_LOCAL_FORCED ||
mode == MODE_ATTESTATION_ENROLLMENT_TOKEN ||
is_mode_attestation_server();
}
......
......@@ -93,6 +93,9 @@ em::DeviceRegisterRequest::Flavor EnrollmentModeToRegistrationFlavor(
case EnrollmentConfig::MODE_ATTESTATION_INITIAL_MANUAL_FALLBACK:
return em::DeviceRegisterRequest::
FLAVOR_ENROLLMENT_ATTESTATION_INITIAL_MANUAL_FALLBACK;
case EnrollmentConfig::MODE_ATTESTATION_ENROLLMENT_TOKEN:
return em::DeviceRegisterRequest::
FLAVOR_ENROLLMENT_ATTESTATION_USB_ENROLLMENT;
}
NOTREACHED() << "Bad enrollment mode: " << mode;
......@@ -187,9 +190,13 @@ EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS(
dm_auth_ = std::move(dm_auth);
CHECK(!client_->is_registered());
CHECK_EQ(DM_STATUS_SUCCESS, client_->status());
CHECK((enrollment_config_.is_mode_attestation() ||
enrollment_config.mode == EnrollmentConfig::MODE_OFFLINE_DEMO) ==
dm_auth_->empty());
if (enrollment_config_.is_mode_attestation()) {
CHECK(dm_auth_->empty() || dm_auth_->has_enrollment_token());
} else if (enrollment_config.mode == EnrollmentConfig::MODE_OFFLINE_DEMO) {
CHECK(dm_auth_->empty());
} else {
CHECK(!dm_auth_->empty());
}
CHECK_NE(enrollment_config.mode == EnrollmentConfig::MODE_OFFLINE_DEMO,
enrollment_config.offline_policy_path.empty());
CHECK(enrollment_config_.auth_mechanism !=
......@@ -455,7 +462,8 @@ void EnrollmentHandlerChromeOS::HandleRegistrationCertificateResult(
em::DeviceRegisterRequest::DEVICE,
EnrollmentModeToRegistrationFlavor(enrollment_config_.mode),
em::DeviceRegisterRequest::LIFETIME_INDEFINITE, license_type_,
pem_certificate_chain, client_id_, requisition_, current_state_key_);
dm_auth_->Clone(), pem_certificate_chain, client_id_, requisition_,
current_state_key_);
} else {
ReportResult(EnrollmentStatus::ForStatus(
EnrollmentStatus::REGISTRATION_CERT_FETCH_FAILED));
......
......@@ -83,6 +83,7 @@ std::string EnrollmentModeToUIMode(policy::EnrollmentConfig::Mode mode) {
case policy::EnrollmentConfig::MODE_INITIAL_SERVER_FORCED:
case policy::EnrollmentConfig::MODE_ATTESTATION_INITIAL_SERVER_FORCED:
case policy::EnrollmentConfig::MODE_ATTESTATION_INITIAL_MANUAL_FALLBACK:
case policy::EnrollmentConfig::MODE_ATTESTATION_ENROLLMENT_TOKEN:
return kEnrollmentModeUIForced;
case policy::EnrollmentConfig::MODE_RECOVERY:
case policy::EnrollmentConfig::MODE_ENROLLED_ROLLBACK:
......
......@@ -254,6 +254,7 @@ void CloudPolicyClient::RegisterWithCertificate(
em::DeviceRegisterRequest::Flavor flavor,
em::DeviceRegisterRequest::Lifetime lifetime,
em::LicenseType::LicenseTypeEnum license_type,
std::unique_ptr<DMAuth> auth,
const std::string& pem_certificate_chain,
const std::string& client_id,
const std::string& requisition,
......@@ -288,9 +289,10 @@ void CloudPolicyClient::RegisterWithCertificate(
request->mutable_license_type()->set_license_type(license_type);
request->set_lifetime(lifetime);
signing_service_->SignData(data.SerializeAsString(),
signing_service_->SignData(
data.SerializeAsString(),
base::Bind(&CloudPolicyClient::OnRegisterWithCertificateRequestSigned,
weak_ptr_factory_.GetWeakPtr()));
weak_ptr_factory_.GetWeakPtr(), base::Passed(&auth)));
}
void CloudPolicyClient::RegisterWithToken(const std::string& token,
......@@ -323,7 +325,9 @@ void CloudPolicyClient::RegisterWithToken(const std::string& token,
weak_ptr_factory_.GetWeakPtr()));
}
void CloudPolicyClient::OnRegisterWithCertificateRequestSigned(bool success,
void CloudPolicyClient::OnRegisterWithCertificateRequestSigned(
std::unique_ptr<DMAuth> auth,
bool success,
em::SignedData signed_data) {
if (!success) {
const em::DeviceManagementResponse response;
......@@ -335,7 +339,7 @@ void CloudPolicyClient::OnRegisterWithCertificateRequestSigned(bool success,
DeviceManagementRequestJob::TYPE_CERT_BASED_REGISTRATION,
GetURLLoaderFactory()));
policy_fetch_request_job_->SetClientID(client_id_);
policy_fetch_request_job_->SetAuthData(DMAuth::NoAuth());
policy_fetch_request_job_->SetAuthData(std::move(auth));
em::SignedData* signed_request = policy_fetch_request_job_->GetRequest()->
mutable_certificate_based_register_request()->mutable_signed_request();
signed_request->set_data(signed_data.data());
......
......@@ -146,6 +146,7 @@ class POLICY_EXPORT CloudPolicyClient {
enterprise_management::DeviceRegisterRequest::Flavor flavor,
enterprise_management::DeviceRegisterRequest::Lifetime lifetime,
enterprise_management::LicenseType::LicenseTypeEnum license_type,
std::unique_ptr<DMAuth> auth,
const std::string& pem_certificate_chain,
const std::string& client_id,
const std::string& requisition,
......@@ -390,7 +391,9 @@ class POLICY_EXPORT CloudPolicyClient {
void OnRetryRegister(DeviceManagementRequestJob* job);
// Callback for siganture of requests.
void OnRegisterWithCertificateRequestSigned(bool success,
void OnRegisterWithCertificateRequestSigned(
std::unique_ptr<DMAuth> auth,
bool success,
enterprise_management::SignedData signed_data);
// Callback for registration requests.
......
......@@ -663,8 +663,8 @@ TEST_F(CloudPolicyClientTest, RegistrationWithCertificateAndPolicyFetch) {
em::DeviceRegisterRequest::DEVICE,
em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_ATTESTATION,
em::DeviceRegisterRequest::LIFETIME_INDEFINITE,
em::LicenseType::UNDEFINED, kEnrollmentCertificate, std::string(),
std::string(), std::string());
em::LicenseType::UNDEFINED, DMAuth::NoAuth(), kEnrollmentCertificate,
std::string(), std::string(), std::string());
EXPECT_TRUE(client_->is_registered());
EXPECT_FALSE(client_->GetPolicyFor(policy_type_, std::string()));
EXPECT_EQ(DM_STATUS_SUCCESS, client_->status());
......@@ -683,8 +683,8 @@ TEST_F(CloudPolicyClientTest, RegistrationWithCertificateFailToSignRequest) {
em::DeviceRegisterRequest::DEVICE,
em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_ATTESTATION,
em::DeviceRegisterRequest::LIFETIME_INDEFINITE,
em::LicenseType::UNDEFINED, kEnrollmentCertificate, std::string(),
std::string(), std::string());
em::LicenseType::UNDEFINED, DMAuth::NoAuth(), kEnrollmentCertificate,
std::string(), std::string(), std::string());
EXPECT_FALSE(client_->is_registered());
EXPECT_EQ(DM_STATUS_CANNOT_SIGN_REQUEST, client_->status());
}
......
......@@ -25753,6 +25753,15 @@ uploading your change for review.
</summary>
</histogram>
<histogram name="Enterprise.EnrollmentConfiguration"
enum="EnterpriseEnrollmentType">
<owner>antrim@chromium.org</owner>
<summary>
Events related to Chrome OS enterprise enrollment automated by OOBE
configuration.
</summary>
</histogram>
<histogram name="Enterprise.EnrollmentForced" enum="EnterpriseEnrollmentType">
<owner>tnagel@chromium.org</owner>
<summary>
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