8 #include <boost/algorithm/string/classification.hpp> 9 #include <boost/algorithm/string/split.hpp> 10 #include <boost/algorithm/string/trim.hpp> 11 #include <boost/filesystem.hpp> 13 #include "bootstrap/bootstrap.h" 15 #include "utilities/exceptions.h" 16 #include "utilities/utils.h" 18 void NetworkConfig::updateFromPropertyTree(
const boost::property_tree::ptree& pt) {
19 CopyFromConfig(ipdiscovery_host,
"ipdiscovery_host", pt);
20 CopyFromConfig(ipdiscovery_port,
"ipdiscovery_port", pt);
21 CopyFromConfig(ipdiscovery_wait_seconds,
"ipdiscovery_wait_seconds", pt);
22 CopyFromConfig(ipuptane_port,
"ipuptane_port", pt);
25 void NetworkConfig::writeToStream(std::ostream& out_stream)
const {
26 writeOption(out_stream, ipdiscovery_host,
"ipdiscovery_host");
27 writeOption(out_stream, ipdiscovery_port,
"ipdiscovery_port");
28 writeOption(out_stream, ipdiscovery_wait_seconds,
"ipdiscovery_wait_seconds");
29 writeOption(out_stream, ipuptane_port,
"ipuptane_port");
32 void TlsConfig::updateFromPropertyTree(
const boost::property_tree::ptree& pt) {
33 CopyFromConfig(server,
"server", pt);
34 CopyFromConfig(server_url_path,
"server_url_path", pt);
35 CopyFromConfig(ca_source,
"ca_source", pt);
36 CopyFromConfig(cert_source,
"cert_source", pt);
37 CopyFromConfig(pkey_source,
"pkey_source", pt);
40 void TlsConfig::writeToStream(std::ostream& out_stream)
const {
41 writeOption(out_stream, server,
"server");
42 writeOption(out_stream, server_url_path,
"server_url_path");
43 writeOption(out_stream, ca_source,
"ca_source");
44 writeOption(out_stream, pkey_source,
"pkey_source");
45 writeOption(out_stream, cert_source,
"cert_source");
48 void ProvisionConfig::updateFromPropertyTree(
const boost::property_tree::ptree& pt) {
49 CopyFromConfig(server,
"server", pt);
50 CopyFromConfig(p12_password,
"p12_password", pt);
51 CopyFromConfig(expiry_days,
"expiry_days", pt);
52 CopyFromConfig(provision_path,
"provision_path", pt);
53 CopyFromConfig(device_id,
"device_id", pt);
54 CopyFromConfig(primary_ecu_serial,
"primary_ecu_serial", pt);
55 CopyFromConfig(primary_ecu_hardware_id,
"primary_ecu_hardware_id", pt);
56 CopyFromConfig(ecu_registration_endpoint,
"ecu_registration_endpoint", pt);
60 void ProvisionConfig::writeToStream(std::ostream& out_stream)
const {
61 writeOption(out_stream, server,
"server");
62 writeOption(out_stream, p12_password,
"p12_password");
63 writeOption(out_stream, expiry_days,
"expiry_days");
64 writeOption(out_stream, provision_path,
"provision_path");
65 writeOption(out_stream, device_id,
"device_id");
66 writeOption(out_stream, primary_ecu_serial,
"primary_ecu_serial");
67 writeOption(out_stream, primary_ecu_hardware_id,
"primary_ecu_hardware_id");
68 writeOption(out_stream, ecu_registration_endpoint,
"ecu_registration_endpoint");
72 void UptaneConfig::updateFromPropertyTree(
const boost::property_tree::ptree& pt) {
73 CopyFromConfig(running_mode,
"running_mode", pt);
74 CopyFromConfig(polling_sec,
"polling_sec", pt);
75 CopyFromConfig(director_server,
"director_server", pt);
76 CopyFromConfig(repo_server,
"repo_server", pt);
77 CopyFromConfig(key_source,
"key_source", pt);
78 CopyFromConfig(key_type,
"key_type", pt);
79 CopyFromConfig(legacy_interface,
"legacy_interface", pt);
84 void UptaneConfig::writeToStream(std::ostream& out_stream)
const {
85 writeOption(out_stream, StringFromRunningMode(running_mode),
"running_mode");
86 writeOption(out_stream, polling_sec,
"polling_sec");
87 writeOption(out_stream, director_server,
"director_server");
88 writeOption(out_stream, repo_server,
"repo_server");
89 writeOption(out_stream, key_source,
"key_source");
90 writeOption(out_stream, key_type,
"key_type");
91 writeOption(out_stream, legacy_interface,
"legacy_interface");
94 void DiscoveryConfig::updateFromPropertyTree(
const boost::property_tree::ptree& pt) {
95 CopyFromConfig(ipuptane,
"ipuptane", pt);
98 void DiscoveryConfig::writeToStream(std::ostream& out_stream)
const { writeOption(out_stream, ipuptane,
"ipuptane"); }
105 std::ostream& operator<<(std::ostream& os,
const Config& cfg) {
106 cfg.writeToStream(os);
110 Config::Config() { postUpdateValues(); }
112 Config::Config(
const boost::filesystem::path& filename) {
113 updateFromToml(filename);
117 Config::Config(
const std::vector<boost::filesystem::path>& config_dirs) {
118 checkDirs(config_dirs);
119 updateFromDirs(config_dirs);
123 Config::Config(
const boost::program_options::variables_map& cmd) {
126 if (cmd.count(
"loglevel") != 0) {
127 logger.loglevel = cmd[
"loglevel"].as<
int>();
128 logger_set_threshold(logger);
129 loglevel_from_cmdline =
true;
132 if (cmd.count(
"config") > 0) {
133 const auto configs = cmd[
"config"].as<std::vector<boost::filesystem::path>>();
135 updateFromDirs(configs);
137 updateFromDirs(config_dirs_);
139 updateFromCommandLine(cmd);
144 return KeyManagerConfig{p11, tls.ca_source, tls.pkey_source, tls.cert_source, uptane.key_type, uptane.key_source};
147 void Config::postUpdateValues() {
148 logger_set_threshold(logger);
150 if (provision.provision_path.empty()) {
151 provision.mode = ProvisionMode::kImplicit;
154 if (tls.server.empty()) {
155 if (!tls.server_url_path.empty()) {
157 tls.server = Utils::readFile(tls.server_url_path);
158 }
catch (
const boost::filesystem::filesystem_error& e) {
159 LOG_ERROR <<
"Couldn't read gateway URL: " << e.what();
162 }
else if (!provision.provision_path.empty()) {
163 if (boost::filesystem::exists(provision.provision_path)) {
164 tls.server = Bootstrap::readServerUrl(provision.provision_path);
166 LOG_ERROR <<
"Provided provision archive " << provision.provision_path <<
" does not exist!";
171 if (!tls.server.empty()) {
172 if (provision.server.empty()) {
173 provision.server = tls.server;
176 if (uptane.repo_server.empty()) {
177 uptane.repo_server = tls.server +
"/repo";
180 if (uptane.director_server.empty()) {
181 uptane.director_server = tls.server +
"/director";
184 if (pacman.ostree_server.empty()) {
185 pacman.ostree_server = tls.server +
"/treehub";
189 if (!uptane.director_server.empty()) {
190 if (provision.ecu_registration_endpoint.empty()) {
191 provision.ecu_registration_endpoint = uptane.director_server +
"/ecus";
195 checkLegacyVersion();
196 initLegacySecondaries();
197 LOG_TRACE <<
"Final configuration that will be used: \n" << (*this);
201 void Config::updateFromTomlString(
const std::string& contents) {
202 boost::property_tree::ptree pt;
203 std::stringstream stream(contents);
204 boost::property_tree::ini_parser::read_ini(stream, pt);
205 updateFromPropertyTree(pt);
208 void Config::updateFromPropertyTree(
const boost::property_tree::ptree& pt) {
210 if (!loglevel_from_cmdline) {
211 CopySubtreeFromConfig(logger,
"logger", pt);
214 logger_set_threshold(logger);
216 CopySubtreeFromConfig(network,
"network", pt);
217 CopySubtreeFromConfig(p11,
"p11", pt);
218 CopySubtreeFromConfig(tls,
"tls", pt);
219 CopySubtreeFromConfig(provision,
"provision", pt);
220 CopySubtreeFromConfig(uptane,
"uptane", pt);
221 CopySubtreeFromConfig(discovery,
"discovery", pt);
222 CopySubtreeFromConfig(pacman,
"pacman", pt);
223 CopySubtreeFromConfig(storage,
"storage", pt);
224 CopySubtreeFromConfig(
import,
"import", pt);
225 CopySubtreeFromConfig(telemetry,
"telemetry", pt);
226 CopySubtreeFromConfig(bootloader,
"bootloader", pt);
229 void Config::updateFromCommandLine(
const boost::program_options::variables_map& cmd) {
231 if (cmd.count(
"loglevel") != 0) {
232 logger.loglevel = cmd[
"loglevel"].as<
int>();
234 if (cmd.count(
"running-mode") != 0) {
235 uptane.running_mode = RunningModeFromString(cmd[
"running-mode"].as<std::string>());
237 if (cmd.count(
"tls-server") != 0) {
238 tls.server = cmd[
"tls-server"].as<std::string>();
240 if (cmd.count(
"repo-server") != 0) {
241 uptane.repo_server = cmd[
"repo-server"].as<std::string>();
243 if (cmd.count(
"director-server") != 0) {
244 uptane.director_server = cmd[
"director-server"].as<std::string>();
246 if (cmd.count(
"ostree-server") != 0) {
247 pacman.ostree_server = cmd[
"ostree-server"].as<std::string>();
249 if (cmd.count(
"primary-ecu-serial") != 0) {
250 provision.primary_ecu_serial = cmd[
"primary-ecu-serial"].as<std::string>();
252 if (cmd.count(
"primary-ecu-hardware-id") != 0) {
253 provision.primary_ecu_hardware_id = cmd[
"primary-ecu-hardware-id"].as<std::string>();
255 if (cmd.count(
"secondary-config") != 0) {
256 std::vector<boost::filesystem::path> sconfigs = cmd[
"secondary-config"].as<std::vector<boost::filesystem::path>>();
257 readSecondaryConfigs(sconfigs);
259 if (cmd.count(
"legacy-interface") != 0) {
260 uptane.legacy_interface = cmd[
"legacy-interface"].as<boost::filesystem::path>();
264 void Config::readSecondaryConfigs(
const std::vector<boost::filesystem::path>& sconfigs) {
265 for (
auto it = sconfigs.cbegin(); it != sconfigs.cend(); ++it) {
270 void Config::checkLegacyVersion() {
271 if (uptane.legacy_interface.empty()) {
274 if (!boost::filesystem::exists(uptane.legacy_interface)) {
275 throw FatalException(std::string(
"Legacy external flasher not found: ") + uptane.legacy_interface.string());
277 std::stringstream command;
279 command << uptane.legacy_interface <<
" api-version --loglevel " << loggerGetSeverity();
280 int rs = Utils::shell(command.str(), &output);
282 throw FatalException(std::string(
"Legacy external flasher api-version command failed: ") + output);
284 boost::trim_if(output, boost::is_any_of(
" \n\r\t"));
286 throw FatalException(std::string(
"Unexpected legacy external flasher API version: ") + output);
290 void Config::initLegacySecondaries() {
291 if (uptane.legacy_interface.empty()) {
294 std::stringstream command;
296 command << uptane.legacy_interface <<
" list-ecus --loglevel " << loggerGetSeverity();
297 int rs = Utils::shell(command.str(), &output);
299 LOG_ERROR <<
"Legacy external flasher list-ecus command failed: " << output;
303 std::stringstream ss(output);
305 while (std::getline(ss, buffer,
'\n')) {
307 sconfig.secondary_type = Uptane::SecondaryType::kLegacy;
308 std::vector<std::string> ecu_info;
309 boost::split(ecu_info, buffer, boost::is_any_of(
" \n\r\t"), boost::token_compress_on);
310 if (ecu_info.size() == 0) {
314 if (ecu_info.size() == 1) {
315 sconfig.ecu_hardware_id = ecu_info[0];
317 sconfig.ecu_serial =
"";
318 sconfig.full_client_dir = storage.path / sconfig.ecu_hardware_id;
319 LOG_INFO <<
"Legacy ECU configured with hardware ID " << sconfig.ecu_hardware_id;
320 }
else if (ecu_info.size() >= 2) {
322 sconfig.ecu_hardware_id = ecu_info[0];
323 sconfig.ecu_serial = ecu_info[1];
324 sconfig.full_client_dir = storage.path / (sconfig.ecu_hardware_id +
"-" + sconfig.ecu_serial);
325 LOG_INFO <<
"Legacy ECU configured with hardware ID " << sconfig.ecu_hardware_id <<
" and serial " 326 << sconfig.ecu_serial;
329 sconfig.partial_verifying =
false;
330 sconfig.ecu_private_key =
"sec.private";
331 sconfig.ecu_public_key =
"sec.public";
333 sconfig.firmware_path = sconfig.full_client_dir /
"firmware.bin";
334 sconfig.metadata_path = sconfig.full_client_dir /
"metadata";
335 sconfig.target_name_path = sconfig.full_client_dir /
"target_name";
336 sconfig.flasher = uptane.legacy_interface;
338 uptane.secondary_configs.push_back(sconfig);
342 void Config::writeToStream(std::ostream& sink)
const {
345 WriteSectionToStream(logger,
"logger", sink);
346 WriteSectionToStream(network,
"network", sink);
347 WriteSectionToStream(p11,
"p11", sink);
348 WriteSectionToStream(tls,
"tls", sink);
349 WriteSectionToStream(provision,
"provision", sink);
350 WriteSectionToStream(uptane,
"uptane", sink);
351 WriteSectionToStream(discovery,
"discovery", sink);
352 WriteSectionToStream(pacman,
"pacman", sink);
353 WriteSectionToStream(storage,
"storage", sink);
354 WriteSectionToStream(
import,
"import", sink);
355 WriteSectionToStream(telemetry,
"telemetry", sink);
356 WriteSectionToStream(bootloader,
"bootloader", sink);
360 ser << asn1::implicit<kAsn1Enum>(
static_cast<const int32_t&
>(
static_cast<int>(cs)));
366 ser << asn1::seq << asn1::implicit<kAsn1Utf8String>(tls_conf.server)
367 << asn1::implicit<kAsn1Utf8String>(tls_conf.server_url_path.string()) << tls_conf.ca_source
368 << tls_conf.pkey_source << tls_conf.cert_source << asn1::endseq;
374 des >> asn1::implicit<kAsn1Enum>(cs_i);
376 if (cs_i < static_cast<int>(CryptoSource::kFile) || cs_i >
static_cast<int>(CryptoSource::kPkcs11)) {
380 cs =
static_cast<CryptoSource
>(cs_i);
386 std::string path_string;
387 des >> asn1::implicit<kAsn1Utf8String>(path_string);
393 des >> asn1::seq >> asn1::implicit<kAsn1Utf8String>(tls_conf.server) >> tls_conf.server_url_path >>
394 tls_conf.ca_source >> tls_conf.pkey_source >> tls_conf.cert_source >> asn1::endseq;
Configuration object for an aktualizr instance running on a primary ECU.