bdy 1.16.15-dev → 1.16.16-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/distTs/package.json +2 -1
- package/distTs/src/api/client.js +34 -6
- package/distTs/src/command/login.js +103 -46
- package/distTs/src/texts.js +5 -3
- package/distTs/src/tunnel/cfg.js +17 -0
- package/distTs/src/tunnel/server/http1.js +11 -6
- package/distTs/src/tunnel/server/http2.js +14 -6
- package/package.json +2 -1
package/distTs/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bdy",
|
|
3
3
|
"preferGlobal": false,
|
|
4
|
-
"version": "1.16.
|
|
4
|
+
"version": "1.16.16-dev",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"eventsource": "4.0.0",
|
|
32
32
|
"fastify": "4.28.1",
|
|
33
33
|
"fdir": "6.5.0",
|
|
34
|
+
"open": "11.0.0",
|
|
34
35
|
"fflate": "0.8.2",
|
|
35
36
|
"human-id": "^4.1.3",
|
|
36
37
|
"isbinaryfile": "5.0.2",
|
package/distTs/src/api/client.js
CHANGED
|
@@ -21,18 +21,24 @@ class ApiClient {
|
|
|
21
21
|
},
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
-
async request(method, path, body, parseResponseBody = false, rawResponseBody = false) {
|
|
25
|
-
const headers = {
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
async request(method, path, body, parseResponseBody = false, rawResponseBody = false, httpUrlEncoded = false) {
|
|
25
|
+
const headers = {};
|
|
26
|
+
if (this.token)
|
|
27
|
+
headers.authorization = `Bearer ${this.token}`;
|
|
28
28
|
let bodyParsed = undefined;
|
|
29
29
|
if (body) {
|
|
30
30
|
if (body instanceof undici_1.FormData) {
|
|
31
31
|
bodyParsed = body;
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
if (httpUrlEncoded) {
|
|
35
|
+
headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8';
|
|
36
|
+
bodyParsed = new URLSearchParams(body).toString();
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
headers['content-type'] = 'application/json; charset=utf-8';
|
|
40
|
+
bodyParsed = JSON.stringify(body);
|
|
41
|
+
}
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
44
|
const opts = {
|
|
@@ -172,6 +178,28 @@ class ApiClient {
|
|
|
172
178
|
async stopSandbox(workspace, sandboxId) {
|
|
173
179
|
return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/stop`, {}, true);
|
|
174
180
|
}
|
|
181
|
+
async registerApp(name, redirectUrl) {
|
|
182
|
+
return await this.request('POST', '/auth/register', {
|
|
183
|
+
redirect_uris: [redirectUrl],
|
|
184
|
+
client_name: name,
|
|
185
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
186
|
+
response_types: ['code'],
|
|
187
|
+
token_endpoint_auth_method: "client_secret_basic",
|
|
188
|
+
token_expires_in: 3600
|
|
189
|
+
}, true);
|
|
190
|
+
}
|
|
191
|
+
async getApp(clientId) {
|
|
192
|
+
return await this.request('GET', `/auth/register/${encodeURIComponent(clientId)}`, null, true);
|
|
193
|
+
}
|
|
194
|
+
async exchangeAppToken(code, clientId, clientSecret, redirectUrl) {
|
|
195
|
+
return await this.request('POST', '/oauth2/token', {
|
|
196
|
+
grant_type: 'authorization_code',
|
|
197
|
+
code,
|
|
198
|
+
client_id: clientId,
|
|
199
|
+
client_secret: clientSecret,
|
|
200
|
+
redirect_uri: redirectUrl
|
|
201
|
+
}, true, false, true);
|
|
202
|
+
}
|
|
175
203
|
async restartSandbox(workspace, sandboxId) {
|
|
176
204
|
return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/restart`, {}, true);
|
|
177
205
|
}
|
|
@@ -6,21 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const cfg_1 = __importDefault(require("../tunnel/cfg"));
|
|
7
7
|
const output_1 = __importDefault(require("../output"));
|
|
8
8
|
const client_1 = __importDefault(require("../api/client"));
|
|
9
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
10
|
+
const open_1 = __importDefault(require("open"));
|
|
9
11
|
const texts_1 = require("../texts");
|
|
10
12
|
const utils_1 = require("../utils");
|
|
11
13
|
const input_1 = __importDefault(require("../input"));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
case utils_1.REST_API_REGION.EU:
|
|
17
|
-
return 'https://eu.buddy.works/security';
|
|
18
|
-
case utils_1.REST_API_REGION.AS:
|
|
19
|
-
return 'https://asia.buddy.works/security';
|
|
20
|
-
default:
|
|
21
|
-
return `https://${baseUrl}/security`;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
14
|
+
const OAUTH_CLIENT_APP_PORT = 7596;
|
|
15
|
+
const OAUTH_CLIENT_APP_HOST = 'localhost';
|
|
16
|
+
const OAUTH_CLIENT_APP_REDIRECT_URL = `http://localhost:${OAUTH_CLIENT_APP_PORT}`;
|
|
17
|
+
const OAUTH_CLIENT_APP_SCOPES = 'WORKSPACE USER_INFO EXECUTION_MANAGE SANDBOX_MANAGE';
|
|
24
18
|
function normalizeBaseUrl(url) {
|
|
25
19
|
let normalized = url.trim();
|
|
26
20
|
normalized = normalized.replace(/^https?:\/\//i, '');
|
|
@@ -52,10 +46,96 @@ async function restApiBaseUrl() {
|
|
|
52
46
|
}
|
|
53
47
|
return `${normalized}/api`;
|
|
54
48
|
}
|
|
55
|
-
async function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
async function oauthServer(api, clientId, clientSecret) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const s = node_http_1.default.createServer(async (req, res) => {
|
|
52
|
+
const url = new URL(req.url || '', `http://${OAUTH_CLIENT_APP_HOST}`);
|
|
53
|
+
const urlCode = url.searchParams.get('code');
|
|
54
|
+
if (!urlCode) {
|
|
55
|
+
res.end(texts_1.ERR_LOGIN_HTTP_FAILED);
|
|
56
|
+
s.close();
|
|
57
|
+
reject(new Error(texts_1.ERR_LOGIN_HTTP_FAILED));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const client = new client_1.default(new URL(`https://${api}`));
|
|
61
|
+
try {
|
|
62
|
+
const response = await client.exchangeAppToken(urlCode, clientId, clientSecret, OAUTH_CLIENT_APP_REDIRECT_URL);
|
|
63
|
+
res.end(texts_1.ERR_LOGIN_HTTP_SUCCESS);
|
|
64
|
+
s.close();
|
|
65
|
+
resolve(response.access_token);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
res.end(texts_1.ERR_LOGIN_HTTP_FAILED);
|
|
69
|
+
s.close();
|
|
70
|
+
reject(new Error(texts_1.ERR_LOGIN_HTTP_FAILED));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
s.on('error', () => {
|
|
75
|
+
s.close();
|
|
76
|
+
reject(texts_1.ERR_LOGIN_HTTP_SERVER_PORT_TAKEN);
|
|
77
|
+
});
|
|
78
|
+
s.listen(OAUTH_CLIENT_APP_PORT, OAUTH_CLIENT_APP_HOST);
|
|
79
|
+
(0, open_1.default)(`https://${api}/oauth2/authorize?type=web_server&client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(OAUTH_CLIENT_APP_REDIRECT_URL)}&response_type=code&scope=${encodeURIComponent(OAUTH_CLIENT_APP_SCOPES)}`);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async function getOrCreateApp(api) {
|
|
83
|
+
const client = new client_1.default(new URL(`https://${api}`));
|
|
84
|
+
let clientId = cfg_1.default.getApiClientId();
|
|
85
|
+
let clientSecret = cfg_1.default.getApiClientSecret();
|
|
86
|
+
if (clientId && clientSecret) {
|
|
87
|
+
try {
|
|
88
|
+
await client.getApp(clientId);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
clientId = null;
|
|
92
|
+
clientSecret = null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!clientId || !clientSecret) {
|
|
96
|
+
const app = await client.registerApp('bdy cli app', OAUTH_CLIENT_APP_REDIRECT_URL);
|
|
97
|
+
clientId = app.client_id;
|
|
98
|
+
clientSecret = app.client_secret;
|
|
99
|
+
cfg_1.default.setApiClient(clientId, clientSecret);
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
clientId,
|
|
103
|
+
clientSecret,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function authorizeOAuth(api) {
|
|
107
|
+
const { clientId, clientSecret } = await getOrCreateApp(api);
|
|
108
|
+
return await oauthServer(api, clientId, clientSecret);
|
|
109
|
+
}
|
|
110
|
+
async function authorizeToken(api, token, workspace, project) {
|
|
111
|
+
const client = new client_1.default(new URL(`https://${api}`), token);
|
|
112
|
+
const w = await client.getWorkspaces();
|
|
113
|
+
if (!w.workspaces?.length) {
|
|
114
|
+
output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACES);
|
|
115
|
+
}
|
|
116
|
+
if (workspace) {
|
|
117
|
+
const found = w.workspaces.find((w) => w.domain === workspace);
|
|
118
|
+
if (!found) {
|
|
119
|
+
output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACE_FOUND);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
workspace = await output_1.default.selectWorkspace(w.workspaces);
|
|
124
|
+
}
|
|
125
|
+
cfg_1.default.setApiToken(token);
|
|
126
|
+
cfg_1.default.setWorkspace(workspace);
|
|
127
|
+
const p = await client.getProjects(workspace);
|
|
128
|
+
if (project) {
|
|
129
|
+
const found = p.projects.find((p) => p.name === project);
|
|
130
|
+
if (!found) {
|
|
131
|
+
output_1.default.exitError(texts_1.ERR_LOGIN_NO_PROJECT_FOUND);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
project = await output_1.default.selectProject(p.projects);
|
|
136
|
+
}
|
|
137
|
+
cfg_1.default.setProject(project);
|
|
138
|
+
output_1.default.exitSuccess(texts_1.TXT_LOGIN_SUCCESS);
|
|
59
139
|
}
|
|
60
140
|
const commandLogin = (0, utils_1.newCommand)('login', texts_1.DESC_COMMAND_LOGIN);
|
|
61
141
|
commandLogin.option('--token <token>', texts_1.OPTION_REST_API_TOKEN);
|
|
@@ -68,9 +148,9 @@ commandLogin.action(async (options) => {
|
|
|
68
148
|
cfg_1.default.clearLogin();
|
|
69
149
|
let api = options.api || process.env.BUDDY_API_ENDPOINT;
|
|
70
150
|
let region = options.region || process.env.BUDDY_REGION;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
151
|
+
const token = options.token || process.env.BUDDY_TOKEN;
|
|
152
|
+
const workspace = options.workspace || process.env.BUDDY_WORKSPACE;
|
|
153
|
+
const project = options.project || process.env.BUDDY_PROJECT;
|
|
74
154
|
if (api) {
|
|
75
155
|
region = utils_1.REST_API_REGION.ONPREM;
|
|
76
156
|
}
|
|
@@ -96,35 +176,12 @@ commandLogin.action(async (options) => {
|
|
|
96
176
|
}
|
|
97
177
|
cfg_1.default.setBaseUrl(api);
|
|
98
178
|
if (!token) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const w = await client.getWorkspaces();
|
|
103
|
-
if (!w.workspaces?.length) {
|
|
104
|
-
output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACES);
|
|
105
|
-
}
|
|
106
|
-
if (workspace) {
|
|
107
|
-
const found = w.workspaces.find((w) => w.domain === workspace);
|
|
108
|
-
if (!found) {
|
|
109
|
-
output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACE_FOUND);
|
|
110
|
-
}
|
|
179
|
+
output_1.default.normal(texts_1.TXT_LOGIN_OAUTH);
|
|
180
|
+
const token = await authorizeOAuth(api);
|
|
181
|
+
await authorizeToken(api, token, workspace, project);
|
|
111
182
|
}
|
|
112
183
|
else {
|
|
113
|
-
|
|
184
|
+
await authorizeToken(api, token, workspace, project);
|
|
114
185
|
}
|
|
115
|
-
cfg_1.default.setApiToken(token);
|
|
116
|
-
cfg_1.default.setWorkspace(workspace);
|
|
117
|
-
const p = await client.getProjects(workspace);
|
|
118
|
-
if (project) {
|
|
119
|
-
const found = p.projects.find((p) => p.name === project);
|
|
120
|
-
if (!found) {
|
|
121
|
-
output_1.default.exitError(texts_1.ERR_LOGIN_NO_PROJECT_FOUND);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
project = await output_1.default.selectProject(p.projects);
|
|
126
|
-
}
|
|
127
|
-
cfg_1.default.setProject(project);
|
|
128
|
-
output_1.default.exitSuccess(texts_1.TXT_LOGIN_SUCCESS);
|
|
129
186
|
});
|
|
130
187
|
exports.default = commandLogin;
|
package/distTs/src/texts.js
CHANGED
|
@@ -9,7 +9,7 @@ exports.LOG_SOCKET_DISCONNECTED = exports.LOG_SOCKET_CONNECTED = exports.LOG_AGE
|
|
|
9
9
|
exports.DEBUG_AUTO_SCROLL = exports.DEBUG_RESOURCE_SCRAPPING_URL = exports.DEBUG_SNAPSHOT_PROCESSING = exports.DEBUG_SNAPSHOTS_PROCESSING = exports.DEBUG_EXEC_COMMAND = exports.DEBUG_EXEC_TEST_COMMAND = exports.LOG_INSTALLED_BROWSER = exports.LOG_SESSION_LINK = exports.LOG_SENDING_DATA = exports.LOG_SENDING_REQUEST = exports.LOG_PROCESSING_SNAPSHOTS = exports.LOG_RUNNING_EXEC_COMMAND = exports.LOG_TUNNEL_SSH_STREAM = exports.LOG_TUNNEL_TLS_AGENT_STREAM = exports.LOG_TUNNEL_TLS_REGION_STREAM = exports.LOG_TUNNEL_TLS_TARGET_STREAM = exports.LOG_TUNNEL_HTTP2_STREAM = exports.LOG_TUNNEL_HTTP1_STREAM = exports.LOG_TUNNEL_TCP_STREAM = exports.LOG_TUNNEL_HTTP_WRONG_USER_AGENTS = exports.LOG_TUNNEL_HTTP_CIRCUIT_BREAKER_OPEN = exports.LOG_TUNNEL_HTTP_RATE_LIMIT = exports.LOG_TUNNEL_HTTP_WRON_AUTH = exports.LOG_TUNNEL_IDENTIFIED = exports.LOG_TUNNEL_DISCONNECTED = exports.LOG_TUNNEL_FAILED = exports.LOG_TUNNEL_CONNECTED = exports.LOG_AGENT_STARTED = exports.LOG_AGENT_SERVER_STARTED = exports.LOG_ERROR_STARTING_AGENT_SERVER = exports.LOG_SSH_CONNECTION = exports.LOG_WRONG_STREAM = exports.LOG_DETECTED_STREAM = exports.LOG_HTTP2_REQUEST = exports.LOG_HTTP2_CONNECTION = exports.LOG_HTTP1_REQUEST = exports.LOG_HTTP1_CONNECTION = exports.LOG_ERROR = exports.LOG_STOPPING_TUNNEL = exports.LOG_STARTING_TUNNEL = exports.LOG_ENABLING_AGENT_TARGET = exports.LOG_DISABLING_AGENT_TARGET = exports.LOG_REMOVING_TUNNEL = exports.LOG_TUNNEL_REGISTERED = exports.LOG_ERROR_WHILE_REFRESHING_AGENT = exports.LOG_REGISTERING_TUNNEL = exports.LOG_GETTING_AGENT = exports.LOG_UNREGISTERING_AGENT = exports.LOG_REGION_DETECTED = exports.LOG_AGENT_REGISTERED = void 0;
|
|
10
10
|
exports.TXT_SANDBOX_STOPPED = exports.TXT_SANDBOX_STARTED = exports.TXT_SANDBOX_DESTROYED = exports.TXT_SANDBOX_CREATED = exports.TXT_SANDBOX_CREATING = exports.OPTION_SANDBOX_COMMAND_LAST = exports.OPTION_SANDBOX_WAIT_TIMEOUT = exports.OPTION_SANDBOX_WAIT = exports.OPTION_SANDBOX_WAIT_APP = exports.OPTION_SANDBOX_WAIT_CONFIGURED = exports.OPTION_SANDBOX_WAIT_RUNNING = exports.ERR_SANDBOX_STOP_FAILED = exports.ERR_SANDBOX_NO_COMMANDS = exports.ERR_SANDBOX_RUNNING_FAILED = exports.ERR_SANDBOX_STOP_TIMEOUT = exports.ERR_SANDBOX_SNAPSHOT_TIMEOUT = exports.ERR_SANDBOX_RUNNING_TIMEOUT = exports.ERR_SANDBOX_APP_TIMEOUT = exports.ERR_SANDBOX_SETUP_TIMEOUT = exports.ERR_SANDBOX_APP_FAILED = exports.ERR_SANDBOX_SETUP_FAILED = exports.ERR_SANDBOX_INVALID_RUNTIME = exports.ERR_SANDBOX_INVALID_RESOURCES = exports.ERR_SANDBOX_NOT_FOUND = exports.OPTION_SANDBOX_COMMAND = exports.OPTION_SANDBOX_DETACHED = exports.OPTION_SANDBOX_RUNTIME = exports.OPTION_SANDBOX_APP_TYPE = exports.OPTION_SANDBOX_APP_DIR = exports.OPTION_SANDBOX_RUN_COMMAND = exports.OPTION_SANDBOX_TAGS = exports.OPTION_SANDBOX_INSTALL_COMMANDS = exports.OPTION_SANDBOX_RESOURCES = exports.OPTION_SANDBOX_OS = exports.OPTION_SANDBOX_NAME = exports.OPTION_SANDBOX_IDENTIFIER = exports.DESC_COMMAND_SANDBOX_EXEC = exports.DESC_COMMAND_SANDBOX_STATUS = exports.DESC_COMMAND_SANDBOX_RESTART = exports.DESC_COMMAND_SANDBOX_STOP = exports.DESC_COMMAND_SANDBOX_START = exports.DESC_COMMAND_SANDBOX_DESTROY = exports.DESC_COMMAND_SANDBOX_GET = exports.DESC_COMMAND_SANDBOX_LIST = exports.DESC_COMMAND_SANDBOX_CREATE = exports.DESC_COMMAND_SANDBOX = exports.DEBUG_WAIT_FOR_IDLE_TIMEOUT = exports.DEBUG_WAIT_FOR_IDLE = exports.DEBUG_RESOURCE_DISCOVERY_TIMEOUT = exports.DEBUG_AUTO_WIDTH = void 0;
|
|
11
11
|
exports.TXT_SANDBOX_EXEC_BACKGROUND = exports.TXT_SANDBOX_EXEC_ID = exports.ERR_SANDBOX_CP_INVALID_DEST = exports.ERR_SANDBOX_CP_SOURCE_NOT_FOUND = exports.TXT_SANDBOX_CP_DONE = exports.TXT_SANDBOX_CP_PROGRESS = exports.OPTION_SANDBOX_CP_SILENT = exports.OPTION_SANDBOX_CP_DEST = exports.OPTION_SANDBOX_CP_SOURCE = exports.DESC_COMMAND_SANDBOX_CP = exports.ERR_SANDBOX_ENDPOINTS_NOT_FOUND = exports.ERR_SANDBOX_ENDPOINT_NOT_FOUND = exports.ERR_SANDBOX_ENDPOINT_EXISTS = exports.TXT_SANDBOX_ENDPOINT_DELETED = exports.TXT_SANDBOX_ENDPOINT_ADDED = exports.OPTION_SANDBOX_ENDPOINT_TYPE = exports.OPTION_SANDBOX_ENDPOINT_PORT = exports.OPTION_SANDBOX_ENDPOINT_NAME_ARG = exports.OPTION_SANDBOX_ENDPOINT_NAME = exports.DESC_COMMAND_SANDBOX_ENDPOINT_DELETE = exports.DESC_COMMAND_SANDBOX_ENDPOINT_ADD = exports.DESC_COMMAND_SANDBOX_ENDPOINT_GET = exports.DESC_COMMAND_SANDBOX_ENDPOINT_LIST = exports.DESC_COMMAND_SANDBOX_ENDPOINT = exports.ERR_SANDBOX_SNAPSHOTS_NOT_FOUND = exports.ERR_SANDBOX_SNAPSHOT_NOT_FOUND = exports.ERR_SANDBOX_SNAPSHOT_FAILED = exports.TXT_SANDBOX_SNAPSHOT_WAITING = exports.TXT_SANDBOX_SNAPSHOT_DELETED = exports.TXT_SANDBOX_SNAPSHOT_CREATED = exports.OPTION_SANDBOX_FROM_SNAPSHOT = exports.OPTION_SANDBOX_SNAPSHOT_NAME_ARG = exports.OPTION_SANDBOX_SNAPSHOT_NAME = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_DELETE = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_GET = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_CREATE = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_LIST = exports.DESC_COMMAND_SANDBOX_SNAPSHOT = exports.TXT_SANDBOX_COMMAND_KILLED = exports.OPTION_SANDBOX_COMMAND_FOLLOW = exports.OPTION_SANDBOX_COMMAND_ID = exports.DESC_COMMAND_SANDBOX_EXEC_KILL = exports.DESC_COMMAND_SANDBOX_EXEC_LOGS = exports.DESC_COMMAND_SANDBOX_EXEC_STATUS = exports.DESC_COMMAND_SANDBOX_EXEC_LIST = exports.TXT_SANDBOX_WAITING_START = exports.TXT_SANDBOX_WAITING_STOP = exports.TXT_SANDBOX_WAITING_APP = exports.TXT_SANDBOX_WAITING_SETUP = exports.TXT_SANDBOX_WAITING_RUNNING = void 0;
|
|
12
|
-
exports.TXT_PROJECT_NONE = exports.ERR_PROJECT_NO_PROJECTS = exports.ERR_PROJECT_NOT_FOUND = exports.TXT_LOGIN_SELECT_PROJECT = exports.TXT_PROJECT_SET_CLEARED = exports.TXT_PROJECT_SET_SUCCESS = exports.DESC_COMMAND_PROJECT_GET = exports.ARG_COMMAND_PROJECT_NAME = exports.DESC_COMMAND_PROJECT_SET = exports.DESC_COMMAND_PROJECT_LIST = exports.DESC_COMMAND_PROJECT = exports.ERR_LOGIN_INVALID_BASE_URL = exports.ERR_LOGIN_NO_PROJECT_FOUND = exports.ERR_LOGIN_NO_WORKSPACE_FOUND = exports.ERR_LOGIN_NO_WORKSPACES = exports.
|
|
12
|
+
exports.TXT_PROJECT_NONE = exports.ERR_PROJECT_NO_PROJECTS = exports.ERR_PROJECT_NOT_FOUND = exports.TXT_LOGIN_SELECT_PROJECT = exports.TXT_PROJECT_SET_CLEARED = exports.TXT_PROJECT_SET_SUCCESS = exports.DESC_COMMAND_PROJECT_GET = exports.ARG_COMMAND_PROJECT_NAME = exports.DESC_COMMAND_PROJECT_SET = exports.DESC_COMMAND_PROJECT_LIST = exports.DESC_COMMAND_PROJECT = exports.ERR_LOGIN_INVALID_BASE_URL = exports.ERR_LOGIN_NO_PROJECT_FOUND = exports.ERR_LOGIN_NO_WORKSPACE_FOUND = exports.ERR_LOGIN_NO_WORKSPACES = exports.ERR_LOGIN_HTTP_SUCCESS = exports.ERR_LOGIN_HTTP_FAILED = exports.TXT_LOGIN_OAUTH = exports.ERR_LOGIN_HTTP_SERVER_PORT_TAKEN = exports.TXT_LOGIN_SUCCESS = exports.TXT_LOGIN_SELECT_WORKSPACE = exports.TXT_LOGIN_ENTER_BASE_URL = exports.TXT_LOGIN_SELECT_REGION = exports.TXT_WORKSPACE_NONE = exports.TXT_WORKSPACE_SET_SUCCESS = exports.ARG_COMMAND_WORKSPACE = exports.DESC_COMMAND_WORKSPACE_GET = exports.DESC_COMMAND_WORKSPACE_SET = exports.DESC_COMMAND_WORKSPACE_LIST = exports.DESC_COMMAND_WORKSPACE = exports.TXT_LOGOUT_SUCCESS = exports.DESC_COMMAND_LOGOUT = exports.DESC_COMMAND_LOGIN = exports.ERR_WHOAMI_LOGOUT = exports.TXT_WHOAMI_NO_PROJECT = exports.TXT_WHOAMI_NO_WORKSPACE = exports.DESC_COMMAND_WHOAMI = exports.TXT_SANDBOX_EXEC_FAILED = exports.TXT_SANDBOX_EXEC_INPROGRESS = exports.TXT_SANDBOX_EXEC_SUCCESS = void 0;
|
|
13
13
|
const utils_1 = require("./utils");
|
|
14
14
|
exports.ERR_REST_API_GENERAL_ERROR = 'Something went wrong';
|
|
15
15
|
exports.ERR_REST_API_CONNECT_ERROR = 'Connection refused. Check selected endpoint';
|
|
@@ -583,10 +583,12 @@ exports.TXT_WORKSPACE_SET_SUCCESS = TXT_WORKSPACE_SET_SUCCESS;
|
|
|
583
583
|
exports.TXT_WORKSPACE_NONE = 'No workspace configured. Run "bdy login" or "bdy workspace set" first.';
|
|
584
584
|
exports.TXT_LOGIN_SELECT_REGION = 'Select region:';
|
|
585
585
|
exports.TXT_LOGIN_ENTER_BASE_URL = 'Enter your Buddy instance URL (e.g., buddy.company.com):';
|
|
586
|
-
const TXT_LOGIN_ENTER_TOKEN = (url) => `Enter your personal access token (get your personal access token at: ${url}):`;
|
|
587
|
-
exports.TXT_LOGIN_ENTER_TOKEN = TXT_LOGIN_ENTER_TOKEN;
|
|
588
586
|
exports.TXT_LOGIN_SELECT_WORKSPACE = 'Select workspace:';
|
|
589
587
|
exports.TXT_LOGIN_SUCCESS = 'Logged in successfully!';
|
|
588
|
+
exports.ERR_LOGIN_HTTP_SERVER_PORT_TAKEN = 'Cant start local http server to authorize';
|
|
589
|
+
exports.TXT_LOGIN_OAUTH = 'Starting authorization process...';
|
|
590
|
+
exports.ERR_LOGIN_HTTP_FAILED = 'Failed to authorize. Try again...';
|
|
591
|
+
exports.ERR_LOGIN_HTTP_SUCCESS = 'Authorized. You can now safely close this browser tab';
|
|
590
592
|
exports.ERR_LOGIN_NO_WORKSPACES = 'No workspaces found for this token';
|
|
591
593
|
exports.ERR_LOGIN_NO_WORKSPACE_FOUND = 'Provided workspace has been not found';
|
|
592
594
|
exports.ERR_LOGIN_NO_PROJECT_FOUND = 'Provided project has been not found';
|
package/distTs/src/tunnel/cfg.js
CHANGED
|
@@ -172,6 +172,17 @@ class Cfg {
|
|
|
172
172
|
this.json.apiToken = token;
|
|
173
173
|
this.save();
|
|
174
174
|
}
|
|
175
|
+
setApiClient(clientId, clientSecret) {
|
|
176
|
+
if (!clientId || !clientSecret) {
|
|
177
|
+
delete this.json.apiClientId;
|
|
178
|
+
delete this.json.apiClientSecret;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
this.json.apiClientId = clientId;
|
|
182
|
+
this.json.apiClientSecret = clientSecret;
|
|
183
|
+
}
|
|
184
|
+
this.save();
|
|
185
|
+
}
|
|
175
186
|
setWhitelist(whitelist) {
|
|
176
187
|
if (!whitelist || !whitelist.length)
|
|
177
188
|
delete this.json.whitelist;
|
|
@@ -192,6 +203,12 @@ class Cfg {
|
|
|
192
203
|
getApiToken() {
|
|
193
204
|
return this.json.apiToken || '';
|
|
194
205
|
}
|
|
206
|
+
getApiClientId() {
|
|
207
|
+
return this.json.apiClientId || '';
|
|
208
|
+
}
|
|
209
|
+
getApiClientSecret() {
|
|
210
|
+
return this.json.apiClientSecret || '';
|
|
211
|
+
}
|
|
195
212
|
getTokenHost() {
|
|
196
213
|
const token = this.getToken();
|
|
197
214
|
if (!token) {
|
|
@@ -11,9 +11,11 @@ const texts_1 = require("../../texts");
|
|
|
11
11
|
const tunnel_1 = require("../../types/tunnel");
|
|
12
12
|
class ServerHttp1 extends events_1.default {
|
|
13
13
|
server;
|
|
14
|
+
host;
|
|
14
15
|
constructor(host) {
|
|
15
16
|
super();
|
|
16
|
-
this.
|
|
17
|
+
this.host = host;
|
|
18
|
+
this.server = http_1.default.createServer((req, res) => this.processRequest(req, res));
|
|
17
19
|
this.server.on('connection', (socket) => {
|
|
18
20
|
socket.id = (0, uuid_1.v4)();
|
|
19
21
|
this.emit(tunnel_1.TUNNEL_HTTP_SOCKET.OPEN, socket);
|
|
@@ -46,7 +48,10 @@ class ServerHttp1 extends events_1.default {
|
|
|
46
48
|
method: logRequest.method,
|
|
47
49
|
setHost: false,
|
|
48
50
|
path: logRequest.url,
|
|
49
|
-
headers:
|
|
51
|
+
headers: {
|
|
52
|
+
...logRequest.headers,
|
|
53
|
+
host: this.host
|
|
54
|
+
},
|
|
50
55
|
});
|
|
51
56
|
if (logRequest.requestBody.data.length > 0)
|
|
52
57
|
req.write(logRequest.requestBody.data);
|
|
@@ -60,9 +65,9 @@ class ServerHttp1 extends events_1.default {
|
|
|
60
65
|
});
|
|
61
66
|
req.end();
|
|
62
67
|
}
|
|
63
|
-
checkHostHeader(req, res
|
|
68
|
+
checkHostHeader(req, res) {
|
|
64
69
|
const headerHost = (req.headers.host || '').split(':')[0];
|
|
65
|
-
if (headerHost === host)
|
|
70
|
+
if (headerHost === this.host)
|
|
66
71
|
return true;
|
|
67
72
|
else {
|
|
68
73
|
res.statusCode = 421;
|
|
@@ -70,8 +75,8 @@ class ServerHttp1 extends events_1.default {
|
|
|
70
75
|
return false;
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
|
-
async processRequest(req, res
|
|
74
|
-
if (!this.checkHostHeader(req, res
|
|
78
|
+
async processRequest(req, res) {
|
|
79
|
+
if (!this.checkHostHeader(req, res))
|
|
75
80
|
return;
|
|
76
81
|
logger_1.default.debug((0, texts_1.LOG_HTTP1_REQUEST)(req.method, req.url));
|
|
77
82
|
this.emit(tunnel_1.TUNNEL_EVENT.HTTP_REQUEST, req, res);
|
|
@@ -11,9 +11,11 @@ const texts_1 = require("../../texts");
|
|
|
11
11
|
const tunnel_1 = require("../../types/tunnel");
|
|
12
12
|
class ServerHttp2 extends events_1.default {
|
|
13
13
|
server;
|
|
14
|
+
host;
|
|
14
15
|
constructor(host) {
|
|
15
16
|
super();
|
|
16
|
-
this.
|
|
17
|
+
this.host = host;
|
|
18
|
+
this.server = http2_1.default.createServer((req, res) => this.processRequest(req, res));
|
|
17
19
|
this.server.on('session', (session) => {
|
|
18
20
|
session.id = (0, uuid_1.v4)();
|
|
19
21
|
this.emit(tunnel_1.TUNNEL_EVENT.HTTP_SESSION_OPEN, session);
|
|
@@ -43,7 +45,10 @@ class ServerHttp2 extends events_1.default {
|
|
|
43
45
|
let client = http2_1.default.connect(`http://localhost:${address.port}`, {
|
|
44
46
|
maxSessionMemory: 100,
|
|
45
47
|
});
|
|
46
|
-
let req = client.request(
|
|
48
|
+
let req = client.request({
|
|
49
|
+
...logRequest.headers,
|
|
50
|
+
':authority': this.host
|
|
51
|
+
});
|
|
47
52
|
if (logRequest.requestBody.data.length > 0)
|
|
48
53
|
req.write(logRequest.requestBody.data);
|
|
49
54
|
req.on('response', () => {
|
|
@@ -64,9 +69,12 @@ class ServerHttp2 extends events_1.default {
|
|
|
64
69
|
});
|
|
65
70
|
req.end();
|
|
66
71
|
}
|
|
67
|
-
checkHostHeader(req, res
|
|
72
|
+
checkHostHeader(req, res) {
|
|
73
|
+
logger_js_1.default.info('checkHostHeader');
|
|
74
|
+
logger_js_1.default.info(this.host);
|
|
75
|
+
logger_js_1.default.info(req.headers[':authority']);
|
|
68
76
|
const headerHost = (req.headers[':authority'] || '').split(':')[0];
|
|
69
|
-
if (headerHost === host)
|
|
77
|
+
if (headerHost === this.host)
|
|
70
78
|
return true;
|
|
71
79
|
else {
|
|
72
80
|
res.statusCode = 421;
|
|
@@ -74,8 +82,8 @@ class ServerHttp2 extends events_1.default {
|
|
|
74
82
|
return false;
|
|
75
83
|
}
|
|
76
84
|
}
|
|
77
|
-
async processRequest(req, res
|
|
78
|
-
if (!this.checkHostHeader(req, res
|
|
85
|
+
async processRequest(req, res) {
|
|
86
|
+
if (!this.checkHostHeader(req, res))
|
|
79
87
|
return;
|
|
80
88
|
logger_js_1.default.debug((0, texts_1.LOG_HTTP2_REQUEST)(req.method, req.url));
|
|
81
89
|
this.emit(tunnel_1.TUNNEL_EVENT.HTTP_REQUEST, req, res);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bdy",
|
|
3
3
|
"preferGlobal": false,
|
|
4
|
-
"version": "1.16.
|
|
4
|
+
"version": "1.16.16-dev",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"eventsource": "4.0.0",
|
|
32
32
|
"fastify": "4.28.1",
|
|
33
33
|
"fdir": "6.5.0",
|
|
34
|
+
"open": "11.0.0",
|
|
34
35
|
"fflate": "0.8.2",
|
|
35
36
|
"human-id": "^4.1.3",
|
|
36
37
|
"isbinaryfile": "5.0.2",
|