1 #include "aktualizr_secondary.h"
3 #include "crypto/keymanager.h"
4 #include "logging/logging.h"
5 #include "update_agent.h"
6 #include "uptane/manifest.h"
7 #include "utilities/utils.h"
13 std::shared_ptr<KeyManager> key_mngr, std::shared_ptr<UpdateAgent> update_agent)
14 : config_(std::move(config)),
15 storage_(std::move(storage)),
16 keys_(std::move(key_mngr)),
17 update_agent_(std::move(update_agent)) {
19 manifest_issuer_ = std::make_shared<Uptane::ManifestIssuer>(keys_, ecu_serial_);
20 initPendingTargetIfAny();
22 if (hasPendingUpdate()) {
25 std::vector<Uptane::Target> installed_versions;
26 boost::optional<Uptane::Target> pending_target;
27 storage_->loadInstalledVersions(ecu_serial_.ToString(),
nullptr, &pending_target);
29 if (!!pending_target) {
32 LOG_INFO <<
"Pending update found; attempting to apply it. Target hash: " << pending_target->sha256Hash();
34 install_res = update_agent_->applyPendingInstall(*pending_target);
36 if (install_res.result_code != data::ResultCode::Numeric::kNeedCompletion) {
37 storage_->saveEcuInstallationResult(ecu_serial_, install_res);
39 if (install_res.success) {
40 LOG_INFO <<
"Pending update has been successfully applied: " << pending_target->sha256Hash();
41 storage_->saveInstalledVersion(ecu_serial_.ToString(), *pending_target, InstalledVersionUpdateMode::kCurrent);
43 LOG_ERROR <<
"Application of the pending update has failed: (" << install_res.result_code.toString() <<
")"
44 << install_res.description;
45 storage_->saveInstalledVersion(ecu_serial_.ToString(), *pending_target, InstalledVersionUpdateMode::kNone);
48 director_repo_.dropTargets(*storage_);
50 LOG_INFO <<
"Pending update hasn't been applied because a reboot hasn't been detected";
60 PublicKey AktualizrSecondary::getPublicKey()
const {
return keys_->UptanePublicKey(); }
65 if (update_agent_->getInstalledImageInfo(installed_image_info)) {
66 manifest = manifest_issuer_->assembleAndSignManifest(installed_image_info);
72 int32_t AktualizrSecondary::getRootVersion(
bool director)
const {
73 std::string root_meta;
74 if (!storage_->loadLatestRoot(&root_meta,
75 (director) ? Uptane::RepositoryType::Director() : Uptane::RepositoryType::Image())) {
76 LOG_ERROR <<
"Could not load root metadata";
80 return Uptane::extractVersionUntrusted(root_meta);
83 bool AktualizrSecondary::putRoot(
const std::string& root,
bool director) {
86 LOG_ERROR <<
"putRootResp is not implemented yet";
90 bool AktualizrSecondary::putMetadata(
const Metadata& metadata) {
return doFullVerification(metadata); }
92 bool AktualizrSecondary::sendFirmware(
const std::string& firmware) {
93 if (!pending_target_.IsValid()) {
94 LOG_ERROR <<
"Aborting image download/receiving; no valid target found.";
98 if (!update_agent_->download(pending_target_, firmware)) {
99 LOG_ERROR <<
"Failed to pull/store an update data";
100 pending_target_ = Uptane::Target::Unknown();
108 if (!pending_target_.IsValid()) {
109 LOG_ERROR <<
"Aborting target image installation; no valid target found.";
113 if (pending_target_.filename() != target_name) {
114 LOG_ERROR <<
"name of the target to install and a name of the pending target do not match";
118 auto install_result = update_agent_->install(pending_target_);
120 switch (install_result) {
121 case data::ResultCode::Numeric::kOk: {
122 storage_->saveInstalledVersion(ecu_serial_.ToString(), pending_target_, InstalledVersionUpdateMode::kCurrent);
123 pending_target_ = Uptane::Target::Unknown();
124 LOG_INFO <<
"The target has been successfully installed: " << target_name;
127 case data::ResultCode::Numeric::kNeedCompletion: {
128 storage_->saveInstalledVersion(ecu_serial_.ToString(), pending_target_, InstalledVersionUpdateMode::kPending);
129 LOG_INFO <<
"The target has been successfully installed, but a reboot is required to be applied: " << target_name;
132 default: { LOG_INFO <<
"Failed to install the target: " << target_name; }
135 return install_result;
138 bool AktualizrSecondary::doFullVerification(
const Metadata& metadata) {
162 if (!director_repo_.updateMeta(*storage_, metadata)) {
163 LOG_ERROR <<
"Failed to update director metadata: " << director_repo_.getLastException().what();
174 if (!image_repo_.updateMeta(*storage_, metadata)) {
175 LOG_ERROR <<
"Failed to update image metadata: " << image_repo_.getLastException().what();
180 if (!director_repo_.matchTargetsWithImageTargets(*(image_repo_.getTargets()))) {
181 LOG_ERROR <<
"Targets metadata from the Director and Image repositories DOES NOT match ";
185 auto targetsForThisEcu = director_repo_.getTargets(getSerial(), getHwId());
187 if (targetsForThisEcu.size() != 1) {
188 LOG_ERROR <<
"Invalid number of targets (should be 1): " << targetsForThisEcu.size();
192 if (!update_agent_->isTargetSupported(targetsForThisEcu[0])) {
193 LOG_ERROR <<
"The given target type is not supported: " << targetsForThisEcu[0].type();
197 pending_target_ = targetsForThisEcu[0];
202 void AktualizrSecondary::uptaneInitialize() {
203 if (keys_->generateUptaneKeyPair().size() == 0) {
204 throw std::runtime_error(
"Failed to generate uptane key pair");
208 EcuSerials ecu_serials;
210 if (storage_->loadEcuSerials(&ecu_serials)) {
211 ecu_serial_ = ecu_serials[0].first;
212 hardware_id_ = ecu_serials[0].second;
216 std::string ecu_serial_local = config_.uptane.ecu_serial;
217 if (ecu_serial_local.empty()) {
218 ecu_serial_local = keys_->UptanePublicKey().KeyId();
221 std::string ecu_hardware_id = config_.uptane.ecu_hardware_id;
222 if (ecu_hardware_id.empty()) {
223 ecu_hardware_id = Utils::getHostname();
224 if (ecu_hardware_id ==
"") {
225 throw std::runtime_error(
"Failed to define ECU hardware ID");
230 storage_->storeEcuSerials(ecu_serials);
231 ecu_serial_ = ecu_serials[0].first;
232 hardware_id_ = ecu_serials[0].second;
242 storage_->importInstalledVersions(config_.import.base_path);
245 void AktualizrSecondary::initPendingTargetIfAny() {
246 if (!director_repo_.checkMetaOffline(*storage_)) {
247 LOG_INFO <<
"No any valid and pending director's targets to be applied";
251 auto targetsForThisEcu = director_repo_.getTargets(ecu_serial_, hardware_id_);
253 if (targetsForThisEcu.size() != 1) {
254 LOG_ERROR <<
"Invalid number of targets (should be 1): " << targetsForThisEcu.size();
258 if (!update_agent_->isTargetSupported(targetsForThisEcu[0])) {
259 LOG_ERROR <<
"The given target type is not supported: " << targetsForThisEcu[0].type();
263 LOG_INFO <<
"There is a valid and pending director's target to be applied";
264 pending_target_ = targetsForThisEcu[0];