in source/fleetprovisioning/FleetProvisioning.cpp [204:362]
bool FleetProvisioning::CreateCertificateUsingCSR(Iotidentity::IotIdentityClient identityClient)
{
LOG_INFO(TAG, "Provisioning new device certificate using CreateCertificateFromCsr API");
auto onCsrAcceptedSubAck = [&](int ioErr) {
if (ioErr != AWS_OP_SUCCESS)
{
LOGM_ERROR(
TAG,
"*** %s: Error subscribing to CreateCertificateFromCsr accepted topic: %s. ***",
DeviceClient::DC_FATAL_ERROR,
ErrorDebugString(ioErr));
}
csrAcceptedCompletedPromise.set_value(ioErr == AWS_OP_SUCCESS);
};
auto onCsrRejectedSubAck = [&](int ioErr) {
if (ioErr != AWS_OP_SUCCESS)
{
LOGM_ERROR(
TAG,
"*** %s: Error subscribing to CreateCertificateFromCsr rejected topic: %s. ***",
DeviceClient::DC_FATAL_ERROR,
ErrorDebugString(ioErr));
}
csrRejectedCompletedPromise.set_value(ioErr == AWS_OP_SUCCESS);
};
auto onCsrPublishSubAck = [&](int ioErr) {
if (ioErr != AWS_OP_SUCCESS)
{
LOGM_ERROR(
TAG,
"*** %s: Error publishing to CreateCertificateFromCsr topic: %s. ***",
DeviceClient::DC_FATAL_ERROR,
ErrorDebugString(ioErr));
}
csrPublishCompletedPromise.set_value(ioErr == AWS_OP_SUCCESS);
};
auto onCsrAccepted = [&](CreateCertificateFromCsrResponse *response, int ioErr) {
if (ioErr == AWS_OP_SUCCESS)
{
LOGM_INFO(TAG, "CreateCertificateFromCsrResponse certificateId: %s. ***", response->CertificateId->c_str());
certificateOwnershipToken = *response->CertificateOwnershipToken;
Aws::Crt::String certificateID = response->CertificateId->c_str();
ostringstream certPathStream;
certPathStream << keyDir << certificateID << "-certificate.pem.crt";
certPath = FileUtils::ExtractExpandedPath(certPathStream.str().c_str()).c_str();
if (FileUtils::StoreValueInFile(response->CertificatePem->c_str(), certPath.c_str()))
{
LOGM_INFO(TAG, "Stored certificate in %s file", certPath.c_str());
LOG_INFO(TAG, "Attempting to set permissions for certificate...");
chmod(certPath.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (FileUtils::ValidateFilePermissions(certPath.c_str(), Permissions::PUBLIC_CERT))
{
LOG_INFO(TAG, "Successfully set permissions on provisioned public certificate");
csrCreationCompletedPromise.set_value(true);
}
else
{
csrCreationCompletedPromise.set_value(false);
}
}
else
{
LOGM_ERROR(TAG, "Failed to store public certificate in file %s", certPath.c_str());
csrCreationCompletedPromise.set_value(false);
}
}
else
{
LOGM_ERROR(
TAG,
"*** %s: Error on CreateCertificateFromCsr subscription: %s. ***",
DeviceClient::DC_FATAL_ERROR,
ErrorDebugString(ioErr));
csrCreationCompletedPromise.set_value(false);
}
};
auto onCsrRejected = [&](ErrorResponse *error, int ioErr) {
if (ioErr == AWS_OP_SUCCESS)
{
LOGM_ERROR(
TAG,
"*** %s: CreateCertificateFromCsr failed with statusCode %d, errorMessage %s and errorCode %s. ***",
DeviceClient::DC_FATAL_ERROR,
*error->StatusCode,
error->ErrorMessage->c_str(),
error->ErrorCode->c_str());
}
else
{
LOGM_ERROR(
TAG,
"*** %s: Error on subscription to CreateCertificateFromCsr Rejected topic: %s. ***",
DeviceClient::DC_FATAL_ERROR,
ErrorDebugString(ioErr));
}
csrCreationCompletedPromise.set_value(false);
};
/*
* CreateCertificateFromCSR workflow
*/
LOG_INFO(TAG, "Subscribing to CreateCertificateFromCsr Accepted and Rejected topics");
CreateCertificateFromCsrSubscriptionRequest csrSubscriptionRequest;
identityClient.SubscribeToCreateCertificateFromCsrAccepted(
csrSubscriptionRequest, AWS_MQTT_QOS_AT_LEAST_ONCE, onCsrAccepted, onCsrAcceptedSubAck);
identityClient.SubscribeToCreateCertificateFromCsrRejected(
csrSubscriptionRequest, AWS_MQTT_QOS_AT_LEAST_ONCE, onCsrRejected, onCsrRejectedSubAck);
auto futureValCsrAcceptedCompletedPromise = csrAcceptedCompletedPromise.get_future();
auto futureValCsrRejectedCompletedPromise = csrRejectedCompletedPromise.get_future();
if (futureValCsrAcceptedCompletedPromise.wait_for(std::chrono::seconds(DEFAULT_WAIT_TIME_SECONDS)) ==
future_status::timeout ||
futureValCsrRejectedCompletedPromise.wait_for(std::chrono::seconds(DEFAULT_WAIT_TIME_SECONDS)) ==
future_status::timeout)
{
LOGM_ERROR(
TAG,
"*** %s: Subscribing to CreateCertificateFromCsr Accepted and Rejected topics timed out. ***",
DeviceClient::DC_FATAL_ERROR);
return false;
}
if (!futureValCsrAcceptedCompletedPromise.get() || !futureValCsrRejectedCompletedPromise.get())
{
return false;
}
LOG_INFO(TAG, "Publishing to CreateCertificateFromCsr topic");
CreateCertificateFromCsrRequest createCertificateFromCsrRequest;
createCertificateFromCsrRequest.CertificateSigningRequest = csrFile.c_str();
identityClient.PublishCreateCertificateFromCsr(
createCertificateFromCsrRequest, AWS_MQTT_QOS_AT_LEAST_ONCE, onCsrPublishSubAck);
auto futureValCsrPublishCompletedPromise = csrPublishCompletedPromise.get_future();
auto futureValCsrCreationCompletedPromise = csrCreationCompletedPromise.get_future();
if (futureValCsrPublishCompletedPromise.wait_for(std::chrono::seconds(DEFAULT_WAIT_TIME_SECONDS)) ==
future_status::timeout)
{
LOGM_ERROR(
TAG, "*** %s: Publishing to CreateCertificateFromCsr topic timed out. ***", DeviceClient::DC_FATAL_ERROR);
return false;
}
if (futureValCsrCreationCompletedPromise.wait_for(std::chrono::seconds(DEFAULT_WAIT_TIME_SECONDS)) ==
future_status::timeout)
{
LOGM_ERROR(TAG, "*** %s: CreateCertificateFromCsr request timed out. ***", DeviceClient::DC_FATAL_ERROR);
return false;
}
return futureValCsrPublishCompletedPromise.get() && futureValCsrCreationCompletedPromise.get();
}