Aktualizr
C++ SOTA Client
primary_secondary_registration_test.cc
1 #include <gtest/gtest.h>
2 
3 #include "httpfake.h"
4 #include "libaktualizr/aktualizr.h"
5 #include "secondary.h"
6 #include "uptane_test_common.h"
7 #include "utilities/utils.h"
8 
9 boost::filesystem::path fake_meta_dir;
10 
11 /* This tests that a device that had an IP Secondary will still find it after
12  * recent changes, even if it does not connect when the device starts. Note that
13  * this is only supported for a single IP Secondary. */
14 TEST(PrimarySecondaryReg, SecondariesMigration) {
15  const Uptane::EcuSerial primary_serial{"p_serial"};
16  const Uptane::EcuSerial secondary_serial{"s_serial"};
17  const Uptane::HardwareIdentifier primary_hwid{"p_hwid"};
18  const Uptane::HardwareIdentifier secondary_hwid{"s_hwid"};
19 
20  TemporaryDirectory temp_dir;
21  auto http = std::make_shared<HttpFake>(temp_dir.Path(), "noupdates", fake_meta_dir);
22  const auto& url = http->tls_server;
23 
24  Config conf("tests/config/basic.toml");
25  conf.uptane.director_server = url + "/director";
26  conf.uptane.repo_server = url + "/repo";
27  conf.provision.server = url;
28  conf.provision.primary_ecu_serial = primary_serial.ToString();
29  conf.provision.primary_ecu_hardware_id = primary_hwid.ToString();
30  conf.storage.path = temp_dir.Path();
31  conf.import.base_path = temp_dir.Path() / "import";
32  conf.tls.server = url;
33  conf.bootloader.reboot_sentinel_dir = temp_dir.Path();
34  const boost::filesystem::path sec_conf_path = temp_dir / "s_config.json";
35  conf.uptane.secondary_config_file = sec_conf_path;
36 
37  auto storage = INvStorage::newStorage(conf.storage);
38  Json::Value sec_conf;
39 
40  // Prepare storage the "old" way (without the secondary_ecus table):
41  storage->storeDeviceId("device");
42  storage->storeEcuSerials({{primary_serial, primary_hwid}, {secondary_serial, secondary_hwid}});
43  storage->storeEcuRegistered();
44 
45  sec_conf["IP"]["secondary_wait_port"] = 9030;
46  sec_conf["IP"]["secondary_wait_timeout"] = 1;
47  sec_conf["IP"]["secondaries"] = Json::arrayValue;
48  sec_conf["IP"]["secondaries"][0]["addr"] = "127.0.0.1:9061";
49  Utils::writeFile(sec_conf_path, sec_conf);
50 
51  {
52  // Confirm that the fields from the secondary_ecus table are empty.
53  std::vector<SecondaryInfo> secs_info;
54  storage->loadSecondariesInfo(&secs_info);
55  EXPECT_EQ(secs_info.size(), 1);
56  EXPECT_EQ(secs_info[0].serial.ToString(), secondary_serial.ToString());
57  EXPECT_EQ(secs_info[0].type, "");
58  EXPECT_EQ(secs_info[0].extra, "");
59  }
60 
61  {
62  // Verify that aktualizr can still start if it can't connect to its
63  // Secondary. This will migrate the Secondary.
64  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
65  Primary::initSecondaries(aktualizr, sec_conf_path);
66  aktualizr.Initialize();
67  aktualizr.CheckUpdates().get();
68 
69  std::vector<SecondaryInfo> secs_info;
70  storage->loadSecondariesInfo(&secs_info);
71  EXPECT_EQ(secs_info.size(), 1);
72  EXPECT_EQ(secs_info[0].serial.ToString(), secondary_serial.ToString());
73  EXPECT_EQ(secs_info[0].type, "IP");
74  EXPECT_EQ(secs_info[0].extra, R"({"ip":"127.0.0.1","port":9061})");
75  }
76 
77  {
78  // Try again (again without connecting) to verify that the Secondary is
79  // correctly found in the storage.
80  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
81  Primary::initSecondaries(aktualizr, sec_conf_path);
82  aktualizr.Initialize();
83  aktualizr.CheckUpdates().get();
84 
85  std::vector<SecondaryInfo> secs_info;
86  storage->loadSecondariesInfo(&secs_info);
87  EXPECT_EQ(secs_info.size(), 1);
88  EXPECT_EQ(secs_info[0].serial.ToString(), secondary_serial.ToString());
89  EXPECT_EQ(secs_info[0].type, "IP");
90  EXPECT_EQ(secs_info[0].extra, R"({"ip":"127.0.0.1","port":9061})");
91  }
92 }
93 
94 /*
95  * Register Virtual Secondaries via json configuration.
96  * Reject multiple Secondaries with the same serial.
97  */
98 TEST(PrimarySecondaryReg, VirtualSecondary) {
99  TemporaryDirectory temp_dir;
100  auto http = std::make_shared<HttpFake>(temp_dir.Path(), "noupdates", fake_meta_dir);
101  Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
102  auto storage = INvStorage::newStorage(conf.storage);
103 
104  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
105  // This should fail because TestAktualizr automatically adds the default
106  // Secondary created in makeTestConfig.
107  EXPECT_THROW(Primary::initSecondaries(aktualizr, conf.uptane.secondary_config_file), std::exception);
108 
109  boost::filesystem::remove(conf.uptane.secondary_config_file);
110  UptaneTestCommon::addDefaultSecondary(conf, temp_dir, "serial2", "hwid2");
111  UptaneTestCommon::addDefaultSecondary(conf, temp_dir, "serial3", "hwid3");
112  Primary::initSecondaries(aktualizr, conf.uptane.secondary_config_file);
113  aktualizr.Initialize();
114 
115  std::vector<std::string> expected_ecus = {"CA:FE:A6:D2:84:9D", "secondary_ecu_serial", "serial2", "serial3"};
116  UptaneTestCommon::verifyEcus(temp_dir, expected_ecus);
117 }
118 
119 #ifndef __NO_MAIN__
120 int main(int argc, char** argv) {
121  ::testing::InitGoogleTest(&argc, argv);
122 
123  logger_init();
124  logger_set_threshold(boost::log::trivial::trace);
125 
126  TemporaryDirectory tmp_dir;
127  fake_meta_dir = tmp_dir.Path();
128  MetaFake meta_fake(fake_meta_dir);
129 
130  return RUN_ALL_TESTS();
131 }
132 #endif
UptaneTestCommon::TestAktualizr
Definition: uptane_test_common.h:21
Uptane::HardwareIdentifier
Definition: types.h:315
Config
Configuration object for an aktualizr instance running on a Primary ECU.
Definition: config.h:208
Uptane::EcuSerial
Definition: types.h:346
TemporaryDirectory
Definition: utils.h:82
MetaFake
Definition: metafake.h:14