AttestationResult TpmCertOperations::RenewAndReplaceAkCert()

in client-library/src/Attestation/AttestationClient/lib/TpmCertOperations.cpp [115:230]


AttestationResult TpmCertOperations::RenewAndReplaceAkCert() {
	AttestationResult result = AttestationResult(AttestationResult::ErrorCode::SUCCESS);

	try {
		ImdsClient imds;
		std::string vm_id = imds.GetVmId();
		if (vm_id.empty()) {
			CLIENT_LOG_ERROR("Failed to get vm id");
			if(telemetry_reporting.get() != nullptr) {
        		telemetry_reporting->UpdateEvent("AkRenew", 
													"Failed to get vm id", 
													TelemetryReportingBase::EventLevel::AK_RENEW_EMPTY_VM_ID);
			}

			result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
			result.description_ = "Failed to get VM id from IMDS";
			return result;
		}

		Tpm tpm;
		std::string request_id = attest::utils::Uuid();
		std::string ak_cert;
		if ((result = ReadAkCertFromTpm(ak_cert)).code_ != AttestationResult::ErrorCode::SUCCESS) {
			CLIENT_LOG_ERROR("Failed to read AK Cert from TPM");
			return result;
		}

		std::string ak_cert_renew_response = imds.RenewAkCert(ak_cert, vm_id, request_id, ak_renew_sync_api_version);
		if (telemetry_reporting.get() != nullptr) {
			telemetry_reporting->UpdateEvent("AkRenew",
												ak_cert_renew_response, TelemetryReportingBase::EventLevel::AK_RENEW_RESPONSE);
		}

		std::string renewed_cert = std::string();
		if (!ak_cert_renew_response.empty()) {
			if (telemetry_reporting.get() != nullptr) {
				telemetry_reporting->UpdateEvent("AkRenew",
												"Successfully retrived AkCert response from Thim",
												TelemetryReportingBase::EventLevel::AK_RENEW_GET_RESPONSE_SUCCESS);
			}
		
			renewed_cert = ParseAndGetAkCert(ak_cert_renew_response);
		
			if (renewed_cert.empty()) {
				CLIENT_LOG_ERROR("Failed to get AkCertPem from response.");
				if (telemetry_reporting.get() != nullptr) {
					telemetry_reporting->UpdateEvent("AkRenew", 
													"Failed to get AkCertPem from response", 
													TelemetryReportingBase::EventLevel::AK_RENEW_RESPONSE_PARSING_FAILURE);
				}
				result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
				result.description_ = "Failed to get AkCert Pem from response";
				return result;
			}

		} else {
			CLIENT_LOG_ERROR("Failed to renew Ak cert using sync api");
			if(telemetry_reporting.get() != nullptr) {
        		telemetry_reporting->UpdateEvent("AkRenew", 
													"Failed to renew Ak Cert using sync api", 
													TelemetryReportingBase::EventLevel::AK_RENEW_EMPTY_CERT_RESPONSE);
			}

			CLIENT_LOG_INFO("Retrying Ak renew using async api");
			request_id = attest::utils::Uuid();
			ak_cert_renew_response = imds.RenewAkCert(ak_cert, vm_id, request_id, ak_renew_async_api_version);

			// sleep for 60 seconds
			std::this_thread::sleep_for(std::chrono::seconds(QUERY_RENEWED_CERT_AFTER_SECONDS));
			request_id = attest::utils::Uuid();
			renewed_cert = imds.QueryAkCert(ak_cert_renew_response, vm_id, request_id);
			if (renewed_cert.empty()) {
				CLIENT_LOG_INFO("Failed to query Ak cert using async api");
				if(telemetry_reporting.get() != nullptr) {
        			telemetry_reporting->UpdateEvent("AkRenew", 
														"Failed to query Ak Cert using async api", 
														TelemetryReportingBase::EventLevel::AK_RENEW_EMPTY_RENEWED_CERT);
				}
				
				result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
				result.description_ = "Failed to query Ak cert using async api";
				return result;
			}
		}

		if (telemetry_reporting.get() != nullptr) {
			telemetry_reporting->UpdateEvent("AkRenew", 
											renewed_cert, 
											TelemetryReportingBase::EventLevel::AK_RENEWED_CERT);
		}

		// write renewed cert to TPM
		std::vector<unsigned char> cert_der = attest::base64::base64_to_binary(
			RemoveCertHeaderAndFooter(renewed_cert));
		tpm.WriteAikCert(cert_der);
		CLIENT_LOG_INFO("Successfully renewed AK cert");
		if(telemetry_reporting.get() != nullptr) {
        	telemetry_reporting->UpdateEvent("AkRenew", 
												"Successfully renewed Ak Cert", 
												TelemetryReportingBase::EventLevel::AK_RENEW_SUCCESS);
		}
	}
	catch (const std::exception& e) {
		CLIENT_LOG_ERROR("Unexpected error occured in RenewAndReplaceAkCert method %s", e.what());
		if(telemetry_reporting.get() != nullptr) {
        	telemetry_reporting->UpdateEvent("AkRenew", 
												"Unexpted Error in RenewAndReplaceAkCert", 
												TelemetryReportingBase::EventLevel::AK_RENEW_UNEXPECTED_ERROR);
		}
		
		result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
		result.description_ = "Unexpected erropr in RenewAndReplaceAkCert";
	}

	return result;
}