bdy 1.22.84 → 1.22.85-beta

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.22.84",
4
+ "version": "1.22.85-beta",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "homepage": "https://buddy.works/docs/cli",
@@ -139,10 +139,10 @@ class AgentSocketClient extends events_1.default {
139
139
  forceBase64: true,
140
140
  transports: ['websocket'],
141
141
  reconnection: false,
142
- rejectUnauthorized: false,
142
+ rejectUnauthorized: !(0, utils_1.isLocalHost)(host),
143
143
  // @ts-ignore
144
144
  agent: new https_1.Agent({
145
- rejectUnauthorized: false,
145
+ rejectUnauthorized: !(0, utils_1.isLocalHost)(host),
146
146
  }),
147
147
  maxHttpBufferSize: 3e6,
148
148
  extraHeaders: {
@@ -26,7 +26,7 @@ class ApiClient {
26
26
  this.clientToken = clientToken;
27
27
  this.client = new undici_1.Pool(baseUrl, {
28
28
  connect: {
29
- rejectUnauthorized: false,
29
+ rejectUnauthorized: !(0, utils_1.isLocalHost)(baseUrl.hostname),
30
30
  },
31
31
  });
32
32
  }
@@ -706,7 +706,7 @@ class ApiClient {
706
706
  client_name: name,
707
707
  grant_types: ['authorization_code', 'refresh_token'],
708
708
  response_types: ['code'],
709
- token_endpoint_auth_method: 'client_secret_basic',
709
+ token_endpoint_auth_method: 'client_secret_post',
710
710
  token_expires_in: 3600,
711
711
  },
712
712
  parseResponseBody: true,
@@ -732,7 +732,7 @@ class ApiClient {
732
732
  parseResponseBody: true,
733
733
  });
734
734
  }
735
- async exchangeAppToken(code, clientId, clientSecret, redirectUrl) {
735
+ async exchangeAppToken(code, clientId, clientSecret, redirectUrl, codeVerifier) {
736
736
  return await this.request({
737
737
  method: 'POST',
738
738
  path: '/oauth2/token',
@@ -742,6 +742,7 @@ class ApiClient {
742
742
  client_id: clientId,
743
743
  client_secret: clientSecret,
744
744
  redirect_uri: redirectUrl,
745
+ code_verifier: codeVerifier,
745
746
  },
746
747
  parseResponseBody: true,
747
748
  httpUrlEncoded: true,
@@ -7,6 +7,7 @@ exports.authorize = authorize;
7
7
  const cfg_1 = __importDefault(require("../tunnel/cfg"));
8
8
  const output_1 = __importDefault(require("../output"));
9
9
  const node_http_1 = __importDefault(require("node:http"));
10
+ const node_crypto_1 = require("node:crypto");
10
11
  const texts_1 = require("../texts");
11
12
  const utils_1 = require("../utils");
12
13
  const input_1 = __importDefault(require("../input"));
@@ -37,6 +38,13 @@ const OAUTH_CLIENT_APP_SCOPES = [
37
38
  function getRedirectUrl(api) {
38
39
  return `https://${api}/oauth2/cli`;
39
40
  }
41
+ function generatePkcePair() {
42
+ const codeVerifier = (0, node_crypto_1.randomBytes)(32).toString('base64url');
43
+ const codeChallenge = (0, node_crypto_1.createHash)('sha256')
44
+ .update(codeVerifier)
45
+ .digest('base64url');
46
+ return { codeVerifier, codeChallenge };
47
+ }
40
48
  async function waitForOpen(isRegister, abortCode, seconds = 3) {
41
49
  output_1.default.normal(isRegister ? texts_1.TXT_REGISTER_OPENING : texts_1.TXT_LOGIN_OPENING);
42
50
  let star = true;
@@ -66,11 +74,12 @@ async function oauthServer(api, clientId, clientSecret, forceRegisterEmail, forc
66
74
  }, OAUTH_TIMEOUT);
67
75
  return new Promise((resolve) => {
68
76
  const state = (0, uuid_1.v4)();
77
+ const { codeVerifier, codeChallenge } = generatePkcePair();
69
78
  const abortCode = new AbortController();
70
79
  const exchange = async (urlCode, urlState, res) => {
71
80
  const client = new ApiClient(new URL(`https://${api}`));
72
81
  try {
73
- const response = await client.exchangeAppToken(urlCode, clientId, clientSecret, redirectUrl);
82
+ const response = await client.exchangeAppToken(urlCode, clientId, clientSecret, redirectUrl, codeVerifier);
74
83
  if (res)
75
84
  res.end(urlState);
76
85
  s.close();
@@ -111,7 +120,7 @@ async function oauthServer(api, clientId, clientSecret, forceRegisterEmail, forc
111
120
  output_1.default.exitError(texts_1.ERR_LOGIN_HTTP_SERVER_PORT_TAKEN);
112
121
  });
113
122
  s.listen(OAUTH_CLIENT_APP_PORT, OAUTH_CLIENT_APP_HOST, async () => {
114
- let url = `https://${api}/oauth2/authorize?type=web_server&client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code&scope=${encodeURIComponent(OAUTH_CLIENT_APP_SCOPES.join(' '))}&state=${encodeURIComponent(state)}`;
123
+ let url = `https://${api}/oauth2/authorize?type=web_server&client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code&scope=${encodeURIComponent(OAUTH_CLIENT_APP_SCOPES.join(' '))}&state=${encodeURIComponent(state)}&code_challenge=${encodeURIComponent(codeChallenge)}&code_challenge_method=S256`;
115
124
  if (isRegister) {
116
125
  url += `&register_email=${encodeURIComponent(forceRegisterEmail)}&register_name=${encodeURIComponent(forceRegisterName)}`;
117
126
  }
@@ -26,7 +26,7 @@ const makeRequest = async (host, path, body, method = 'POST', respAsJson = true,
26
26
  headers: body ? { 'Content-Type': 'application/json' } : undefined,
27
27
  method,
28
28
  signal: c.signal,
29
- dispatcher: output_1.default.getUndiciUnauthorizedAgent(),
29
+ dispatcher: (0, utils_1.isLocalHost)(host) ? output_1.default.getUndiciUnauthorizedAgent() : undefined,
30
30
  });
31
31
  if (respAsJson)
32
32
  data = await response.json();
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../utils");
7
+ const logger_1 = __importDefault(require("../logger"));
8
+ const tunnel_1 = require("../types/tunnel");
9
+ class TunnelConfig {
10
+ type;
11
+ region;
12
+ target;
13
+ whitelist;
14
+ domain;
15
+ subdomain;
16
+ name;
17
+ timeout;
18
+ useragents;
19
+ headers;
20
+ responseHeaders;
21
+ terminate;
22
+ key;
23
+ cert;
24
+ ca;
25
+ host;
26
+ login;
27
+ password;
28
+ authType;
29
+ serve;
30
+ circuitBreaker;
31
+ log;
32
+ verify;
33
+ compression;
34
+ http2;
35
+ sshIp;
36
+ sshId;
37
+ sshPort;
38
+ sshUser;
39
+ sshPassword;
40
+ sshForwardPort;
41
+ sshClientUser;
42
+ sshClientPassword;
43
+ targetProto;
44
+ targetHost;
45
+ targetPort;
46
+ targetAuth;
47
+ constructor({ type, target, region, timeout, domain, subdomain, name, whitelist, tlsSettings, httpSettings, sshSettings, }) {
48
+ this.type = type;
49
+ this.region = region;
50
+ this.target = target;
51
+ this.whitelist = whitelist || [];
52
+ this.domain = domain;
53
+ this.subdomain = subdomain;
54
+ this.name = name;
55
+ this.timeout = timeout || utils_1.DEFAULT_TIMEOUT;
56
+ this.useragents = [];
57
+ this.headers = [];
58
+ this.responseHeaders = [];
59
+ if (tlsSettings) {
60
+ this.terminate = tlsSettings.terminate;
61
+ this.key = tlsSettings.key;
62
+ this.cert = tlsSettings.cert;
63
+ this.ca = tlsSettings.ca;
64
+ }
65
+ if (httpSettings) {
66
+ this.host = httpSettings.host;
67
+ if (httpSettings.authType) {
68
+ this.authType = httpSettings.authType;
69
+ if (this.authType === tunnel_1.TUNNEL_HTTP_AUTH_TYPE.BASIC) {
70
+ this.login = httpSettings.login || '';
71
+ this.password = httpSettings.password || '';
72
+ }
73
+ }
74
+ else if (httpSettings.login || httpSettings.password) {
75
+ this.authType = tunnel_1.TUNNEL_HTTP_AUTH_TYPE.BASIC;
76
+ this.login = httpSettings.login || '';
77
+ this.password = httpSettings.password || '';
78
+ }
79
+ else {
80
+ this.authType = tunnel_1.TUNNEL_HTTP_AUTH_TYPE.NONE;
81
+ }
82
+ this.ca = httpSettings.ca;
83
+ this.serve = httpSettings.serve;
84
+ this.useragents = httpSettings.userAgents || [];
85
+ this.headers = httpSettings.headers || [];
86
+ this.responseHeaders = httpSettings.responseHeaders || [];
87
+ this.circuitBreaker = httpSettings.circuitBreaker;
88
+ this.log = httpSettings.log;
89
+ this.verify = httpSettings.verify;
90
+ this.compression = httpSettings.compression;
91
+ this.http2 = httpSettings.http2;
92
+ }
93
+ if (sshSettings) {
94
+ this.sshIp = sshSettings.ip;
95
+ this.sshId = sshSettings.sshId;
96
+ this.sshPort = sshSettings.port;
97
+ this.sshUser = sshSettings.user;
98
+ this.sshPassword = sshSettings.password;
99
+ this.sshForwardPort = sshSettings.forwardPort;
100
+ this.sshClientUser = sshSettings.clientUser;
101
+ this.sshClientPassword = sshSettings.clientPassword;
102
+ }
103
+ this.targetProto = 'http';
104
+ this.targetHost = 'localhost';
105
+ this.targetPort = 80;
106
+ this.targetAuth = null;
107
+ if (this.type === tunnel_1.TUNNEL_TYPE.HTTP) {
108
+ let m = this.target.match(utils_1.TARGET_ONLY_PORT_REGEX);
109
+ if (m) {
110
+ this.targetPort = parseInt(m[0], 10);
111
+ }
112
+ else {
113
+ m = this.target.match(utils_1.TARGET_HTTP_REGEX);
114
+ if (m) {
115
+ if (m[2])
116
+ this.targetProto = m[2];
117
+ if (m[6])
118
+ this.targetPort = parseInt(m[6], 10);
119
+ else if (this.targetProto === 'https')
120
+ this.targetPort = 443;
121
+ if (m[4])
122
+ this.targetHost = m[4];
123
+ if (m[3])
124
+ this.targetAuth = m[3].replace(/@$/, '');
125
+ }
126
+ }
127
+ }
128
+ else if (this.type === tunnel_1.TUNNEL_TYPE.SSH) {
129
+ this.targetHost = 'localhost';
130
+ this.targetProto = 'ssh://';
131
+ this.targetPort = 22;
132
+ }
133
+ else {
134
+ const m = this.target.match(utils_1.TARGET_TCP_TLS_REGEX);
135
+ if (m) {
136
+ this.targetPort = parseInt(m[3], 10);
137
+ if (m[2])
138
+ this.targetHost = m[2];
139
+ }
140
+ }
141
+ }
142
+ changed(incoming, tunnelId) {
143
+ const diff = (field, a, b) => {
144
+ logger_1.default.debug(`Tunnel '${tunnelId}' hasChanged: ${field} (running=${JSON.stringify(a)} incoming=${JSON.stringify(b)})`);
145
+ return true;
146
+ };
147
+ if (this.type !== incoming.type)
148
+ return diff('type', this.type, incoming.type);
149
+ if (this.target !== incoming.target)
150
+ return diff('target', this.target, incoming.target);
151
+ if (this.region !== incoming.region)
152
+ return diff('region', this.region, incoming.region);
153
+ if (this.timeout !== incoming.timeout)
154
+ return diff('timeout', this.timeout, incoming.timeout);
155
+ if (this.domain !== incoming.domain)
156
+ return diff('domain', this.domain, incoming.domain);
157
+ if (this.subdomain !== incoming.subdomain)
158
+ return diff('subdomain', this.subdomain, incoming.subdomain);
159
+ if (this.terminate !== incoming.terminate)
160
+ return diff('terminate', this.terminate, incoming.terminate);
161
+ if (this.key !== incoming.key)
162
+ return diff('key', this.key, incoming.key);
163
+ if (this.cert !== incoming.cert)
164
+ return diff('cert', this.cert, incoming.cert);
165
+ if (this.ca !== incoming.ca)
166
+ return diff('ca', this.ca, incoming.ca);
167
+ if (this.host !== incoming.host)
168
+ return diff('host', this.host, incoming.host);
169
+ if (this.login !== incoming.login)
170
+ return diff('login', this.login, incoming.login);
171
+ if (this.password !== incoming.password)
172
+ return diff('password', this.password, incoming.password);
173
+ if (this.authType !== incoming.authType)
174
+ return diff('authType', this.authType, incoming.authType);
175
+ if (this.serve !== incoming.serve)
176
+ return diff('serve', this.serve, incoming.serve);
177
+ if (this.circuitBreaker !== incoming.circuitBreaker)
178
+ return diff('circuitBreaker', this.circuitBreaker, incoming.circuitBreaker);
179
+ if (this.log !== incoming.log)
180
+ return diff('log', this.log, incoming.log);
181
+ if (this.verify !== incoming.verify)
182
+ return diff('verify', this.verify, incoming.verify);
183
+ if (this.http2 !== incoming.http2)
184
+ return diff('http2', this.http2, incoming.http2);
185
+ if (this.compression !== incoming.compression)
186
+ return diff('compression', this.compression, incoming.compression);
187
+ if (this.sshIp !== incoming.sshIp)
188
+ return diff('sshIp', this.sshIp, incoming.sshIp);
189
+ if (this.sshId !== incoming.sshId)
190
+ return diff('sshId', this.sshId, incoming.sshId);
191
+ if (this.sshPort !== incoming.sshPort)
192
+ return diff('sshPort', this.sshPort, incoming.sshPort);
193
+ if (this.sshUser !== incoming.sshUser)
194
+ return diff('sshUser', this.sshUser, incoming.sshUser);
195
+ if (this.sshPassword !== incoming.sshPassword)
196
+ return diff('sshPassword', this.sshPassword, incoming.sshPassword);
197
+ if (this.sshForwardPort !== incoming.sshForwardPort)
198
+ return diff('sshForwardPort', this.sshForwardPort, incoming.sshForwardPort);
199
+ if (this.sshClientPassword !== incoming.sshClientPassword)
200
+ return diff('sshClientPassword', this.sshClientPassword, incoming.sshClientPassword);
201
+ if (this.sshClientUser !== incoming.sshClientUser)
202
+ return diff('sshClientUser', this.sshClientUser, incoming.sshClientUser);
203
+ if (this._stringListChanged('whitelist', this.whitelist, incoming.whitelist, diff))
204
+ return true;
205
+ if (this._stringListChanged('useragents', this.useragents, incoming.useragents, diff))
206
+ return true;
207
+ if (this._headerListChanged('headers', this.headers, incoming.headers, diff))
208
+ return true;
209
+ if (this._headerListChanged('responseHeaders', this.responseHeaders, incoming.responseHeaders, diff))
210
+ return true;
211
+ return false;
212
+ }
213
+ _stringListChanged(field, running, incoming, diff) {
214
+ if (running?.length !== incoming?.length)
215
+ return diff(`${field}.length`, running, incoming);
216
+ if (running && incoming) {
217
+ const a = [...running].sort();
218
+ const b = [...incoming].sort();
219
+ for (let i = 0; i < a.length; i += 1) {
220
+ if (a[i] !== b[i])
221
+ return diff(field, running, incoming);
222
+ }
223
+ }
224
+ return false;
225
+ }
226
+ _headerListChanged(field, running, incoming, diff) {
227
+ if (running?.length !== incoming?.length)
228
+ return diff(`${field}.length`, running, incoming);
229
+ if (running && incoming) {
230
+ const sortHeaders = (a, b) => a.name.localeCompare(b.name);
231
+ const a = [...running].sort(sortHeaders);
232
+ const b = [...incoming].sort(sortHeaders);
233
+ for (let i = 0; i < a.length; i += 1) {
234
+ if (a[i].name !== b[i].name || a[i].value !== b[i].value)
235
+ return diff(field, running, incoming);
236
+ }
237
+ }
238
+ return false;
239
+ }
240
+ }
241
+ exports.default = TunnelConfig;