• 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

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

17
#include <string>
18
#include <memory>
19

20
#include <api/auth.hpp>
21

22
#include <mender-auth/context.hpp>
23
#include <mender-auth/cli/keystore.hpp>
24

25
#include <common/conf.hpp>
26
#include <common/events.hpp>
27
#include <common/log.hpp>
28

29
#include <mender-auth/ipc/server.hpp>
30

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

35
using namespace std;
36

37
namespace auth_client = mender::api::auth;
38
namespace events = mender::common::events;
39
namespace ipc = mender::auth::ipc;
40
namespace log = mender::common::log;
41

42
shared_ptr<MenderKeyStore> KeystoreFromConfig(
4✔
43
        const conf::MenderConfig &config, const string &passphrase) {
44
        cli::StaticKey static_key = cli::StaticKey::No;
4✔
45
        string pem_file;
8✔
46
        string ssl_engine;
8✔
47

48
        // TODO: review and simplify logic as part of MEN-6668. See discussion at:
49
        // https://github.com/mendersoftware/mender/pull/1378#discussion_r1317185066
50
        if (config.https_client.key != "") {
4✔
51
                pem_file = config.https_client.key;
×
52
                ssl_engine = config.https_client.ssl_engine;
×
53
                static_key = cli::StaticKey::Yes;
×
54
        }
55
        if (config.security.auth_private_key != "") {
4✔
56
                pem_file = config.security.auth_private_key;
×
57
                ssl_engine = config.security.ssl_engine;
×
58
                static_key = cli::StaticKey::Yes;
×
59
        }
60
        if (config.https_client.key == "" && config.security.auth_private_key == "") {
4✔
61
                pem_file = config.paths.GetKeyFile();
4✔
62
                ssl_engine = config.https_client.ssl_engine;
4✔
63
                static_key = cli::StaticKey::No;
4✔
64
        }
65

66
        return make_shared<MenderKeyStore>(pem_file, ssl_engine, static_key, passphrase);
8✔
67
}
68

69
error::Error DoBootstrap(shared_ptr<MenderKeyStore> keystore, const bool force) {
4✔
70
        auto err = keystore->Load();
4✔
71
        if (err != error::NoError && err.code != MakeError(NoKeysError, "").code) {
6✔
72
                return err;
×
73
        }
74
        if (err.code == MakeError(NoKeysError, "").code || force) {
8✔
75
                log::Info("Generating new RSA key");
3✔
76
                err = keystore->Generate();
3✔
77
                if (err != error::NoError) {
3✔
78
                        return err;
×
79
                }
80
                err = keystore->Save();
3✔
81
                if (err != error::NoError) {
3✔
82
                        return err;
×
83
                }
84
        }
85
        return err;
4✔
86
}
87

88
error::Error DoAuthenticate(context::MenderContext &main_context) {
4✔
89
        events::EventLoop loop;
8✔
90
        auto &config = main_context.GetConfig();
4✔
91
        if (config.server_url == "") {
4✔
92
                log::Info("No server set in the configuration, skipping authentication");
3✔
93
                return error::NoError;
3✔
94
        }
95
        log::Info("Trying to authenticate with the server: '" + config.server_url + "'");
1✔
96
        mender::common::events::Timer timer {loop};
2✔
97
        http::ClientConfig client_config {
98
                config.server_certificate, config.https_client.certificate, config.https_client.key};
2✔
99
        http::Client client {client_config, loop};
3✔
100
        auto err = auth_client::FetchJWTToken(
101
                client,
102
                config.server_url,
1✔
103
                config.paths.GetKeyFile(),
2✔
104
                config.paths.GetInventoryScriptsDir(),
2✔
105
                [&loop, &config, &timer](auth_client::APIResponse resp) {
4✔
106
                        log::Info("Got Auth response");
1✔
107
                        if (resp) {
1✔
108
                                log::Info(
1✔
109
                                        "Successfully authorized with the server: " + config.server_url + resp.value());
2✔
110
                        } else {
111
                                log::Error(resp.error().String());
×
112
                        }
113
                        timer.Cancel();
1✔
114
                        loop.Stop();
1✔
115
                },
1✔
116
                config.tenant_token);
3✔
117
        if (err != error::NoError) {
1✔
118
                return err;
×
119
        }
120
        timer.AsyncWait(chrono::seconds {30}, [&loop](error::Error err) { loop.Stop(); });
1✔
121
        loop.Run();
1✔
122
        return error::NoError;
1✔
123
}
124

125
DaemonAction::DaemonAction(shared_ptr<MenderKeyStore> keystore, const bool force_bootstrap) :
×
126
        keystore_(keystore),
127
        force_bootstrap_(force_bootstrap) {
×
128
}
×
129

130
ExpectedActionPtr DaemonAction::Create(
×
131
        const conf::MenderConfig &config, const string &passphrase, const bool force_bootstrap) {
132
        auto key_store = KeystoreFromConfig(config, passphrase);
×
133

134
        return make_shared<DaemonAction>(key_store, force_bootstrap);
×
135
}
136

137
error::Error DaemonAction::Execute(context::MenderContext &main_context) {
×
138
        auto &config = main_context.GetConfig();
×
139
        if (!none_of(config.servers.cbegin(), config.servers.cend(), [](const string &it) {
×
140
                        return it != "";
×
141
                })) {
142
                log::Error("Cannot run in daemon mode with no server URL specified");
×
143
                return error::MakeError(error::ExitWithFailureError, "");
×
144
        }
145

146
        auto err = DoBootstrap(keystore_, force_bootstrap_);
×
147
        if (err != error::NoError) {
×
148
                log::Error("Failed to bootstrap: " + err.String());
×
149
                return error::MakeError(error::ExitWithFailureError, "");
×
150
        }
151

152
        events::EventLoop loop {};
×
153

154
        ipc::Server ipc_server {loop, config};
×
155

156
        err = ipc_server.Listen();
×
157
        if (err != error::NoError) {
×
158
                log::Error("Failed to start the listen loop");
×
159
                log::Error(err.String());
×
160
                return error::MakeError(error::ExitWithFailureError, "");
×
161
        }
162

163
        loop.Run();
×
164

165
        return error::NoError;
×
166
}
167

168
BootstrapAction::BootstrapAction(shared_ptr<MenderKeyStore> keystore, bool force_bootstrap) :
×
169
        keystore_(keystore),
170
        force_bootstrap_(force_bootstrap) {
×
171
}
×
172

173
ExpectedActionPtr BootstrapAction::Create(
4✔
174
        const conf::MenderConfig &config, const string &passphrase, bool force_bootstrap) {
175
        auto key_store = KeystoreFromConfig(config, passphrase);
4✔
176

177
        return make_shared<BootstrapAction>(key_store, force_bootstrap);
12✔
178
}
179

180
error::Error BootstrapAction::Execute(context::MenderContext &main_context) {
4✔
181
        auto err = DoBootstrap(keystore_, force_bootstrap_);
8✔
182
        if (err != error::NoError) {
4✔
183
                return err;
×
184
        }
185
        return DoAuthenticate(main_context);
4✔
186
}
187

188
} // namespace cli
189
} // namespace auth
190
} // 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