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

mendersoftware / mender / 1034821089

12 Oct 2023 02:46PM UTC coverage: 79.922% (+0.3%) from 79.579%
1034821089

push

gitlab-ci

lluiscampos
fix: Implement `--trusted-certs` and `--skip-verify` cli options

Changelog: None
Ticket: MEN-6679

Signed-off-by: Lluis Campos <lluis.campos@northern.tech>

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

6592 of 8248 relevant lines covered (79.92%)

9744.95 hits per line

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

53.03
/mender-auth/cli/cli.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 <mender-auth/cli/cli.hpp>
16

17
#include <string>
18

19
#include <common/conf.hpp>
20
#include <common/expected.hpp>
21
#include <common/io.hpp>
22
#include <common/setup.hpp>
23
#include <common/cli.hpp>
24
#include <mender-version.h>
25

26
#include <mender-auth/cli/actions.hpp>
27
#include <mender-auth/context.hpp>
28
#include <mender-auth/ipc/server.hpp>
29

30
namespace mender {
31
namespace auth {
32
namespace cli {
33

34
using namespace std;
35

36
namespace conf = mender::common::conf;
37
namespace expected = mender::common::expected;
38
namespace io = mender::common::io;
39
namespace setup = mender::common::setup;
40

41
namespace context = mender::auth::context;
42
namespace ipc = mender::auth::ipc;
43
namespace cli = mender::common::cli;
44

45
const vector<cli::Option> opts_bootstrap_daemon {
46
        cli::Option {
47
                .long_option = "forcebootstrap",
48
                .short_option = "F",
49
                .description = "Force bootstrap",
50
        },
51
        cli::Option {
52
                .long_option = "passphrase-file",
53
                .description =
54
                        "Passphrase file for decrypting an encrypted private key. '-' loads passphrase from stdin",
55
                .default_value = "''",
56
        },
57
};
58

59
const cli::Command cmd_bootstrap {
60
        .name = "bootstrap",
61
        .description = "Perform bootstrap and exit",
62
        .options = opts_bootstrap_daemon,
63
};
64

65
const cli::Command cmd_daemon {
66
        .name = "daemon",
67
        .description = "Start the client as a background service",
68
        .options = opts_bootstrap_daemon,
69
};
70

71
const conf::Paths default_paths {};
72

73
const cli::App cli_mender_auth = {
74
        .name = "mender-auth",
75
        .short_description = "manage and start Mender Auth",
76
        .long_description =
77
                R"(mender-auth integrates both the mender-auth daemon and commands for manually
78
   performing tasks performed by the daemon (see list of COMMANDS below).
79

80
Global flag remarks:
81
   - Supported log levels incudes: 'debug', 'info', 'warning', 'error', 'panic' and
82
     'fatal'.
83

84
Environment variables:
85
   - MENDER_CONF_DIR - configuration (default: )"
86
                + default_paths.GetPathConfDir() + R"().
87
   - MENDER_DATA_DIR - identity, inventory and update modules (default: )"
88
                + default_paths.GetPathDataDir() + R"().
89
   - MENDER_DATASTORE_DIR - runtime datastore (default: )"
90
                + default_paths.GetDataStore() + R"().)",
91
        .version = string {MENDER_VERSION},
92
        .commands =
93
                {
94
                        cmd_bootstrap,
95
                        cmd_daemon,
96
                },
97
        .global_options =
98
                {
99
                        cli::Option {
100
                                .long_option = "config",
101
                                .short_option = "c",
102
                                .description = "Configuration FILE path",
103
                                .default_value = default_paths.GetConfFile(),
104
                                .parameter = "FILE"},
105
                        cli::Option {
106
                                .long_option = "fallback-config",
107
                                .short_option = "b",
108
                                .description = "Fallback configuration FILE path",
109
                                .default_value = default_paths.GetFallbackConfFile(),
110
                                .parameter = "FILE"},
111
                        cli::Option {
112
                                .long_option = "data",
113
                                .short_option = "d",
114
                                .description = "Mender state data DIRECTORY path",
115
                                .default_value = default_paths.GetPathDataDir(),
116
                                .parameter = "DIR"},
117
                        cli::Option {
118
                                .long_option = "log-file",
119
                                .short_option = "L",
120
                                .description = "FILE to log to",
121
                                .parameter = "FILE"},
122
                        cli::Option {
123
                                .long_option = "log-level",
124
                                .short_option = "l",
125
                                .description = "Set logging level",
126
                                .default_value = "info",
127
                        },
128
                        cli::Option {
129
                                .long_option = "trusted-certs",
130
                                .short_option = "E",
131
                                .description = "Trusted server certificates FILE path",
132
                                .parameter = "FILE"},
133
                        // TODO: not implemented
134
                        cli::Option {
135
                                .long_option = "no-syslog",
136
                                .description = "Disable logging to syslog",
137
                        },
138
                        cli::Option {
139
                                .long_option = "skipverify",
140
                                .description = "Skip certificate verification",
141
                        },
142
                },
143
};
144

145
static expected::ExpectedString GetPassphraseFromFile(const string &filepath) {
×
146
        string passphrase = "";
×
147
        if (filepath == "") {
×
148
                return passphrase;
×
149
        }
150

151
        auto ex_ifs = io::OpenIfstream(filepath == "-" ? io::paths::Stdin : filepath);
×
152
        if (!ex_ifs) {
×
153
                return expected::unexpected(ex_ifs.error());
×
154
        }
155
        auto &ifs = ex_ifs.value();
×
156

157
        errno = 0;
×
158
        getline(ifs, passphrase);
×
159
        if (ifs.bad()) {
×
160
                int io_errno = errno;
×
161
                error::Error err {
162
                        generic_category().default_error_condition(io_errno),
×
163
                        "Failed to read passphrase from '" + filepath + "'"};
×
164
                return expected::unexpected(err);
×
165
        }
166

167
        return passphrase;
×
168
}
169

170
static ExpectedActionPtr ParseAuthArguments(
6✔
171
        const conf::MenderConfig &config,
172
        vector<string>::const_iterator start,
173
        vector<string>::const_iterator end) {
174
        if (start == end) {
6✔
175
                return expected::unexpected(conf::MakeError(conf::InvalidOptionsError, "Need an action"));
3✔
176
        }
177

178
        conf::CmdlineOptionsIterator opts_iter(
179
                start + 1,
180
                end,
181
                {},
182
                {
183
                        "--help",
184
                        "-h",
185
                });
35✔
186
        auto ex_opt_val = opts_iter.Next();
5✔
187

188
        bool help_arg = false;
189
        while (ex_opt_val && ((ex_opt_val.value().option != "") || (ex_opt_val.value().value != ""))) {
5✔
190
                auto opt_val = ex_opt_val.value();
×
191
                if ((opt_val.option == "--help") || (opt_val.option == "-h")) {
×
192
                        help_arg = true;
193
                        break;
×
194
                }
195
                ex_opt_val = opts_iter.Next();
×
196
        }
197

198
        if (help_arg) {
199
                cli::PrintCliCommandHelp(cli_mender_auth, start[0]);
×
200
                return expected::unexpected(error::MakeError(error::ExitWithSuccessError, ""));
×
201
        }
202

203
        string passphrase = "";
5✔
204
        bool forcebootstrap = false;
205
        if (start[0] == "bootstrap" || start[0] == "daemon") {
5✔
206
                conf::CmdlineOptionsIterator opts_iter(
207
                        start + 1, end, {"--passphrase-file"}, {"--forcebootstrap", "-F"});
40✔
208
                auto ex_opt_val = opts_iter.Next();
4✔
209

210
                while (ex_opt_val
211
                           && ((ex_opt_val.value().option != "") || (ex_opt_val.value().value != ""))) {
5✔
212
                        auto opt_val = ex_opt_val.value();
1✔
213
                        if ((opt_val.option == "--passphrase-file")) {
1✔
214
                                auto ex_passphrase = GetPassphraseFromFile(opt_val.value);
×
215
                                if (!ex_passphrase) {
×
216
                                        return expected::unexpected(ex_passphrase.error());
×
217
                                }
218
                                passphrase = ex_passphrase.value();
×
219
                        } else if ((opt_val.option == "--forcebootstrap" || opt_val.option == "-F")) {
1✔
220
                                forcebootstrap = true;
221
                        }
222
                        ex_opt_val = opts_iter.Next();
2✔
223
                }
224
                if (!ex_opt_val) {
4✔
225
                        return expected::unexpected(ex_opt_val.error());
×
226
                }
227
        }
228

229
        if (start[0] == "bootstrap") {
5✔
230
                return BootstrapAction::Create(config, passphrase, forcebootstrap);
4✔
231
        } else if (start[0] == "daemon") {
1✔
232
                return DaemonAction::Create(config, passphrase, forcebootstrap);
×
233
        } else {
234
                return expected::unexpected(
1✔
235
                        conf::MakeError(conf::InvalidOptionsError, "No such action: " + start[0]));
3✔
236
        }
237
}
238

239
error::Error DoMain(
6✔
240
        const vector<string> &args, function<void(context::MenderContext &ctx)> test_hook) {
241
        setup::GlobalSetup();
6✔
242

243
        conf::MenderConfig config;
12✔
244
        auto arg_pos = config.ProcessCmdlineArgs(args.begin(), args.end(), cli_mender_auth);
6✔
245
        if (!arg_pos) {
6✔
246
                if (arg_pos.error().code != error::MakeError(error::ExitWithSuccessError, "").code) {
×
247
                        cli::PrintCliHelp(cli_mender_auth);
×
248
                }
249
                return arg_pos.error();
×
250
        }
251

252
        auto action = ParseAuthArguments(config, args.begin() + arg_pos.value(), args.end());
6✔
253
        if (!action) {
6✔
254
                if (action.error().code != error::MakeError(error::ExitWithSuccessError, "").code) {
2✔
255
                        if (args.size() > 0) {
2✔
256
                                cli::PrintCliCommandHelp(cli_mender_auth, args[0]);
1✔
257
                        } else {
258
                                cli::PrintCliHelp(cli_mender_auth);
1✔
259
                        }
260
                }
261
                return action.error();
2✔
262
        }
263

264
        context::MenderContext context(config);
265

266
        test_hook(context);
4✔
267

268
        return action.value()->Execute(context);
4✔
269
}
270

271
} // namespace cli
272
} // namespace auth
273
} // 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