VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/CloudGateway.cpp@ 98100

Last change on this file since 98100 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/* $Id: CloudGateway.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * Implementation of local and cloud gateway management.
4 */
5
6/*
7 * Copyright (C) 2019-2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_CONSOLE
29
30/* Make sure all the stdint.h macros are included - must come first! */
31#ifndef __STDC_LIMIT_MACROS
32# define __STDC_LIMIT_MACROS
33#endif
34#ifndef __STDC_CONSTANT_MACROS
35# define __STDC_CONSTANT_MACROS
36#endif
37
38#include "LoggingNew.h"
39#include "ApplianceImpl.h"
40#include "CloudNetworkImpl.h"
41#include "CloudGateway.h"
42
43#include <iprt/http.h>
44#include <iprt/inifile.h>
45#include <iprt/net.h>
46#include <iprt/path.h>
47#include <iprt/vfs.h>
48#include <iprt/uri.h>
49#ifdef DEBUG
50#include <iprt/file.h>
51#include <VBox/com/utils.h>
52#endif
53
54#ifdef VBOX_WITH_LIBSSH
55/* Prevent inclusion of Winsock2.h */
56#define _WINSOCK2API_
57#include <libssh/libssh.h>
58#endif /* VBOX_WITH_LIBSSH */
59
60
61static HRESULT setMacAddress(const Utf8Str& str, RTMAC& mac)
62{
63 int rc = RTNetStrToMacAddr(str.c_str(), &mac);
64 if (RT_FAILURE(rc))
65 {
66 LogRel(("CLOUD-NET: Invalid MAC address '%s'\n", str.c_str()));
67 return E_INVALIDARG;
68 }
69 return S_OK;
70}
71
72
73HRESULT GatewayInfo::setCloudMacAddress(const Utf8Str& mac)
74{
75 return setMacAddress(mac, mCloudMacAddress);
76}
77
78
79HRESULT GatewayInfo::setLocalMacAddress(const Utf8Str& mac)
80{
81 return setMacAddress(mac, mLocalMacAddress);
82}
83
84
85class CloudError
86{
87public:
88 CloudError(HRESULT hrc, const Utf8Str& strText) : mHrc(hrc), mText(strText) {};
89 HRESULT getRc() { return mHrc; };
90 Utf8Str getText() { return mText; };
91
92private:
93 HRESULT mHrc;
94 Utf8Str mText;
95};
96
97
98static void handleErrors(HRESULT hrc, const char *pszFormat, ...)
99{
100 if (FAILED(hrc))
101 {
102 va_list va;
103 va_start(va, pszFormat);
104 Utf8Str strError(pszFormat, va);
105 va_end(va);
106 LogRel(("CLOUD-NET: %s (rc=%x)\n", strError.c_str(), hrc));
107 throw CloudError(hrc, strError);
108 }
109
110}
111
112
113class CloudClient
114{
115public:
116 CloudClient(ComPtr<IVirtualBox> virtualBox, const Bstr& strProvider, const Bstr& strProfile);
117 ~CloudClient() {};
118
119 void startCloudGateway(const ComPtr<ICloudNetwork> &network, GatewayInfo& gateway);
120 void stopCloudGateway(const GatewayInfo& gateway);
121
122private:
123 ComPtr<ICloudProviderManager> mManager;
124 ComPtr<ICloudProvider> mProvider;
125 ComPtr<ICloudProfile> mProfile;
126 ComPtr<ICloudClient> mClient;
127};
128
129
130CloudClient::CloudClient(ComPtr<IVirtualBox> virtualBox, const Bstr& strProvider, const Bstr& strProfile)
131{
132 HRESULT hrc = virtualBox->COMGETTER(CloudProviderManager)(mManager.asOutParam());
133 handleErrors(hrc, "Failed to obtain cloud provider manager object");
134 hrc = mManager->GetProviderByShortName(strProvider.raw(), mProvider.asOutParam());
135 handleErrors(hrc, "Failed to obtain cloud provider '%ls'", strProvider.raw());
136 hrc = mProvider->GetProfileByName(strProfile.raw(), mProfile.asOutParam());
137 handleErrors(hrc, "Failed to obtain cloud profile '%ls'", strProfile.raw());
138 hrc = mProfile->CreateCloudClient(mClient.asOutParam());
139 handleErrors(hrc, "Failed to create cloud client");
140}
141
142
143void CloudClient::startCloudGateway(const ComPtr<ICloudNetwork> &network, GatewayInfo& gateway)
144{
145 ComPtr<IProgress> progress;
146 ComPtr<ICloudNetworkGatewayInfo> gatewayInfo;
147 HRESULT hrc = mClient->StartCloudNetworkGateway(network, Bstr(gateway.mPublicSshKey).raw(),
148 gatewayInfo.asOutParam(), progress.asOutParam());
149 handleErrors(hrc, "Failed to launch compute instance");
150 hrc = progress->WaitForCompletion(-1);
151 handleErrors(hrc, "Failed to launch compute instance (wait)");
152
153 Bstr instanceId;
154 hrc = gatewayInfo->COMGETTER(InstanceId)(instanceId.asOutParam());
155 handleErrors(hrc, "Failed to get launched compute instance id");
156 gateway.mGatewayInstanceId = instanceId;
157
158 Bstr publicIP;
159 hrc = gatewayInfo->COMGETTER(PublicIP)(publicIP.asOutParam());
160 handleErrors(hrc, "Failed to get cloud gateway public IP address");
161 gateway.mCloudPublicIp = publicIP;
162
163 Bstr secondaryPublicIP;
164 hrc = gatewayInfo->COMGETTER(SecondaryPublicIP)(secondaryPublicIP.asOutParam());
165 handleErrors(hrc, "Failed to get cloud gateway secondary public IP address");
166 gateway.mCloudSecondaryPublicIp = secondaryPublicIP;
167
168 Bstr macAddress;
169 hrc = gatewayInfo->COMGETTER(MacAddress)(macAddress.asOutParam());
170 handleErrors(hrc, "Failed to get cloud gateway public IP address");
171 gateway.setCloudMacAddress(macAddress);
172}
173
174
175void CloudClient::stopCloudGateway(const GatewayInfo& gateway)
176{
177 ComPtr<IProgress> progress;
178 HRESULT hrc = mClient->TerminateInstance(Bstr(gateway.mGatewayInstanceId).raw(), progress.asOutParam());
179 handleErrors(hrc, "Failed to terminate compute instance");
180#if 0
181 /* Someday we may want to wait until the cloud gateway has terminated. */
182 hrc = progress->WaitForCompletion(-1);
183 handleErrors(hrc, "Failed to terminate compute instance (wait)");
184#endif
185}
186
187
188HRESULT startCloudGateway(ComPtr<IVirtualBox> virtualBox, ComPtr<ICloudNetwork> network, GatewayInfo& gateway)
189{
190 HRESULT hrc = S_OK;
191
192 try {
193 hrc = network->COMGETTER(Provider)(gateway.mCloudProvider.asOutParam());
194 hrc = network->COMGETTER(Profile)(gateway.mCloudProfile.asOutParam());
195 CloudClient client(virtualBox, gateway.mCloudProvider, gateway.mCloudProfile);
196 client.startCloudGateway(network, gateway);
197 }
198 catch (CloudError e)
199 {
200 hrc = e.getRc();
201 }
202
203 return hrc;
204}
205
206
207HRESULT stopCloudGateway(ComPtr<IVirtualBox> virtualBox, GatewayInfo& gateway)
208{
209 if (gateway.mGatewayInstanceId.isEmpty())
210 return S_OK;
211
212 LogRel(("CLOUD-NET: Terminating cloud gateway instance '%s'...\n", gateway.mGatewayInstanceId.c_str()));
213
214 HRESULT hrc = S_OK;
215 try {
216 CloudClient client(virtualBox, gateway.mCloudProvider, gateway.mCloudProfile);
217 client.stopCloudGateway(gateway);
218#if 0
219# ifdef DEBUG
220 char szKeyPath[RTPATH_MAX];
221
222 int rc = GetVBoxUserHomeDirectory(szKeyPath, sizeof(szKeyPath), false /* fCreateDir */);
223 if (RT_SUCCESS(rc))
224 {
225 rc = RTPathAppend(szKeyPath, sizeof(szKeyPath), "gateway-key.pem");
226 AssertRCReturn(rc, rc);
227 rc = RTFileDelete(szKeyPath);
228 if (RT_FAILURE(rc))
229 LogRel(("WARNING! Failed to delete private key %s with rc=%d\n", szKeyPath, rc));
230 }
231 else
232 LogRel(("WARNING! Failed to get VirtualBox user home directory with '%Rrc'\n", rc));
233# endif /* DEBUG */
234#endif
235 }
236 catch (CloudError e)
237 {
238 hrc = e.getRc();
239 LogRel(("CLOUD-NET: Failed to terminate cloud gateway instance (rc=%x).\n", hrc));
240 }
241 gateway.mGatewayInstanceId.setNull();
242 return hrc;
243}
244
245
246HRESULT generateKeys(GatewayInfo& gateway)
247{
248#ifndef VBOX_WITH_LIBSSH
249 RT_NOREF(gateway);
250 return E_NOTIMPL;
251#else /* VBOX_WITH_LIBSSH */
252 ssh_key single_use_key;
253 int rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &single_use_key);
254 if (rc != SSH_OK)
255 {
256 LogRel(("Failed to generate a key pair. rc = %d\n", rc));
257 return E_FAIL;
258 }
259
260 char *pstrKey = NULL;
261 rc = ssh_pki_export_privkey_base64(single_use_key, NULL, NULL, NULL, &pstrKey);
262 if (rc != SSH_OK)
263 {
264 LogRel(("Failed to export private key. rc = %d\n", rc));
265 return E_FAIL;
266 }
267 gateway.mPrivateSshKey = pstrKey;
268#if 0
269# ifdef DEBUG
270 char szConfigPath[RTPATH_MAX];
271
272 rc = GetVBoxUserHomeDirectory(szConfigPath, sizeof(szConfigPath), false /* fCreateDir */);
273 if (RT_SUCCESS(rc))
274 {
275 rc = RTPathAppend(szConfigPath, sizeof(szConfigPath), "gateway-key.pem");
276 AssertRCReturn(rc, rc);
277 rc = ssh_pki_export_privkey_file(single_use_key, NULL, NULL, NULL, szConfigPath);
278 if (rc != SSH_OK)
279 {
280 LogRel(("Failed to export private key to %s with rc=%d\n", szConfigPath, rc));
281 return E_FAIL;
282 }
283# ifndef RT_OS_WINDOWS
284 rc = RTPathSetMode(szConfigPath, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR); /* Satisfy ssh client */
285 AssertRCReturn(rc, rc);
286# endif
287 }
288 else
289 {
290 LogRel(("Failed to get VirtualBox user home directory with '%Rrc'\n", rc));
291 return E_FAIL;
292 }
293# endif /* DEBUG */
294#endif
295 ssh_string_free_char(pstrKey);
296 pstrKey = NULL;
297 rc = ssh_pki_export_pubkey_base64(single_use_key, &pstrKey);
298 if (rc != SSH_OK)
299 {
300 LogRel(("Failed to export public key. rc = %d\n", rc));
301 return E_FAIL;
302 }
303 gateway.mPublicSshKey = Utf8StrFmt("ssh-rsa %s single-use-key", pstrKey);
304 ssh_string_free_char(pstrKey);
305 ssh_key_free(single_use_key);
306
307 return S_OK;
308#endif /* VBOX_WITH_LIBSSH */
309}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette