5 #include <boost/filesystem.hpp>
6 #include <boost/program_options.hpp>
8 #include "libaktualizr/packagemanagerfactory.h"
10 #include "aktualizr_info_config.h"
11 #include "logging/logging.h"
12 #include "storage/invstorage.h"
13 #include "storage/sql_utils.h"
14 #include "utilities/aktualizr_version.h"
16 namespace bpo = boost::program_options;
18 static int loadAndPrintDelegations(
const std::shared_ptr<INvStorage> &storage) {
19 std::vector<std::pair<Uptane::Role, std::string> > delegations;
20 bool delegations_fetch_res = storage->loadAllDelegations(delegations);
22 if (!delegations_fetch_res) {
23 std::cout <<
"Failed to load delegations" << std::endl;
27 if (!delegations.empty()) {
28 for (
const auto &delegation : delegations) {
29 std::cout << delegation.first <<
": " << delegation.second << std::endl;
32 std::cout <<
"Delegations are not present" << std::endl;
37 void checkInfoOptions(
const bpo::options_description &description,
const bpo::variables_map &vm) {
38 if (vm.count(
"help") != 0) {
39 std::cout << description <<
'\n';
42 if (vm.count(
"version") != 0) {
43 std::cout <<
"Current aktualizr-info version is: " << aktualizr_version() <<
"\n";
48 int main(
int argc,
char **argv) {
49 bpo::options_description all(
"aktualizr-info command line options");
50 bpo::options_description description(
"aktualizr-info command line options");
51 bpo::options_description hidden(
"deprecated options");
53 description.add_options()
54 (
"help,h",
"print usage")
55 (
"version,v",
"Current aktualizr version")
56 (
"config,c", bpo::value<std::vector<boost::filesystem::path> >()->composing(),
"configuration file or directory")
57 (
"loglevel", bpo::value<int>(),
"set log level 0-5 (trace, debug, info, warning, error, fatal)")
58 (
"name-only",
"Only output device name (intended for scripting). Cannot be used in combination with other arguments.")
59 (
"tls-creds",
"Outputs TLS credentials")
60 (
"tls-root-ca",
"Outputs TLS Root CA")
61 (
"tls-cert",
"Outputs TLS client certificate")
62 (
"tls-prv-key",
"Output TLS client private key")
63 (
"ecu-keys",
"Outputs Uptane keys")
64 (
"ecu-pub-key",
"Outputs Uptane public key")
65 (
"ecu-prv-key",
"Outputs Uptane private key")
66 (
"image-root",
"Outputs root.json from Image repo")
67 (
"image-timestamp",
"Outputs timestamp.json from Image repo")
68 (
"image-snapshot",
"Outputs snapshot.json from Image repo")
69 (
"image-targets",
"Outputs targets.json from Image repo")
70 (
"delegation",
"Outputs metadata of Image repo Targets' delegations")
71 (
"director-root",
"Outputs root.json from Director repo")
72 (
"director-targets",
"Outputs targets.json from Director repo")
73 (
"allow-migrate",
"Opens database in read/write mode to make possible to migrate database if needed")
74 (
"wait-until-provisioned",
"Outputs metadata when device already provisioned");
77 (
"images-root",
"Outputs root.json from Image repo")
78 (
"images-timestamp",
"Outputs timestamp.json from Image repo")
79 (
"images-snapshot",
"Outputs snapshot.json from Image repo")
80 (
"images-target",
"Outputs targets.json from Image repo")
81 (
"images-targets",
"Outputs targets.json from Image repo")
82 (
"image-target",
"Outputs targets.json from Image repo")
83 (
"director-target",
"Outputs targets.json from Director repo");
87 all.add(description).add(hidden);
88 bpo::variables_map vm;
89 bpo::basic_parsed_options<char> parsed_options = bpo::command_line_parser(argc, argv).options(all).run();
90 bpo::store(parsed_options, vm);
91 checkInfoOptions(description, vm);
93 std::vector<std::string> unregistered_options =
94 bpo::collect_unrecognized(parsed_options.options, bpo::include_positional);
95 if (vm.count(
"help") == 0 && !unregistered_options.empty()) {
96 std::cout << description <<
"\n";
101 if (vm.count(
"loglevel") == 0U) {
102 logger_set_enable(
false);
107 bool secondary_db =
false;
109 bool readonly =
true;
110 if (vm.count(
"allow-migrate") != 0U) {
114 bool wait_provisioning =
false;
115 if (vm.count(
"wait-until-provisioned") != 0) {
116 wait_provisioning =
true;
119 std::shared_ptr<INvStorage> storage;
120 bool cmd_trigger =
false;
121 std::string device_id;
123 bool registered =
false;
124 bool has_metadata =
false;
125 std::string director_root;
126 if (wait_provisioning) {
127 while (!registered || !has_metadata) {
129 storage = INvStorage::newStorage(config.storage, readonly);
131 registered = storage->loadEcuRegistered();
132 has_metadata = storage->loadLatestRoot(&director_root, Uptane::RepositoryType::Director());
133 }
catch (std::exception &e) {
140 storage = INvStorage::newStorage(config.storage, readonly);
143 bool deviceid_loaded =
false;
144 if (storage->loadDeviceId(&device_id)) {
145 deviceid_loaded =
true;
147 if (vm.count(
"name-only") != 0U) {
148 std::cout << device_id << std::endl;
153 registered = registered || storage->loadEcuRegistered();
154 has_metadata = has_metadata || storage->loadLatestRoot(&director_root, Uptane::RepositoryType::Director());
156 bool tlscred_loaded =
false;
162 storage->loadTlsCreds(&ca, &cert, &pkey);
163 if (!ca.empty() || !cert.empty() || !pkey.empty()) {
164 tlscred_loaded =
true;
167 if (vm.count(
"tls-creds") != 0U) {
168 std::cout <<
"Root CA certificate:" << std::endl << ca << std::endl;
169 std::cout <<
"Client certificate:" << std::endl << cert << std::endl;
170 std::cout <<
"Client private key:" << std::endl << pkey << std::endl;
175 if (vm.count(
"tls-root-ca") != 0U) {
177 storage->loadTlsCa(&ca);
178 std::cout << ca << std::endl;
182 if (vm.count(
"tls-cert") != 0U) {
184 storage->loadTlsCert(&cert);
185 std::cout << cert << std::endl;
189 if (vm.count(
"tls-prv-key") != 0U) {
191 storage->loadTlsPkey(&key);
192 std::cout << key << std::endl;
197 bool ecukeys_loaded =
false;
201 storage->loadPrimaryKeys(&pub, &priv);
202 if (!pub.empty() && !priv.empty()) {
203 ecukeys_loaded =
true;
205 if (vm.count(
"ecu-keys") != 0U) {
206 std::cout <<
"Public key:" << std::endl << pub << std::endl;
207 std::cout <<
"Private key:" << std::endl << priv << std::endl;
211 if (vm.count(
"ecu-pub-key") != 0U) {
213 storage->loadPrimaryPublic(&key);
214 std::cout << key << std::endl;
218 if (vm.count(
"ecu-prv-key") != 0U) {
220 storage->loadPrimaryPrivate(&key);
221 std::cout << key << std::endl;
226 std::string msg_metadata_fail =
"Metadata is not available";
227 if (vm.count(
"image-root") != 0U || vm.count(
"images-root") != 0U) {
229 std::cout << msg_metadata_fail << std::endl;
231 std::string images_root;
232 storage->loadLatestRoot(&images_root, Uptane::RepositoryType::Image());
233 std::cout << images_root << std::endl;
238 if (vm.count(
"image-targets") != 0U || vm.count(
"image-target") != 0U || vm.count(
"images-targets") != 0U ||
239 vm.count(
"images-target") != 0U) {
241 std::cout << msg_metadata_fail << std::endl;
243 std::string images_targets;
244 storage->loadNonRoot(&images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
245 std::cout << images_targets << std::endl;
250 if (vm.count(
"delegation") != 0U) {
252 std::cout << msg_metadata_fail << std::endl;
254 loadAndPrintDelegations(storage);
259 if (vm.count(
"director-root") != 0U) {
261 std::cout << msg_metadata_fail << std::endl;
263 std::cout << director_root << std::endl;
268 if (vm.count(
"director-targets") != 0U || vm.count(
"director-target") != 0U) {
270 std::cout << msg_metadata_fail << std::endl;
272 std::string director_targets;
273 storage->loadNonRoot(&director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
274 std::cout << director_targets << std::endl;
279 if (vm.count(
"image-snapshot") != 0U || vm.count(
"images-snapshot") != 0U) {
281 std::cout << msg_metadata_fail << std::endl;
283 std::string snapshot;
284 storage->loadNonRoot(&snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
285 std::cout << snapshot << std::endl;
290 if (vm.count(
"image-timestamp") != 0U || vm.count(
"images-timestamp") != 0U) {
292 std::cout << msg_metadata_fail << std::endl;
294 std::string timestamp;
295 storage->loadNonRoot(×tamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
296 std::cout << timestamp << std::endl;
305 if (!deviceid_loaded && !tlscred_loaded && ecukeys_loaded) {
311 if (!deviceid_loaded) {
312 std::cout <<
"Couldn't load device ID" << std::endl;
314 std::cout <<
"Device ID: " << device_id << std::endl;
318 std::string ecu_name = secondary_db ?
"Secondary" :
"Primary";
320 if (!storage->loadEcuSerials(&serials)) {
321 std::cout <<
"Couldn't load ECU serials" << std::endl;
322 }
else if (serials.empty()) {
323 std::cout << ecu_name <<
" serial is not found" << std::endl;
325 std::cout << ecu_name <<
" ECU serial ID: " << serials[0].first << std::endl;
326 std::cout << ecu_name <<
" ECU hardware ID: " << serials[0].second << std::endl;
329 if (serials.size() > 1) {
330 auto it = serials.begin() + 1;
331 std::cout <<
"Secondaries:\n";
332 int secondary_number = 1;
333 for (; it != serials.end(); ++it) {
334 std::cout << secondary_number++ <<
") serial ID: " << it->first << std::endl;
335 std::cout <<
" hardware ID: " << it->second << std::endl;
337 boost::optional<Uptane::Target> current_version;
338 boost::optional<Uptane::Target> pending_version;
340 auto load_installed_version_res =
341 storage->loadInstalledVersions((it->first).ToString(), ¤t_version, &pending_version);
343 if (!load_installed_version_res || (!current_version && !pending_version)) {
344 std::cout <<
" no details about installed nor pending images\n";
346 if (!!current_version) {
347 std::cout <<
" installed image hash: " << current_version->sha256Hash() <<
"\n";
348 std::cout <<
" installed image filename: " << current_version->filename() <<
"\n";
350 if (!!pending_version) {
351 std::cout <<
" pending image hash: " << pending_version->sha256Hash() <<
"\n";
352 std::cout <<
" pending image filename: " << pending_version->filename() <<
"\n";
358 std::vector<MisconfiguredEcu> misconfigured_ecus;
359 storage->loadMisconfiguredEcus(&misconfigured_ecus);
360 if (!misconfigured_ecus.empty()) {
361 std::cout <<
"Removed or unregistered ECUs (deprecated):" << std::endl;
362 std::vector<MisconfiguredEcu>::const_iterator it;
363 for (it = misconfigured_ecus.begin(); it != misconfigured_ecus.end(); ++it) {
364 std::cout <<
" '" << it->serial <<
"' with hardware_id '" << it->hardware_id <<
"' "
365 << (it->state == EcuState::kOld ?
"has been removed from config" :
"not registered yet") << std::endl;
370 std::cout <<
"Provisioned on server: " << (registered ?
"yes" :
"no") << std::endl;
372 std::cout <<
"Fetched metadata: " << (has_metadata ?
"yes" :
"no") << std::endl;
374 auto pacman = PackageManagerFactory::makePackageManager(config.pacman, config.bootloader, storage,
nullptr);
378 if (current_target.IsValid()) {
379 std::cout <<
"Current " << ecu_name <<
" ECU running version: " << current_target.sha256Hash() << std::endl;
381 std::cout <<
"No currently running version on " << ecu_name <<
" ECU" << std::endl;
384 std::vector<Uptane::Target> installed_versions;
385 boost::optional<Uptane::Target> pending;
386 storage->loadPrimaryInstalledVersions(
nullptr, &pending);
389 std::cout <<
"Pending " << ecu_name <<
" ECU version: " << pending->sha256Hash() << std::endl;
391 }
catch (
const bpo::error &o) {
392 std::cout << o.what() << std::endl << description;
395 }
catch (
const std::exception &exc) {
396 std::cerr <<
"Error: " << exc.what() << std::endl;