Skip to content

Commit

Permalink
Merge pull request #35 from uptane/virtual-secondary-verification
Browse files Browse the repository at this point in the history
Implement proper metadata verification in ManagedSecondary.
  • Loading branch information
pattivacek authored Nov 5, 2021
2 parents fb5eec7 + 4a7e37e commit 70478f6
Show file tree
Hide file tree
Showing 18 changed files with 213 additions and 206 deletions.
2 changes: 0 additions & 2 deletions src/aktualizr_secondary/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ set(AKTUALIZR_SECONDARY_LIB_SRC
aktualizr_secondary.cc
aktualizr_secondary_config.cc
aktualizr_secondary_file.cc
aktualizr_secondary_metadata.cc
msg_handler.cc
secondary_tcp_server.cc
update_agent_file.cc
Expand Down Expand Up @@ -41,7 +40,6 @@ set(ALL_AKTUALIZR_SECONDARY_HEADERS
aktualizr_secondary.h
aktualizr_secondary_config.h
aktualizr_secondary_file.h
aktualizr_secondary_metadata.h
msg_handler.h
secondary_tcp_server.h
update_agent.h
Expand Down
14 changes: 8 additions & 6 deletions src/aktualizr_secondary/aktualizr_secondary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ Uptane::Manifest AktualizrSecondary::getManifest() const {
return manifest;
}

data::InstallationResult AktualizrSecondary::putMetadata(const Metadata& metadata) { return verifyMetadata(metadata); }
data::InstallationResult AktualizrSecondary::putMetadata(const Uptane::SecondaryMetadata& metadata) {
return verifyMetadata(metadata);
}

data::InstallationResult AktualizrSecondary::install() {
if (!pending_target_.IsValid()) {
Expand Down Expand Up @@ -68,7 +70,7 @@ data::InstallationResult AktualizrSecondary::install() {
return result;
}

data::InstallationResult AktualizrSecondary::verifyMetadata(const Metadata& metadata) {
data::InstallationResult AktualizrSecondary::verifyMetadata(const Uptane::SecondaryMetadata& metadata) {
// 5.4.4.2. Full verification https://uptane.github.io/uptane-standard/uptane-standard.html#metadata_verification

// 1. Load and verify the current time or the most recent securely attested time.
Expand Down Expand Up @@ -364,24 +366,24 @@ AktualizrSecondary::ReturnCode AktualizrSecondary::putRootHdlr(Asn1Message& in_m
} else {
try {
director_repo_.verifyRoot(json);
storage_->storeRoot(json, repo_type, Uptane::Version(director_repo_.rootVersion()));
storage_->clearNonRootMeta(repo_type);
} catch (const std::exception& e) {
LOG_ERROR << "Failed to update Director Root metadata: " << e.what();
result = data::InstallationResult(data::ResultCode::Numeric::kVerificationFailed,
std::string("Failed to update Director Root metadata: ") + e.what());
}
storage_->storeRoot(json, repo_type, Uptane::Version(director_repo_.rootVersion()));
storage_->clearNonRootMeta(repo_type);
}
} else if (repo_type == Uptane::RepositoryType::Image()) {
try {
image_repo_.verifyRoot(json);
storage_->storeRoot(json, repo_type, Uptane::Version(image_repo_.rootVersion()));
storage_->clearNonRootMeta(repo_type);
} catch (const std::exception& e) {
LOG_ERROR << "Failed to update Image repo Root metadata: " << e.what();
result = data::InstallationResult(data::ResultCode::Numeric::kVerificationFailed,
std::string("Failed to update Image repo Root metadata: ") + e.what());
}
storage_->storeRoot(json, repo_type, Uptane::Version(image_repo_.rootVersion()));
storage_->clearNonRootMeta(repo_type);
} else {
LOG_WARNING << "Received Root version request with invalid repo type: " << pr->repotype;
result = data::InstallationResult(
Expand Down
8 changes: 4 additions & 4 deletions src/aktualizr_secondary/aktualizr_secondary.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
#define AKTUALIZR_SECONDARY_H

#include "aktualizr_secondary_config.h"
#include "aktualizr_secondary_metadata.h"
#include "msg_handler.h"
#include "uptane/directorrepository.h"
#include "uptane/imagerepository.h"
#include "uptane/manifest.h"
#include "uptane/secondary_metadata.h"

class UpdateAgent;
class INvStorage;
Expand All @@ -23,9 +23,9 @@ class AktualizrSecondary : public MsgDispatcher {
Uptane::Manifest getManifest() const;
const Uptane::Target& getPendingTarget() const { return pending_target_; }

virtual data::InstallationResult putMetadata(const Metadata& metadata);
virtual data::InstallationResult putMetadata(const Uptane::SecondaryMetadata& metadata);
virtual data::InstallationResult putMetadata(const Uptane::MetaBundle& meta_bundle) {
return putMetadata(Metadata(meta_bundle));
return putMetadata(Uptane::SecondaryMetadata(meta_bundle));
}

virtual data::InstallationResult install();
Expand All @@ -50,7 +50,7 @@ class AktualizrSecondary : public MsgDispatcher {
private:
static void copyMetadata(Uptane::MetaBundle& meta_bundle, Uptane::RepositoryType repo, const Uptane::Role& role,
std::string& json);
data::InstallationResult verifyMetadata(const Metadata& metadata);
data::InstallationResult verifyMetadata(const Uptane::SecondaryMetadata& metadata);
data::InstallationResult findTargets();
void uptaneInitialize();
void registerHandlers();
Expand Down
48 changes: 0 additions & 48 deletions src/aktualizr_secondary/aktualizr_secondary_metadata.cc

This file was deleted.

27 changes: 0 additions & 27 deletions src/aktualizr_secondary/aktualizr_secondary_metadata.h

This file was deleted.

3 changes: 2 additions & 1 deletion src/aktualizr_secondary/aktualizr_secondary_ostree_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ class UptaneRepoWrapper {
public:
UptaneRepoWrapper() { uptane_repo_.generateRepo(KeyType::kED25519); }

Metadata addOstreeRev(const std::string& rev, const std::string& hardware_id, const std::string& serial) {
Uptane::SecondaryMetadata addOstreeRev(const std::string& rev, const std::string& hardware_id,
const std::string& serial) {
// it makes sense to add 'addOstreeImage' to UptaneRepo interface/class uptane_repo.h
auto custom = Json::Value();
custom["targetFormat"] = "OSTREE";
Expand Down
12 changes: 6 additions & 6 deletions src/aktualizr_secondary/aktualizr_secondary_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ class UptaneRepoWrapper {
public:
UptaneRepoWrapper() { uptane_repo_.generateRepo(KeyType::kED25519); }

Metadata addImageFile(const std::string& targetname, const std::string& hardware_id, const std::string& serial,
size_t size = 2049, bool add_and_sign_target = true, bool add_invalid_images = false,
size_t delta = 2) {
Uptane::SecondaryMetadata addImageFile(const std::string& targetname, const std::string& hardware_id,
const std::string& serial, size_t size = 2049, bool add_and_sign_target = true,
bool add_invalid_images = false, size_t delta = 2) {
const auto image_file_path = root_dir_ / targetname;
generateRandomFile(image_file_path, size);

Expand Down Expand Up @@ -279,15 +279,15 @@ class SecondaryTestNegative
SecondaryTestNegative() : SecondaryTest(std::get<2>(GetParam())), success_expected_(std::get<3>(GetParam())) {}

protected:
class MetadataInvalidator : public Metadata {
class MetadataInvalidator : public Uptane::SecondaryMetadata {
public:
MetadataInvalidator(const Uptane::MetaBundle& valid_metadata, const Uptane::RepositoryType& repo,
const Uptane::Role& role)
: Metadata(valid_metadata), repo_type_(repo), role_(role) {}
: Uptane::SecondaryMetadata(valid_metadata), repo_type_(repo), role_(role) {}

void getRoleMetadata(std::string* result, const Uptane::RepositoryType& repo, const Uptane::Role& role,
Uptane::Version version) const override {
Metadata::getRoleMetadata(result, repo, role, version);
Uptane::SecondaryMetadata::getRoleMetadata(result, repo, role, version);
if (!(repo_type_ == repo && role_ == role)) {
return;
}
Expand Down
18 changes: 10 additions & 8 deletions src/libaktualizr/uptane/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
set(SOURCES
directorrepository.cc
fetcher.cc
imagerepository.cc
iterator.cc
manifest.cc
metawithkeys.cc
role.cc
root.cc
secondary_metadata.cc
tuf.cc
uptanerepository.cc
directorrepository.cc
imagerepository.cc
manifest.cc)
uptanerepository.cc)

set(HEADERS
directorrepository.h
exceptions.h
fetcher.h
imagerepository.h
iterator.h
manifest.h
secondary_metadata.h
tuf.h
uptanerepository.h
directorrepository.h
imagerepository.h
manifest.h)
uptanerepository.h)


add_library(uptane OBJECT ${SOURCES})
Expand Down
52 changes: 52 additions & 0 deletions src/libaktualizr/uptane/secondary_metadata.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "secondary_metadata.h"

namespace Uptane {

SecondaryMetadata::SecondaryMetadata(MetaBundle meta_bundle_in) : meta_bundle_(std::move(meta_bundle_in)) {
try {
director_root_version_ =
Version(extractVersionUntrusted(getMetaFromBundle(meta_bundle_, RepositoryType::Director(), Role::Root())));
} catch (const std::exception& e) {
LOG_DEBUG << "Failed to read Director Root version: " << e.what();
}
try {
image_root_version_ =
Version(extractVersionUntrusted(getMetaFromBundle(meta_bundle_, RepositoryType::Image(), Role::Root())));
} catch (const std::exception& e) {
LOG_DEBUG << "Failed to read Image repo Root version: " << e.what();
}
}

void SecondaryMetadata::fetchRole(std::string* result, int64_t maxsize, RepositoryType repo, const Role& role,
Version version) const {
(void)maxsize;
getRoleMetadata(result, repo, role, version);
}

void SecondaryMetadata::fetchLatestRole(std::string* result, int64_t maxsize, RepositoryType repo,
const Role& role) const {
(void)maxsize;
getRoleMetadata(result, repo, role, Version());
}

void SecondaryMetadata::getRoleMetadata(std::string* result, const RepositoryType& repo, const Role& role,
Version version) const {
if (role == Role::Root() && version != Version()) {
// If requesting a Root version beyond what we have available, fail as
// expected. If requesting a version before what is available, just use what
// is available, since root rotation isn't supported here.
if (repo == RepositoryType::Director() && director_root_version_ < version) {
LOG_DEBUG << "Requested Director Root version " << version << " but only version " << director_root_version_
<< " is available.";
throw std::runtime_error("Metadata not found");
} else if (repo == RepositoryType::Image() && image_root_version_ < version) {
LOG_DEBUG << "Requested Image repo Root version " << version << " but only version " << image_root_version_
<< " is available.";
throw std::runtime_error("Metadata not found");
}
}

*result = getMetaFromBundle(meta_bundle_, repo, role);
}

} // namespace Uptane
30 changes: 30 additions & 0 deletions src/libaktualizr/uptane/secondary_metadata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef AKTUALIZR_SECONDARY_METADATA_H_
#define AKTUALIZR_SECONDARY_METADATA_H_

#include "uptane/fetcher.h"
#include "uptane/tuf.h"

namespace Uptane {

class SecondaryMetadata : public IMetadataFetcher {
public:
SecondaryMetadata(MetaBundle meta_bundle_in);
SecondaryMetadata(SecondaryMetadata&&) = default;

void fetchRole(std::string* result, int64_t maxsize, RepositoryType repo, const Role& role,
Version version) const override;
void fetchLatestRole(std::string* result, int64_t maxsize, RepositoryType repo, const Role& role) const override;

protected:
virtual void getRoleMetadata(std::string* result, const RepositoryType& repo, const Role& role,
Version version) const;

private:
const MetaBundle meta_bundle_;
Version director_root_version_;
Version image_root_version_;
};

} // namespace Uptane

#endif // AKTUALIZR_SECONDARY_METADATA_H_
12 changes: 10 additions & 2 deletions src/libaktualizr/uptane/uptane_delegation_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,16 @@ TEST(Delegation, Basic) {
EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);

result::Install install_result = aktualizr.Install(download_result.updates).get();
EXPECT_TRUE(install_result.dev_report.success);
for (const auto& r : install_result.ecu_reports) {
EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
}
}

EXPECT_EQ(http->events_seen, 8);
// TODO: implement delegation support in ManagedSecondary and restore the
// Secondary target in the metadata generation scripts; then there should
// be 8 events.
EXPECT_EQ(http->events_seen, 4);
}
}

Expand All @@ -103,7 +107,10 @@ TEST(Delegation, RevokeAfterCheckUpdates) {

result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
EXPECT_EQ(update_result.updates.size(), 2);
// TODO: implement delegation support in ManagedSecondary and restore the
// Secondary target in the metadata generation scripts; then there should
// be 2 updates.
EXPECT_EQ(update_result.updates.size(), 1);
}
// Revoke delegation after CheckUpdates() and test if we can properly handle it.
{
Expand All @@ -119,6 +126,7 @@ TEST(Delegation, RevokeAfterCheckUpdates) {
EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);

result::Install install_result = aktualizr.Install(download_result.updates).get();
EXPECT_TRUE(install_result.dev_report.success);
for (const auto& r : install_result.ecu_reports) {
EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
}
Expand Down
Loading

0 comments on commit 70478f6

Please sign in to comment.