Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
config.cc
1 #include "config.h"
2 
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <iomanip>
6 #include <sstream>
7 
8 #include "bootstrap/bootstrap.h"
9 #include "config.h"
10 #include "utilities/exceptions.h"
11 #include "utilities/utils.h"
12 
13 void TlsConfig::updateFromPropertyTree(const boost::property_tree::ptree& pt) {
14  CopyFromConfig(server, "server", pt);
15  CopyFromConfig(server_url_path, "server_url_path", pt);
16  CopyFromConfig(ca_source, "ca_source", pt);
17  CopyFromConfig(cert_source, "cert_source", pt);
18  CopyFromConfig(pkey_source, "pkey_source", pt);
19 }
20 
21 void TlsConfig::writeToStream(std::ostream& out_stream) const {
22  writeOption(out_stream, server, "server");
23  writeOption(out_stream, server_url_path, "server_url_path");
24  writeOption(out_stream, ca_source, "ca_source");
25  writeOption(out_stream, pkey_source, "pkey_source");
26  writeOption(out_stream, cert_source, "cert_source");
27 }
28 
29 void ProvisionConfig::updateFromPropertyTree(const boost::property_tree::ptree& pt) {
30  CopyFromConfig(server, "server", pt);
31  CopyFromConfig(p12_password, "p12_password", pt);
32  CopyFromConfig(expiry_days, "expiry_days", pt);
33  CopyFromConfig(provision_path, "provision_path", pt);
34  CopyFromConfig(device_id, "device_id", pt);
35  CopyFromConfig(primary_ecu_serial, "primary_ecu_serial", pt);
36  CopyFromConfig(primary_ecu_hardware_id, "primary_ecu_hardware_id", pt);
37  CopyFromConfig(ecu_registration_endpoint, "ecu_registration_endpoint", pt);
38  // provision.mode is set in postUpdateValues.
39 }
40 
41 void ProvisionConfig::writeToStream(std::ostream& out_stream) const {
42  writeOption(out_stream, server, "server");
43  writeOption(out_stream, p12_password, "p12_password");
44  writeOption(out_stream, expiry_days, "expiry_days");
45  writeOption(out_stream, provision_path, "provision_path");
46  writeOption(out_stream, device_id, "device_id");
47  writeOption(out_stream, primary_ecu_serial, "primary_ecu_serial");
48  writeOption(out_stream, primary_ecu_hardware_id, "primary_ecu_hardware_id");
49  writeOption(out_stream, ecu_registration_endpoint, "ecu_registration_endpoint");
50  // Skip provision.mode since it is dependent on other options.
51 }
52 
53 void UptaneConfig::updateFromPropertyTree(const boost::property_tree::ptree& pt) {
54  CopyFromConfig(polling_sec, "polling_sec", pt);
55  CopyFromConfig(director_server, "director_server", pt);
56  CopyFromConfig(repo_server, "repo_server", pt);
57  CopyFromConfig(key_source, "key_source", pt);
58  CopyFromConfig(key_type, "key_type", pt);
59  CopyFromConfig(force_install_completion, "force_install_completion", pt);
60  CopyFromConfig(secondary_config_file, "secondary_config_file", pt);
61 }
62 
63 void UptaneConfig::writeToStream(std::ostream& out_stream) const {
64  writeOption(out_stream, polling_sec, "polling_sec");
65  writeOption(out_stream, director_server, "director_server");
66  writeOption(out_stream, repo_server, "repo_server");
67  writeOption(out_stream, key_source, "key_source");
68  writeOption(out_stream, key_type, "key_type");
69  writeOption(out_stream, force_install_completion, "force_install_completion");
70  writeOption(out_stream, secondary_config_file, "secondary_config_file");
71 }
72 
73 /**
74  * \par Description:
75  * Overload the << operator for the configuration class allowing
76  * us to print its content, i.e. for logging purposes.
77  */
78 std::ostream& operator<<(std::ostream& os, const Config& cfg) {
79  cfg.writeToStream(os);
80  return os;
81 }
82 
83 Config::Config() { postUpdateValues(); }
84 
85 Config::Config(const boost::filesystem::path& filename) {
86  updateFromToml(filename);
87  postUpdateValues();
88 }
89 
90 Config::Config(const std::vector<boost::filesystem::path>& config_dirs) {
91  checkDirs(config_dirs);
92  updateFromDirs(config_dirs);
93  postUpdateValues();
94 }
95 
96 Config::Config(const boost::program_options::variables_map& cmd) {
97  // Redundantly check and set the loglevel from the commandline prematurely so
98  // that it is taken account while processing the config.
99  if (cmd.count("loglevel") != 0) {
100  logger.loglevel = cmd["loglevel"].as<int>();
101  logger_set_threshold(logger);
102  loglevel_from_cmdline = true;
103  }
104 
105  if (cmd.count("config") > 0) {
106  const auto configs = cmd["config"].as<std::vector<boost::filesystem::path>>();
107  checkDirs(configs);
108  updateFromDirs(configs);
109  } else {
110  updateFromDirs(config_dirs_);
111  }
112  updateFromCommandLine(cmd);
113  postUpdateValues();
114 }
115 
116 KeyManagerConfig Config::keymanagerConfig() const {
117  return KeyManagerConfig{p11, tls.ca_source, tls.pkey_source, tls.cert_source, uptane.key_type, uptane.key_source};
118 }
119 
120 void Config::postUpdateValues() {
121  logger_set_threshold(logger);
122 
123  provision.mode = provision.provision_path.empty() ? ProvisionMode::kDeviceCred : ProvisionMode::kSharedCred;
124 
125  if (tls.server.empty()) {
126  if (!tls.server_url_path.empty()) {
127  try {
128  tls.server = Utils::readFile(tls.server_url_path, true);
129  } catch (const boost::filesystem::filesystem_error& e) {
130  LOG_ERROR << "Couldn't read gateway URL: " << e.what();
131  tls.server = "";
132  }
133  } else if (!provision.provision_path.empty()) {
134  if (boost::filesystem::exists(provision.provision_path)) {
135  tls.server = Bootstrap::readServerUrl(provision.provision_path);
136  } else {
137  LOG_ERROR << "Provided provision archive " << provision.provision_path << " does not exist!";
138  }
139  }
140  }
141 
142  if (!tls.server.empty()) {
143  if (provision.server.empty()) {
144  provision.server = tls.server;
145  }
146 
147  if (uptane.repo_server.empty()) {
148  uptane.repo_server = tls.server + "/repo";
149  }
150 
151  if (uptane.director_server.empty()) {
152  uptane.director_server = tls.server + "/director";
153  }
154 
155  if (pacman.ostree_server.empty()) {
156  pacman.ostree_server = tls.server + "/treehub";
157  }
158  }
159 
160  if (!uptane.director_server.empty()) {
161  if (provision.ecu_registration_endpoint.empty()) {
162  provision.ecu_registration_endpoint = uptane.director_server + "/ecus";
163  }
164  }
165 
166  LOG_TRACE << "Final configuration that will be used: \n" << (*this);
167 }
168 
169 // For testing
170 void Config::updateFromTomlString(const std::string& contents) {
171  boost::property_tree::ptree pt;
172  std::stringstream stream(contents);
173  boost::property_tree::ini_parser::read_ini(stream, pt);
174  updateFromPropertyTree(pt);
175 }
176 
177 void Config::updateFromPropertyTree(const boost::property_tree::ptree& pt) {
178  // Keep this order the same as in config.h and Config::writeToStream().
179  if (!loglevel_from_cmdline) {
180  CopySubtreeFromConfig(logger, "logger", pt);
181  // If not already set from the commandline, set the loglevel now so that it
182  // affects the rest of the config processing.
183  logger_set_threshold(logger);
184  }
185  CopySubtreeFromConfig(p11, "p11", pt);
186  CopySubtreeFromConfig(tls, "tls", pt);
187  CopySubtreeFromConfig(provision, "provision", pt);
188  CopySubtreeFromConfig(uptane, "uptane", pt);
189  CopySubtreeFromConfig(pacman, "pacman", pt);
190  CopySubtreeFromConfig(storage, "storage", pt);
191  CopySubtreeFromConfig(import, "import", pt);
192  CopySubtreeFromConfig(telemetry, "telemetry", pt);
193  CopySubtreeFromConfig(bootloader, "bootloader", pt);
194 }
195 
196 void Config::updateFromCommandLine(const boost::program_options::variables_map& cmd) {
197  // Try to keep these options in the same order as parse_options() in main.cc.
198  if (cmd.count("loglevel") != 0) {
199  logger.loglevel = cmd["loglevel"].as<int>();
200  }
201  if (cmd.count("tls-server") != 0) {
202  tls.server = cmd["tls-server"].as<std::string>();
203  }
204  if (cmd.count("repo-server") != 0) {
205  uptane.repo_server = cmd["repo-server"].as<std::string>();
206  }
207  if (cmd.count("director-server") != 0) {
208  uptane.director_server = cmd["director-server"].as<std::string>();
209  }
210  if (cmd.count("ostree-server") != 0) {
211  pacman.ostree_server = cmd["ostree-server"].as<std::string>();
212  }
213  if (cmd.count("primary-ecu-serial") != 0) {
214  provision.primary_ecu_serial = cmd["primary-ecu-serial"].as<std::string>();
215  }
216  if (cmd.count("primary-ecu-hardware-id") != 0) {
217  provision.primary_ecu_hardware_id = cmd["primary-ecu-hardware-id"].as<std::string>();
218  }
219  if (cmd.count("secondary-config-file") != 0) {
220  uptane.secondary_config_file = cmd["secondary_config_file"].as<boost::filesystem::path>();
221  }
222 }
223 
224 void Config::writeToStream(std::ostream& sink) const {
225  // Keep this order the same as in config.h and
226  // Config::updateFromPropertyTree().
227  WriteSectionToStream(logger, "logger", sink);
228  WriteSectionToStream(p11, "p11", sink);
229  WriteSectionToStream(tls, "tls", sink);
230  WriteSectionToStream(provision, "provision", sink);
231  WriteSectionToStream(uptane, "uptane", sink);
232  WriteSectionToStream(pacman, "pacman", sink);
233  WriteSectionToStream(storage, "storage", sink);
234  WriteSectionToStream(import, "import", sink);
235  WriteSectionToStream(telemetry, "telemetry", sink);
236  WriteSectionToStream(bootloader, "bootloader", sink);
237 }
Config
Configuration object for an aktualizr instance running on a primary ECU.
Definition: config.h:73
KeyManagerConfig
Definition: keymanager_config.h:9