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