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" 14 storage_(
std::move(storage)),
15 keys_(
std::make_shared<
KeyManager>(storage_, config_.keymanagerConfig())) {
17 manifest_issuer_ = std::make_shared<Uptane::ManifestIssuer>(keys_, ecu_serial_);
21 PublicKey AktualizrSecondary::publicKey()
const {
return keys_->UptanePublicKey(); }
27 if (getInstalledImageInfo(installed_image_info)) {
28 manifest = manifest_issuer_->assembleAndSignManifest(installed_image_info);
35 return doFullVerification(metadata);
39 if (!pending_target_.IsValid()) {
40 LOG_ERROR <<
"Aborting target image installation; no valid target found.";
42 "Aborting target image installation; no valid target found.");
45 auto target_name = pending_target_.filename();
46 auto result = installPendingTarget(pending_target_);
48 switch (
result.result_code.num_code) {
49 case data::ResultCode::Numeric::kOk: {
50 storage_->saveInstalledVersion(ecu_serial_.ToString(), pending_target_, InstalledVersionUpdateMode::kCurrent);
51 pending_target_ = Uptane::Target::Unknown();
52 LOG_INFO <<
"The target has been successfully installed: " << target_name;
55 case data::ResultCode::Numeric::kNeedCompletion: {
56 storage_->saveInstalledVersion(ecu_serial_.ToString(), pending_target_, InstalledVersionUpdateMode::kPending);
57 LOG_INFO <<
"The target has been successfully installed, but a reboot is required to be applied: " << target_name;
61 LOG_INFO <<
"Failed to install the target: " << target_name;
80 director_repo_.updateMeta(*storage_, metadata);
81 }
catch (
const std::exception& e) {
82 LOG_ERROR <<
"Failed to update Director metadata: " << e.what();
84 std::string(
"Failed to update Director metadata: ") + e.what());
92 image_repo_.updateMeta(*storage_, metadata);
93 }
catch (
const std::exception& e) {
94 LOG_ERROR <<
"Failed to update Image repo metadata: " << e.what();
96 std::string(
"Failed to update Image repo metadata: ") + e.what());
100 if (!director_repo_.matchTargetsWithImageTargets(*(image_repo_.getTargets()))) {
101 LOG_ERROR <<
"Targets metadata from the Director and Image repositories do not match";
103 "Targets metadata from the Director and Image repositories do not match");
106 auto targetsForThisEcu = director_repo_.getTargets(serial(), hwID());
108 if (targetsForThisEcu.size() != 1) {
109 LOG_ERROR <<
"Invalid number of targets (should be 1): " << targetsForThisEcu.size();
112 "Invalid number of targets (should be 1): " + std::to_string(targetsForThisEcu.size()));
115 if (!isTargetSupported(targetsForThisEcu[0])) {
116 LOG_ERROR <<
"The given target type is not supported: " << targetsForThisEcu[0].type();
118 "The given target type is not supported: " + targetsForThisEcu[0].type());
121 pending_target_ = targetsForThisEcu[0];
123 LOG_DEBUG <<
"Metadata verified, new update found.";
127 void AktualizrSecondary::uptaneInitialize() {
128 if (keys_->generateUptaneKeyPair().size() == 0) {
129 throw std::runtime_error(
"Failed to generate Uptane key pair");
133 EcuSerials ecu_serials;
135 if (storage_->loadEcuSerials(&ecu_serials)) {
136 ecu_serial_ = ecu_serials[0].first;
137 hardware_id_ = ecu_serials[0].second;
141 std::string ecu_serial_local = config_.uptane.ecu_serial;
142 if (ecu_serial_local.empty()) {
143 ecu_serial_local = keys_->UptanePublicKey().KeyId();
146 std::string ecu_hardware_id = config_.uptane.ecu_hardware_id;
147 if (ecu_hardware_id.empty()) {
148 ecu_hardware_id = Utils::getHostname();
149 if (ecu_hardware_id ==
"") {
150 throw std::runtime_error(
"Failed to define ECU hardware ID");
155 storage_->storeEcuSerials(ecu_serials);
156 ecu_serial_ = ecu_serials[0].first;
157 hardware_id_ = ecu_serials[0].second;
167 storage_->importInstalledVersions(config_.import.base_path);
170 void AktualizrSecondary::initPendingTargetIfAny() {
172 director_repo_.checkMetaOffline(*storage_);
173 }
catch (
const std::exception& e) {
174 LOG_INFO <<
"No valid metadata found in storage.";
178 auto targetsForThisEcu = director_repo_.getTargets(ecu_serial_, hardware_id_);
180 if (targetsForThisEcu.size() != 1) {
181 LOG_ERROR <<
"Invalid number of targets (should be 1): " << targetsForThisEcu.size();
185 if (!isTargetSupported(targetsForThisEcu[0])) {
186 LOG_ERROR <<
"The given target type is not supported: " << targetsForThisEcu[0].type();
190 pending_target_ = targetsForThisEcu[0];
193 void AktualizrSecondary::registerHandlers() {
194 registerHandler(AKIpUptaneMes_PR_getInfoReq,
195 std::bind(&AktualizrSecondary::getInfoHdlr,
this, std::placeholders::_1, std::placeholders::_2));
197 registerHandler(AKIpUptaneMes_PR_versionReq,
198 std::bind(&AktualizrSecondary::versionHdlr,
this, std::placeholders::_1, std::placeholders::_2));
200 registerHandler(AKIpUptaneMes_PR_manifestReq,
201 std::bind(&AktualizrSecondary::getManifestHdlr,
this, std::placeholders::_1, std::placeholders::_2));
203 registerHandler(AKIpUptaneMes_PR_putMetaReq2,
204 std::bind(&AktualizrSecondary::putMetaHdlr,
this, std::placeholders::_1, std::placeholders::_2));
206 registerHandler(AKIpUptaneMes_PR_installReq,
207 std::bind(&AktualizrSecondary::installHdlr,
this, std::placeholders::_1, std::placeholders::_2));
213 out_msg.present(AKIpUptaneMes_PR_getInfoResp);
214 auto info_resp = out_msg.getInfoResp();
216 SetString(&info_resp->ecuSerial, serial().ToString());
217 SetString(&info_resp->hwId, hwID().ToString());
218 info_resp->keyType =
static_cast<AKIpUptaneKeyType_t
>(publicKey().Type());
219 SetString(&info_resp->key, publicKey().Value());
221 return ReturnCode::kOk;
225 const uint32_t version = 2;
226 auto version_req = in_msg.versionReq();
227 const auto primary_version =
static_cast<uint32_t
>(version_req->version);
228 if (primary_version < version) {
229 LOG_ERROR <<
"Primary protocol version is " << primary_version <<
" but Secondary version is " << version
230 <<
"! Communication will most likely fail!";
231 }
else if (primary_version > version) {
232 LOG_INFO <<
"Primary protocol version is " << primary_version <<
" but Secondary version is " << version
233 <<
". Please consider upgrading the Secondary.";
236 out_msg.present(AKIpUptaneMes_PR_versionResp);
237 auto version_resp = out_msg.versionResp();
238 version_resp->version = version;
240 return ReturnCode::kOk;
243 AktualizrSecondary::ReturnCode AktualizrSecondary::getManifestHdlr(
Asn1Message& in_msg,
Asn1Message& out_msg) {
246 out_msg.present(AKIpUptaneMes_PR_manifestResp);
247 auto manifest_resp = out_msg.manifestResp();
248 manifest_resp->manifest.present = manifest_PR_json;
249 SetString(&manifest_resp->manifest.choice.json, Utils::jsonToStr(getManifest()));
251 LOG_TRACE <<
"Manifest: \n" << getManifest();
252 return ReturnCode::kOk;
257 auto key = std::make_pair(repo, role);
258 if (meta_bundle.count(key) > 0) {
259 LOG_WARNING << repo.toString() <<
" metadata in contains multiple " << role.ToString() <<
" objects.";
262 meta_bundle.emplace(key, std::move(json));
265 AktualizrSecondary::ReturnCode AktualizrSecondary::putMetaHdlr(
Asn1Message& in_msg,
Asn1Message& out_msg) {
266 auto md = in_msg.putMetaReq2();
267 Uptane::MetaBundle meta_bundle;
269 if (md->directorRepo.present == directorRepo_PR_collection) {
271 const int director_meta_count = md->directorRepo.choice.collection.list.count;
272 for (
int i = 0; i < director_meta_count; i++) {
274 const AKMetaJson_t
object = *md->directorRepo.choice.collection.list.array[i];
275 const std::string role = ToString(
object.role);
276 std::string json = ToString(
object.json);
277 LOG_DEBUG <<
"Received Director repo " << role <<
" metadata:\n" << json;
278 if (role == Uptane::Role::ROOT) {
279 copyMetadata(meta_bundle, Uptane::RepositoryType::Director(), Uptane::Role::Root(), json);
280 }
else if (role == Uptane::Role::TARGETS) {
281 copyMetadata(meta_bundle, Uptane::RepositoryType::Director(), Uptane::Role::Targets(), json);
283 LOG_WARNING <<
"Director metadata in unknown format:" << md->directorRepo.present;
288 if (md->imageRepo.present == imageRepo_PR_collection) {
290 const int image_meta_count = md->imageRepo.choice.collection.list.count;
291 for (
int i = 0; i < image_meta_count; i++) {
293 const AKMetaJson_t
object = *md->imageRepo.choice.collection.list.array[i];
294 const std::string role = ToString(
object.role);
295 std::string json = ToString(
object.json);
296 LOG_DEBUG <<
"Received Image repo " << role <<
" metadata:\n" << json;
297 if (role == Uptane::Role::ROOT) {
298 copyMetadata(meta_bundle, Uptane::RepositoryType::Image(), Uptane::Role::Root(), json);
299 }
else if (role == Uptane::Role::TIMESTAMP) {
300 copyMetadata(meta_bundle, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp(), json);
301 }
else if (role == Uptane::Role::SNAPSHOT) {
302 copyMetadata(meta_bundle, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot(), json);
303 }
else if (role == Uptane::Role::TARGETS) {
304 copyMetadata(meta_bundle, Uptane::RepositoryType::Image(), Uptane::Role::Targets(), json);
306 LOG_WARNING <<
"Image metadata in unknown format:" << md->imageRepo.present;
311 if (meta_bundle.size() != 6) {
312 LOG_WARNING <<
"Metadata received from Primary is incomplete: " << md->imageRepo.present;
317 auto m = out_msg.present(AKIpUptaneMes_PR_putMetaResp2).putMetaResp2();
318 m->result =
static_cast<AKInstallationResultCode_t
>(result.result_code.num_code);
319 SetString(&m->description, result.description);
321 return ReturnCode::kOk;
324 AktualizrSecondary::ReturnCode AktualizrSecondary::installHdlr(
Asn1Message& in_msg,
Asn1Message& out_msg) {
326 auto result = install();
328 auto m = out_msg.present(AKIpUptaneMes_PR_installResp2).installResp2();
329 m->result =
static_cast<AKInstallationResultCode_t
>(result.result_code.num_code);
330 SetString(&m->description, result.description);
332 if (data::ResultCode::Numeric::kNeedCompletion == result.result_code.num_code) {
333 return ReturnCode::kRebootRequired;
336 return ReturnCode::kOk;
Reference counted holder for the top-level ASN1 message structure.
Metadata verification failed.
SWM Internal integrity error.
Results of libaktualizr API calls.