Skip to content

Commit

Permalink
[WIP] tuf: Add new TUF Repo subclass to access an external TUF client…
Browse files Browse the repository at this point in the history
… agent

Signed-off-by: Andre Detsch <[email protected]>
  • Loading branch information
detsch committed Jul 18, 2024
1 parent 1e252ab commit f6b6127
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ set(SRC helpers.cc
tuf/akhttpsreposource.cc
tuf/localreposource.cc
tuf/akrepo.cc
tuf/httprepo.cc
daemon.cc
aklitereportqueue.cc)

Expand All @@ -49,12 +50,16 @@ set(HEADERS helpers.h
tuf/akhttpsreposource.h
tuf/localreposource.h
tuf/akrepo.h
tuf/httprepo.h
../include/aktualizr-lite/api.h
../include/aktualizr-lite/aklite_client_ext.h
../include/aktualizr-lite/tuf/tuf.h
daemon.h
aklitereportqueue.h)

# Use experimental standalone tuf agent
add_definitions(-DAKLITE_USE_TUF_AGENT)

if(USE_COMPOSEAPP_ENGINE)
set(SRC ${SRC} composeapp/appengine.cc)
set(HEADERS ${HEADERS} composeapp/appengine.h)
Expand Down
5 changes: 5 additions & 0 deletions src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "ostree/repo.h"
#include "tuf/akhttpsreposource.h"
#include "tuf/akrepo.h"
#include "tuf/httprepo.h"
#include "tuf/localreposource.h"
#include "uptane/exceptions.h"

Expand Down Expand Up @@ -158,7 +159,11 @@ void AkliteClient::Init(Config& config, bool finalize, bool apply_lock) {
}
}

#ifdef AKLITE_USE_TUF_AGENT
tuf_repo_ = std::make_unique<aklite::tuf::HttpRepo>(client_->config);
#else
tuf_repo_ = std::make_unique<aklite::tuf::AkRepo>(client_->config);
#endif
hw_id_ = client_->primary_ecu.second.ToString();
}

Expand Down
5 changes: 5 additions & 0 deletions src/liteclient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,11 @@ bool LiteClient::importRootMeta(const boost::filesystem::path& src, Uptane::Vers
}

void LiteClient::importRootMetaIfNeededAndPresent() {
#ifdef AKLITE_USE_TUF_AGENT
LOG_WARNING << "Skipping importRootMetaIfNeededAndPresent";
return;
#endif

const auto import{isRootMetaImportNeeded()};
if (!std::get<0>(import)) {
return;
Expand Down
121 changes: 121 additions & 0 deletions src/tuf/httprepo.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include "httprepo.h"
#include <curl/curl.h>
#include "logging/logging.h"
#include "target.h"

#include "tuf/localreposource.h"
#include "uptane/exceptions.h"

#include <curl/curl.h>
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <string>

#include <boost/algorithm/string.hpp>

namespace aklite::tuf {

HttpRepo::HttpRepo(const boost::filesystem::path& storage_path) {}

HttpRepo::HttpRepo(const Config& config) {}

size_t writeFunction(void* ptr, size_t size, size_t nmemb, std::string* data) {
data->append(static_cast<char*>(ptr), size * nmemb);
return size * nmemb;
}

std::string curl_request(const std::string& path, bool post) {
auto* curl = curl_easy_init();
if (curl == nullptr) {
LOG_ERROR << "Failed to instantiate curl handler";
return "";
}
// TODO: Make endpoint configurable
curl_easy_setopt(curl, CURLOPT_URL, (std::string("http://127.0.0.1/") + path).c_str());
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
// curl_easy_setopt(curl, CURLOPT_USERPWD, "user:pass");
curl_easy_setopt(curl, CURLOPT_USERAGENT, "aklite/1.0.0");
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
std::string response_string;

if (post) {
/* size of the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0L);

// /* pass in a pointer to the data - libcurl will not copy */
unsigned char b[0];
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, b);
curl_easy_setopt(curl, CURLOPT_POST, 1);
}

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunction);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
curl_easy_setopt(curl, CURLOPT_PORT, 9080);

std::string header_string;
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_string);

char* url;
long response_code;
double elapsed;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed);
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);

curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl = nullptr;

return response_string;
}

static std::vector<TufTarget> parseTargets(const std::string& targets_raw) {
// targets_raw contains the "signed" portion of the targets.json file
auto targets_json = Utils::parseJSON(targets_raw);
if (!targets_json.isObject()) {
throw Uptane::InvalidMetadata("", "targets", "invalid targets.json");
}

std::vector<TufTarget> targets;
for (auto t_it = targets_json.begin(); t_it != targets_json.end(); t_it++) {
const auto& content = *t_it;
TufTarget t(t_it.key().asString(), content["hashes"]["sha256"].asString(),
std::stoi(content["custom"]["version"].asString()), content["custom"]);
targets.push_back(t);
}
return targets;
}

std::vector<TufTarget> HttpRepo::GetTargets() {
const auto* url = "targets";
auto targets_raw = curl_request(url, false);
return parseTargets(targets_raw);
}

std::string HttpRepo::GetRoot(int version) {
if (version != -1) {
LOG_WARNING << "Fetching specific Root version is not supported. Retrieving the last one.";
}

const auto* url = "root";
auto root_raw = curl_request(url, false);
return root_raw;
}

void HttpRepo::UpdateMeta(std::shared_ptr<RepoSource> repo_src) {
auto local_repo_src = std::dynamic_pointer_cast<aklite::tuf::LocalRepoSource>(repo_src);

std::string url;
if (local_repo_src != nullptr) {
url = "targets/update/?localTufRepo=" + local_repo_src->SourceDir();
} else {
url = "targets/update/";
}
curl_request(url, true);
}

void HttpRepo::CheckMeta() { LOG_WARNING << "Skipping CheckMeta"; }

} // namespace aklite::tuf
27 changes: 27 additions & 0 deletions src/tuf/httprepo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef AKTUALIZR_LITE_HTTP_REPO_H_
#define AKTUALIZR_LITE_HTTP_REPO_H_

#include "libaktualizr/config.h"
#include "storage/invstorage.h"
#include "uptane/fetcher.h"
#include "uptane/imagerepository.h"

#include "aktualizr-lite/tuf/tuf.h"
#include "target.h"

namespace aklite::tuf {

// Repo implementation that uses libaktualizr to provide TUF metadata handling and storage
class HttpRepo : public Repo {
public:
explicit HttpRepo(const boost::filesystem::path& storage_path);
explicit HttpRepo(const Config& config);
std::vector<TufTarget> GetTargets() override;
std::string GetRoot(int version) override;
void UpdateMeta(std::shared_ptr<RepoSource> repo_src) override;
void CheckMeta() override;
};

} // namespace aklite::tuf

#endif
2 changes: 2 additions & 0 deletions src/tuf/localreposource.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ std::string LocalRepoSource::FetchSnapshot() { return fetchFile(src_dir_ / "snap

std::string LocalRepoSource::FetchTargets() { return fetchFile(src_dir_ / "targets.json"); }

std::string LocalRepoSource::SourceDir() { return src_dir_.string(); }

} // namespace aklite::tuf
2 changes: 2 additions & 0 deletions src/tuf/localreposource.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class LocalRepoSource : public RepoSource {
std::string FetchSnapshot() override;
std::string FetchTargets() override;

std::string SourceDir();

private:
static std::string fetchFile(const boost::filesystem::path &meta_file_path);

Expand Down

0 comments on commit f6b6127

Please sign in to comment.