Aktualizr
C++ SOTA Client
sotauptaneclient.h
1 #ifndef SOTA_UPTANE_CLIENT_H_
2 #define SOTA_UPTANE_CLIENT_H_
3 
4 #include <map>
5 #include <memory>
6 #include <string>
7 #include <utility>
8 #include <vector>
9 
10 #include <boost/signals2.hpp>
11 #include "gtest/gtest_prod.h"
12 #include "json/json.h"
13 
14 #include "libaktualizr/campaign.h"
15 #include "libaktualizr/config.h"
16 #include "libaktualizr/events.h"
17 #include "libaktualizr/packagemanagerfactory.h"
18 #include "libaktualizr/packagemanagerinterface.h"
19 #include "libaktualizr/results.h"
20 #include "libaktualizr/secondaryinterface.h"
21 
22 #include "bootloader/bootloader.h"
23 #include "http/httpclient.h"
24 #include "primary/secondary_provider_builder.h"
25 #include "reportqueue.h"
26 #include "uptane/directorrepository.h"
27 #include "uptane/exceptions.h"
28 #include "uptane/fetcher.h"
29 #include "uptane/imagerepository.h"
30 #include "uptane/iterator.h"
31 #include "uptane/manifest.h"
32 #include "uptane/tuf.h"
33 #include "utilities/apiqueue.h"
34 
36  public:
37  SotaUptaneClient(Config &config_in, std::shared_ptr<INvStorage> storage_in, std::shared_ptr<HttpInterface> http_in,
38  std::shared_ptr<event::Channel> events_channel_in,
39  const Uptane::EcuSerial &primary_serial = Uptane::EcuSerial::Unknown(),
40  const Uptane::HardwareIdentifier &hwid = Uptane::HardwareIdentifier::Unknown())
41  : config(config_in),
42  storage(std::move(storage_in)),
43  http(std::move(http_in)),
44  package_manager_(PackageManagerFactory::makePackageManager(config.pacman, config.bootloader, storage, http)),
45  uptane_fetcher(new Uptane::Fetcher(config, http)),
46  events_channel(std::move(events_channel_in)),
47  primary_ecu_serial_(primary_serial),
48  primary_ecu_hw_id_(hwid) {
49  report_queue = std_::make_unique<ReportQueue>(config, http, storage);
50  secondary_provider_ = SecondaryProviderBuilder::Build(config, storage, package_manager_);
51  }
52 
53  SotaUptaneClient(Config &config_in, const std::shared_ptr<INvStorage> &storage_in,
54  std::shared_ptr<HttpInterface> http_in)
55  : SotaUptaneClient(config_in, storage_in, std::move(http_in), nullptr) {}
56 
57  SotaUptaneClient(Config &config_in, const std::shared_ptr<INvStorage> &storage_in)
58  : SotaUptaneClient(config_in, storage_in, std::make_shared<HttpClient>()) {}
59 
60  void initialize();
61  void addSecondary(const std::shared_ptr<SecondaryInterface> &sec);
62  result::Download downloadImages(const std::vector<Uptane::Target> &targets,
63  const api::FlowControlToken *token = nullptr);
64  std::pair<bool, Uptane::Target> downloadImage(const Uptane::Target &target,
65  const api::FlowControlToken *token = nullptr);
66  void reportPause();
67  void reportResume();
68  void sendDeviceData(const Json::Value &custom_hwinfo = Json::nullValue);
69  result::UpdateCheck fetchMeta();
70  bool putManifest(const Json::Value &custom = Json::nullValue);
71  result::UpdateCheck checkUpdates();
72  result::Install uptaneInstall(const std::vector<Uptane::Target> &updates);
73  result::CampaignCheck campaignCheck();
74  void campaignAccept(const std::string &campaign_id);
75  void campaignDecline(const std::string &campaign_id);
76  void campaignPostpone(const std::string &campaign_id);
77 
78  bool hasPendingUpdates() const;
79  bool isInstallCompletionRequired() const;
80  void completeInstall() const;
81  Uptane::LazyTargetsList allTargets() const;
82  Uptane::Target getCurrent() const { return package_manager_->getCurrent(); }
83  std::vector<Uptane::Target> getStoredTargets() const { return package_manager_->getTargetFiles(); }
84  void deleteStoredTarget(const Uptane::Target &target) { package_manager_->removeTargetFile(target); }
85  std::ifstream openStoredTarget(const Uptane::Target &target) {
86  auto status = package_manager_->verifyTarget(target);
87  if (status == TargetStatus::kGood) {
88  return package_manager_->openTargetFile(target);
89  } else {
90  throw std::runtime_error("Failed to open Target");
91  }
92  }
93 
94  void updateImageMeta(); // TODO: make private once aktualizr has a proper TUF API
95  void checkImageMetaOffline();
96  data::InstallationResult PackageInstall(const Uptane::Target &target);
97  TargetStatus VerifyTarget(const Uptane::Target &target) const { return package_manager_->verifyTarget(target); }
98  std::string treehubCredentials() const;
99 
100  private:
101  FRIEND_TEST(Aktualizr, FullNoUpdates);
102  FRIEND_TEST(Aktualizr, DeviceInstallationResult);
103  FRIEND_TEST(Aktualizr, DeviceInstallationResultMetadata);
104  FRIEND_TEST(Aktualizr, FullMultipleSecondaries);
105  FRIEND_TEST(Aktualizr, CheckNoUpdates);
106  FRIEND_TEST(Aktualizr, DownloadWithUpdates);
107  FRIEND_TEST(Aktualizr, FinalizationFailure);
108  FRIEND_TEST(Aktualizr, InstallationFailure);
109  FRIEND_TEST(Aktualizr, AutoRebootAfterUpdate);
110  FRIEND_TEST(Aktualizr, EmptyTargets);
111  FRIEND_TEST(Aktualizr, FullOstreeUpdate);
112  FRIEND_TEST(Aktualizr, DownloadNonOstreeBin);
114  FRIEND_TEST(DockerAppManager, DockerAppBundles);
115  FRIEND_TEST(Uptane, AssembleManifestGood);
116  FRIEND_TEST(Uptane, AssembleManifestBad);
117  FRIEND_TEST(Uptane, InstallFakeGood);
118  FRIEND_TEST(Uptane, restoreVerify);
119  FRIEND_TEST(Uptane, PutManifest);
120  FRIEND_TEST(Uptane, offlineIteration);
121  FRIEND_TEST(Uptane, IgnoreUnknownUpdate);
122  FRIEND_TEST(Uptane, kRejectAllTest);
123  FRIEND_TEST(UptaneCI, ProvisionAndPutManifest);
124  FRIEND_TEST(UptaneCI, CheckKeys);
125  FRIEND_TEST(UptaneKey, Check); // Note hacky name
126  FRIEND_TEST(UptaneNetwork, DownloadFailure);
127  FRIEND_TEST(UptaneNetwork, LogConnectivityRestored);
128  FRIEND_TEST(UptaneVector, Test);
129  FRIEND_TEST(aktualizr_secondary_uptane, credentialsPassing);
130  friend class CheckForUpdate; // for load tests
131  friend class ProvisionDeviceTask; // for load tests
132 
133  void uptaneIteration(std::vector<Uptane::Target> *targets, unsigned int *ecus_count);
134  void uptaneOfflineIteration(std::vector<Uptane::Target> *targets, unsigned int *ecus_count);
135  result::UpdateStatus checkUpdatesOffline(const std::vector<Uptane::Target> &targets);
136  Json::Value AssembleManifest();
137  std::exception_ptr getLastException() const { return last_exception; }
138  static std::vector<Uptane::Target> findForEcu(const std::vector<Uptane::Target> &targets,
139  const Uptane::EcuSerial &ecu_id);
140  data::InstallationResult PackageInstallSetResult(const Uptane::Target &target);
141  void finalizeAfterReboot();
142  void reportHwInfo(const Json::Value &custom_hwinfo);
143  void reportInstalledPackages();
144  void reportNetworkInfo();
145  void reportAktualizrConfiguration();
146  bool waitSecondariesReachable(const std::vector<Uptane::Target> &updates);
147  void storeInstallationFailure(const data::InstallationResult &result);
148  data::InstallationResult rotateSecondaryRoot(Uptane::RepositoryType repo, SecondaryInterface &secondary);
149  void sendMetadataToEcus(const std::vector<Uptane::Target> &targets, data::InstallationResult *result,
150  std::string *raw_installation_report);
151  std::future<data::InstallationResult> sendFirmwareAsync(SecondaryInterface &secondary, const Uptane::Target &target);
152  std::vector<result::Install::EcuReport> sendImagesToEcus(const std::vector<Uptane::Target> &targets);
153 
154  bool putManifestSimple(const Json::Value &custom = Json::nullValue);
155  void getNewTargets(std::vector<Uptane::Target> *new_targets, unsigned int *ecus_count = nullptr);
156  void updateDirectorMeta();
157  void checkDirectorMetaOffline();
158  void computeDeviceInstallationResult(data::InstallationResult *result, std::string *raw_installation_report) const;
159  std::unique_ptr<Uptane::Target> findTargetInDelegationTree(const Uptane::Target &target, bool offline);
160  std::unique_ptr<Uptane::Target> findTargetHelper(const Uptane::Targets &cur_targets,
161  const Uptane::Target &queried_target, int level, bool terminating,
162  bool offline);
163  void checkAndUpdatePendingSecondaries();
164  const Uptane::EcuSerial &primaryEcuSerial() const { return primary_ecu_serial_; }
165  boost::optional<Uptane::HardwareIdentifier> getEcuHwId(const Uptane::EcuSerial &serial) const;
166 
167  template <class T, class... Args>
168  void sendEvent(Args &&... args) {
169  std::shared_ptr<event::BaseEvent> event = std::make_shared<T>(std::forward<Args>(args)...);
170  if (events_channel) {
171  (*events_channel)(std::move(event));
172  } else if (!event->isTypeOf<event::DownloadProgressReport>()) {
173  LOG_INFO << "got " << event->variant << " event";
174  }
175  }
176 
177  Config &config;
178  Uptane::DirectorRepository director_repo;
179  Uptane::ImageRepository image_repo;
180  Uptane::ManifestIssuer::Ptr uptane_manifest;
181  std::shared_ptr<INvStorage> storage;
182  std::shared_ptr<HttpInterface> http;
183  std::shared_ptr<PackageManagerInterface> package_manager_;
184  std::shared_ptr<Uptane::Fetcher> uptane_fetcher;
185  std::unique_ptr<ReportQueue> report_queue;
186  std::shared_ptr<SecondaryProvider> secondary_provider_;
187  std::shared_ptr<event::Channel> events_channel;
188  boost::signals2::scoped_connection conn;
189  std::exception_ptr last_exception;
190  // ecu_serial => secondary*
191  std::map<Uptane::EcuSerial, SecondaryInterface::Ptr> secondaries;
192  std::mutex download_mutex;
193  Uptane::EcuSerial primary_ecu_serial_;
194  Uptane::HardwareIdentifier primary_ecu_hw_id_;
195 };
196 
198  public:
199  explicit TargetCompare(const Uptane::Target &target_in) : target(target_in) {}
200  bool operator()(const Uptane::Target &in) const { return (in.MatchTarget(target)); }
201 
202  private:
203  const Uptane::Target &target;
204 };
205 
206 #endif // SOTA_UPTANE_CLIENT_H_
results.h
Uptane::Fetcher
Definition: fetcher.h:33
Uptane::DirectorRepository
Definition: directorrepository.h:13
data::InstallationResult
Definition: types.h:277
SotaUptaneClient
Definition: sotauptaneclient.h:35
UptaneVector
Definition: uptane_vector_tests.cc:84
Uptane::ImageRepository
Definition: imagerepository.h:13
result::UpdateCheck
Container for information about available updates.
Definition: results.h:37
Uptane::HardwareIdentifier
Definition: types.h:315
DockerAppBundles
Definition: dockerappmanager.h:44
Config
Configuration object for an aktualizr instance running on a Primary ECU.
Definition: config.h:208
events.h
Uptane::RepositoryType
Definition: tuf.h:21
result::UpdateStatus
UpdateStatus
Status of an update.
Definition: results.h:25
Uptane::EcuSerial
Definition: types.h:346
Uptane::Targets
Definition: tuf.h:271
Aktualizr
This class provides the main APIs necessary for launching and controlling libaktualizr.
Definition: aktualizr.h:24
result::Download
Container for information about downloading an update.
Definition: results.h:116
Uptane::LazyTargetsList
Definition: iterator.h:12
api::FlowControlToken
Provides a thread-safe way to pause and terminate task execution.
Definition: apiqueue.h:19
DockerAppStandalone
Definition: dockerappmanager.h:21
result
Results of libaktualizr API calls.
Definition: results.h:12
result::Install
Container for information about installing an update.
Definition: results.h:129
event::DownloadProgressReport
A report for a download in progress.
Definition: events.h:68
Uptane::Target
Definition: types.h:379
result::CampaignCheck
Container for information about available campaigns.
Definition: results.h:16
Uptane
Base data types that are used in The Update Framework (TUF), part of Uptane.
Definition: packagemanagerinterface.h:18
DockerAppManager
Definition: dockerappmanager.h:67
TargetCompare
Definition: sotauptaneclient.h:197
event
Aktualizr status events.
Definition: events.h:15
SecondaryInterface
Definition: secondaryinterface.h:9