• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender / 1022753986

02 Oct 2023 10:37AM UTC coverage: 78.168% (-2.0%) from 80.127%
1022753986

push

gitlab-ci

oleorhagen
feat: Run the authentication loop once upon bootstrap

Ticket: MEN-6658
Changelog: None

Signed-off-by: Ole Petter <ole.orhagen@northern.tech>

32 of 32 new or added lines in 1 file covered. (100.0%)

6996 of 8950 relevant lines covered (78.17%)

10353.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.33
/common/config_parser/config_parser.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <common/config_parser.hpp>
16

17
#include <string>
18
#include <vector>
19
#include <algorithm>
20

21
#include <common/json.hpp>
22
#include <common/log.hpp>
23

24
namespace mender {
25
namespace common {
26
namespace config_parser {
27

28
using namespace std;
29

30
namespace json = mender::common::json;
31
namespace log = mender::common::log;
32

33
const ConfigParserErrorCategoryClass ConfigParserErrorCategory;
34

35
const char *ConfigParserErrorCategoryClass::name() const noexcept {
×
36
        return "ConfigParserErrorCategory";
×
37
}
38

39
string ConfigParserErrorCategoryClass::message(int code) const {
×
40
        switch (code) {
×
41
        case NoError:
×
42
                return "Success";
×
43
        case ValidationError:
×
44
                return "Validation error";
×
45
        default:
×
46
                return "Unknown";
×
47
        }
48
}
49

50
error::Error MakeError(ConfigParserErrorCode code, const string &msg) {
3✔
51
        return error::Error(error_condition(code, ConfigParserErrorCategory), msg);
6✔
52
}
53

54
ExpectedBool MenderConfigFromFile::ValidateArtifactKeyCondition() const {
3✔
55
        if (artifact_verify_key.size() != 0) {
3✔
56
                if (artifact_verify_keys.size() != 0) {
2✔
57
                        auto err = MakeError(
58
                                ConfigParserErrorCode::ValidationError,
59
                                "Both 'ArtifactVerifyKey' and 'ArtifactVerifyKeys' are set");
2✔
60
                        return expected::unexpected(err);
2✔
61
                }
62
        }
63
        return true;
2✔
64
}
65

66
ExpectedBool MenderConfigFromFile::ValidateServerConfig() const {
3✔
67
        if (server_url.size() != 0 && servers.size() != 0) {
3✔
68
                auto err = MakeError(
69
                        ConfigParserErrorCode::ValidationError,
70
                        "Both 'Servers' AND 'ServerURL given in the configuration. Please set only one of these fields");
2✔
71
                return expected::unexpected(err);
2✔
72
        }
73

74
        if (servers.size() == 0) {
2✔
75
                if (server_url.size() == 0) {
1✔
76
                        log::Warning(
×
77
                                "No ServerURL found in the configuration. The client will not be able to download updates");
×
78
                }
79
        }
80
        return true;
2✔
81
}
82

83
ExpectedBool MenderConfigFromFile::LoadFile(const string &path) {
217✔
84
        const json::ExpectedJson e_cfg_json = json::LoadFromFile(path);
434✔
85
        if (!e_cfg_json) {
217✔
86
                auto err = e_cfg_json.error();
205✔
87
                return expected::unexpected(err);
410✔
88
        }
89

90
        bool applied = false;
12✔
91

92
        /* Deal with plain string values first */
93
        const json::Json cfg_json = e_cfg_json.value();
24✔
94
        json::ExpectedJson e_cfg_value = cfg_json.Get("ArtifactVerifyKey");
24✔
95
        if (e_cfg_value) {
12✔
96
                const json::Json value_json = e_cfg_value.value();
20✔
97
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
98
                if (e_cfg_string) {
10✔
99
                        this->artifact_verify_key = e_cfg_string.value();
10✔
100
                        applied = true;
10✔
101
                }
102
        }
103

104
        e_cfg_value = cfg_json.Get("RootfsPartA");
12✔
105
        if (e_cfg_value) {
12✔
106
                const json::Json value_json = e_cfg_value.value();
16✔
107
                const json::ExpectedString e_cfg_string = value_json.GetString();
16✔
108
                if (e_cfg_string) {
8✔
109
                        this->rootfs_part_A = e_cfg_string.value();
7✔
110
                        applied = true;
7✔
111
                }
112
        }
113

114
        e_cfg_value = cfg_json.Get("RootfsPartB");
12✔
115
        if (e_cfg_value) {
12✔
116
                const json::Json value_json = e_cfg_value.value();
20✔
117
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
118
                if (e_cfg_string) {
10✔
119
                        this->rootfs_part_B = e_cfg_string.value();
10✔
120
                        applied = true;
10✔
121
                }
122
        }
123

124
        e_cfg_value = cfg_json.Get("BootUtilitiesSetActivePart");
12✔
125
        if (e_cfg_value) {
12✔
126
                const json::Json value_json = e_cfg_value.value();
20✔
127
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
128
                if (e_cfg_string) {
10✔
129
                        this->boot_utilities_set_active_part = e_cfg_string.value();
10✔
130
                        applied = true;
10✔
131
                }
132
        }
133

134
        e_cfg_value = cfg_json.Get("BootUtilitiesGetNextActivePart");
12✔
135
        if (e_cfg_value) {
12✔
136
                const json::Json value_json = e_cfg_value.value();
14✔
137
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
138
                if (e_cfg_string) {
7✔
139
                        this->boot_utilities_get_next_active_part = e_cfg_string.value();
7✔
140
                        applied = true;
7✔
141
                }
142
        }
143

144
        e_cfg_value = cfg_json.Get("DeviceTypeFile");
12✔
145
        if (e_cfg_value) {
12✔
146
                const json::Json value_json = e_cfg_value.value();
20✔
147
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
148
                if (e_cfg_string) {
10✔
149
                        this->device_type_file = e_cfg_string.value();
10✔
150
                        applied = true;
10✔
151
                }
152
        }
153

154
        e_cfg_value = cfg_json.Get("ServerCertificate");
12✔
155
        if (e_cfg_value) {
12✔
156
                const json::Json value_json = e_cfg_value.value();
14✔
157
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
158
                if (e_cfg_string) {
7✔
159
                        this->server_certificate = e_cfg_string.value();
7✔
160
                        applied = true;
7✔
161
                }
162
        }
163

164
        e_cfg_value = cfg_json.Get("ServerURL");
12✔
165
        if (e_cfg_value) {
12✔
166
                const json::Json value_json = e_cfg_value.value();
20✔
167
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
168
                if (e_cfg_string) {
10✔
169
                        this->server_url = e_cfg_string.value();
10✔
170
                        applied = true;
10✔
171
                }
172
        }
173

174
        e_cfg_value = cfg_json.Get("UpdateLogPath");
12✔
175
        if (e_cfg_value) {
12✔
176
                const json::Json value_json = e_cfg_value.value();
14✔
177
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
178
                if (e_cfg_string) {
7✔
179
                        this->update_log_path = e_cfg_string.value();
7✔
180
                        applied = true;
7✔
181
                }
182
        }
183

184
        e_cfg_value = cfg_json.Get("TenantToken");
12✔
185
        if (e_cfg_value) {
12✔
186
                const json::Json value_json = e_cfg_value.value();
14✔
187
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
188
                if (e_cfg_string) {
7✔
189
                        this->tenant_token = e_cfg_string.value();
7✔
190
                        applied = true;
7✔
191
                }
192
        }
193

194
        e_cfg_value = cfg_json.Get("DaemonLogLevel");
12✔
195
        if (e_cfg_value) {
12✔
196
                const json::Json value_json = e_cfg_value.value();
14✔
197
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
198
                if (e_cfg_string) {
7✔
199
                        this->daemon_log_level = e_cfg_string.value();
7✔
200
                        applied = true;
7✔
201
                }
202
        }
203

204
        /* Boolean values now */
205
        e_cfg_value = cfg_json.Get("SkipVerify");
12✔
206
        if (e_cfg_value) {
12✔
207
                const json::Json value_json = e_cfg_value.value();
18✔
208
                const json::ExpectedBool e_cfg_bool = value_json.GetBool();
18✔
209
                if (e_cfg_bool) {
9✔
210
                        this->skip_verify = e_cfg_bool.value();
9✔
211
                        applied = true;
9✔
212
                }
213
        }
214

215
        e_cfg_value = cfg_json.Get("DBus");
12✔
216
        if (e_cfg_value) {
12✔
217
                const json::Json value_json = e_cfg_value.value();
14✔
218
                const json::ExpectedJson e_cfg_subval = value_json.Get("Enabled");
14✔
219
                if (e_cfg_subval) {
7✔
220
                        const json::Json subval_json = e_cfg_subval.value();
14✔
221
                        const json::ExpectedBool e_cfg_bool = subval_json.GetBool();
14✔
222
                        if (e_cfg_bool) {
7✔
223
                                this->dbus_enabled = e_cfg_bool.value();
7✔
224
                                applied = true;
7✔
225
                        }
226
                }
227
        }
228

229
        /* Integer values */
230
        e_cfg_value = cfg_json.Get("UpdateControlMapExpirationTimeSeconds");
12✔
231
        if (e_cfg_value) {
12✔
232
                const json::Json value_json = e_cfg_value.value();
14✔
233
                const auto e_cfg_int = value_json.GetInt();
14✔
234
                if (e_cfg_int) {
7✔
235
                        this->update_control_map_expiration_time_seconds = e_cfg_int.value();
7✔
236
                        applied = true;
7✔
237
                }
238
        }
239

240
        e_cfg_value = cfg_json.Get("UpdateControlMapBootExpirationTimeSeconds");
12✔
241
        if (e_cfg_value) {
12✔
242
                const json::Json value_json = e_cfg_value.value();
14✔
243
                const auto e_cfg_int = value_json.GetInt();
14✔
244
                if (e_cfg_int) {
7✔
245
                        this->update_control_map_boot_expiration_time_seconds = e_cfg_int.value();
7✔
246
                        applied = true;
7✔
247
                }
248
        }
249

250
        e_cfg_value = cfg_json.Get("UpdatePollIntervalSeconds");
12✔
251
        if (e_cfg_value) {
12✔
252
                const json::Json value_json = e_cfg_value.value();
14✔
253
                const auto e_cfg_int = value_json.GetInt();
14✔
254
                if (e_cfg_int) {
7✔
255
                        this->update_poll_interval_seconds = e_cfg_int.value();
7✔
256
                        applied = true;
7✔
257
                }
258
        }
259

260
        e_cfg_value = cfg_json.Get("InventoryPollIntervalSeconds");
12✔
261
        if (e_cfg_value) {
12✔
262
                const json::Json value_json = e_cfg_value.value();
14✔
263
                const auto e_cfg_int = value_json.GetInt();
14✔
264
                if (e_cfg_int) {
7✔
265
                        this->inventory_poll_interval_seconds = e_cfg_int.value();
7✔
266
                        applied = true;
7✔
267
                }
268
        }
269

270
        e_cfg_value = cfg_json.Get("RetryPollIntervalSeconds");
12✔
271
        if (e_cfg_value) {
12✔
272
                const json::Json value_json = e_cfg_value.value();
14✔
273
                const auto e_cfg_int = value_json.GetInt();
14✔
274
                if (e_cfg_int) {
7✔
275
                        this->retry_poll_interval_seconds = e_cfg_int.value();
7✔
276
                        applied = true;
7✔
277
                }
278
        }
279

280
        e_cfg_value = cfg_json.Get("RetryPollCount");
12✔
281
        if (e_cfg_value) {
12✔
282
                const json::Json value_json = e_cfg_value.value();
14✔
283
                const auto e_cfg_int = value_json.GetInt();
14✔
284
                if (e_cfg_int) {
7✔
285
                        this->retry_poll_count = e_cfg_int.value();
7✔
286
                        applied = true;
7✔
287
                }
288
        }
289

290
        e_cfg_value = cfg_json.Get("StateScriptTimeoutSeconds");
12✔
291
        if (e_cfg_value) {
12✔
292
                const json::Json value_json = e_cfg_value.value();
14✔
293
                const auto e_cfg_int = value_json.GetInt();
14✔
294
                if (e_cfg_int) {
7✔
295
                        this->state_script_timeout_seconds = e_cfg_int.value();
7✔
296
                        applied = true;
7✔
297
                }
298
        }
299

300
        e_cfg_value = cfg_json.Get("StateScriptRetryTimeoutSeconds");
12✔
301
        if (e_cfg_value) {
12✔
302
                const json::Json value_json = e_cfg_value.value();
14✔
303
                const auto e_cfg_int = value_json.GetInt();
14✔
304
                if (e_cfg_int) {
7✔
305
                        this->state_script_retry_timeout_seconds = e_cfg_int.value();
7✔
306
                        applied = true;
7✔
307
                }
308
        }
309

310
        e_cfg_value = cfg_json.Get("StateScriptRetryIntervalSeconds");
12✔
311
        if (e_cfg_value) {
12✔
312
                const json::Json value_json = e_cfg_value.value();
14✔
313
                const auto e_cfg_int = value_json.GetInt();
14✔
314
                if (e_cfg_int) {
7✔
315
                        this->state_script_retry_interval_seconds = e_cfg_int.value();
7✔
316
                        applied = true;
7✔
317
                }
318
        }
319

320
        e_cfg_value = cfg_json.Get("ModuleTimeoutSeconds");
12✔
321
        if (e_cfg_value) {
12✔
322
                const json::Json value_json = e_cfg_value.value();
14✔
323
                const auto e_cfg_int = value_json.GetInt();
14✔
324
                if (e_cfg_int) {
7✔
325
                        this->module_timeout_seconds = e_cfg_int.value();
7✔
326
                        applied = true;
7✔
327
                }
328
        }
329

330
        /* Vectors/arrays now */
331
        e_cfg_value = cfg_json.Get("ArtifactVerifyKeys");
12✔
332
        if (e_cfg_value) {
12✔
333
                const json::Json value_array = e_cfg_value.value();
16✔
334
                const json::ExpectedSize e_n_items = value_array.GetArraySize();
16✔
335
                if (e_n_items) {
8✔
336
                        for (size_t i = 0; i < e_n_items.value(); i++) {
31✔
337
                                const json::ExpectedJson e_array_item = value_array.Get(i);
46✔
338
                                if (e_array_item) {
23✔
339
                                        const json::ExpectedString e_item_string = e_array_item.value().GetString();
46✔
340
                                        if (e_item_string) {
23✔
341
                                                const string item_value = e_item_string.value();
46✔
342
                                                if (count(
23✔
343
                                                                this->artifact_verify_keys.begin(),
344
                                                                this->artifact_verify_keys.end(),
345
                                                                item_value)
346
                                                        == 0) {
23✔
347
                                                        this->artifact_verify_keys.push_back(item_value);
23✔
348
                                                        applied = true;
23✔
349
                                                }
350
                                        }
351
                                }
352
                        }
353
                }
354
        }
355

356
        e_cfg_value = cfg_json.Get("Servers");
12✔
357
        if (e_cfg_value) {
12✔
358
                const json::Json value_array = e_cfg_value.value();
16✔
359
                const json::ExpectedSize e_n_items = value_array.GetArraySize();
16✔
360
                if (e_n_items) {
8✔
361
                        for (size_t i = 0; i < e_n_items.value(); i++) {
23✔
362
                                const json::ExpectedJson e_array_item = value_array.Get(i);
30✔
363
                                if (e_array_item) {
15✔
364
                                        const json::ExpectedJson e_item_json = e_array_item.value().Get("ServerURL");
30✔
365
                                        if (e_item_json) {
15✔
366
                                                const json::ExpectedString e_item_string = e_item_json.value().GetString();
30✔
367
                                                if (e_item_string) {
15✔
368
                                                        const string item_value = e_item_string.value();
30✔
369
                                                        if (count(this->servers.begin(), this->servers.end(), item_value)
15✔
370
                                                                == 0) {
15✔
371
                                                                this->servers.push_back(std::move(item_value));
15✔
372
                                                                applied = true;
15✔
373
                                                        }
374
                                                }
375
                                        }
376
                                }
377
                        }
378
                }
379
        }
380

381
        /* Last but not least, complex values */
382
        e_cfg_value = cfg_json.Get("HttpsClient");
12✔
383
        if (e_cfg_value) {
12✔
384
                const json::Json value_json = e_cfg_value.value();
16✔
385
                json::ExpectedJson e_cfg_subval = value_json.Get("Certificate");
16✔
386
                if (e_cfg_subval) {
8✔
387
                        const json::Json subval_json = e_cfg_subval.value();
16✔
388
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
16✔
389
                        if (e_cfg_string) {
8✔
390
                                this->https_client.certificate = e_cfg_string.value();
8✔
391
                                applied = true;
8✔
392
                        }
393
                }
394

395
                e_cfg_subval = value_json.Get("Key");
8✔
396
                if (e_cfg_subval) {
8✔
397
                        const json::Json subval_json = e_cfg_subval.value();
14✔
398
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
399
                        if (e_cfg_string) {
7✔
400
                                this->https_client.key = e_cfg_string.value();
7✔
401
                                applied = true;
7✔
402
                        }
403
                }
404

405
                e_cfg_subval = value_json.Get("SSLEngine");
8✔
406
                if (e_cfg_subval) {
8✔
407
                        const json::Json subval_json = e_cfg_subval.value();
14✔
408
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
409
                        if (e_cfg_string) {
7✔
410
                                this->https_client.ssl_engine = e_cfg_string.value();
7✔
411
                                applied = true;
7✔
412
                        }
413
                }
414
        }
415

416
        e_cfg_value = cfg_json.Get("Security");
12✔
417
        if (e_cfg_value) {
12✔
418
                const json::Json value_json = e_cfg_value.value();
14✔
419
                json::ExpectedJson e_cfg_subval = value_json.Get("AuthPrivateKey");
14✔
420
                if (e_cfg_subval) {
7✔
421
                        const json::Json subval_json = e_cfg_subval.value();
14✔
422
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
423
                        if (e_cfg_string) {
7✔
424
                                this->security.auth_private_key = e_cfg_string.value();
7✔
425
                                applied = true;
7✔
426
                        }
427
                }
428

429
                e_cfg_subval = value_json.Get("SSLEngine");
7✔
430
                if (e_cfg_subval) {
7✔
431
                        const json::Json subval_json = e_cfg_subval.value();
14✔
432
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
433
                        if (e_cfg_string) {
7✔
434
                                this->security.ssl_engine = e_cfg_string.value();
7✔
435
                                applied = true;
7✔
436
                        }
437
                }
438
        }
439

440
        e_cfg_value = cfg_json.Get("Connectivity");
12✔
441
        if (e_cfg_value) {
12✔
442
                const json::Json value_json = e_cfg_value.value();
16✔
443
                json::ExpectedJson e_cfg_subval = value_json.Get("DisableKeepAlive");
16✔
444
                if (e_cfg_subval) {
8✔
445
                        const json::Json subval_json = e_cfg_subval.value();
16✔
446
                        const json::ExpectedBool e_cfg_bool = subval_json.GetBool();
16✔
447
                        if (e_cfg_bool) {
8✔
448
                                this->connectivity.disable_keep_alive = e_cfg_bool.value();
8✔
449
                                applied = true;
8✔
450
                        }
451
                }
452

453
                e_cfg_subval = value_json.Get("IdleConnTimeoutSeconds");
8✔
454
                if (e_cfg_subval) {
8✔
455
                        const json::Json subval_json = e_cfg_subval.value();
16✔
456
                        const auto e_cfg_int = subval_json.GetInt();
16✔
457
                        if (e_cfg_int) {
8✔
458
                                this->connectivity.idle_conn_timeout_seconds = e_cfg_int.value();
8✔
459
                                applied = true;
8✔
460
                        }
461
                }
462
        }
463

464
        return applied;
12✔
465
}
466

467
void MenderConfigFromFile::Reset() {
1✔
468
        *this = MenderConfigFromFile();
1✔
469
}
1✔
470

471
ExpectedBool MenderConfigFromFile::ValidateConfig() {
×
472
        auto ak_conf = this->ValidateArtifactKeyCondition();
×
473
        if (!ak_conf) {
×
474
                return ak_conf;
×
475
        }
476
        auto server_conf = this->ValidateServerConfig();
×
477
        if (!server_conf) {
×
478
                return server_conf;
×
479
        }
480
        return true;
×
481
}
482

483

484

485
} // namespace config_parser
486
} // namespace common
487
} // namespace mender
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc