host-execution-mcp 1.0.0
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/CHANGELOG.md +330 -0
- package/LICENSE +21 -0
- package/README.md +92 -0
- package/SECURITY.md +72 -0
- package/dist/access/docker-runtime.d.ts +38 -0
- package/dist/access/docker-runtime.js +61 -0
- package/dist/access/docker-runtime.js.map +1 -0
- package/dist/access/index.d.ts +110 -0
- package/dist/access/index.js +174 -0
- package/dist/access/index.js.map +1 -0
- package/dist/access/paradi-auth.d.ts +33 -0
- package/dist/access/paradi-auth.js +89 -0
- package/dist/access/paradi-auth.js.map +1 -0
- package/dist/access/paradi-transport.d.ts +10 -0
- package/dist/access/paradi-transport.js +39 -0
- package/dist/access/paradi-transport.js.map +1 -0
- package/dist/access/paradi-username.d.ts +5 -0
- package/dist/access/paradi-username.js +14 -0
- package/dist/access/paradi-username.js.map +1 -0
- package/dist/access/probe.d.ts +14 -0
- package/dist/access/probe.js +63 -0
- package/dist/access/probe.js.map +1 -0
- package/dist/access/session-pool.d.ts +25 -0
- package/dist/access/session-pool.js +46 -0
- package/dist/access/session-pool.js.map +1 -0
- package/dist/access/ssh-transport.d.ts +16 -0
- package/dist/access/ssh-transport.js +74 -0
- package/dist/access/ssh-transport.js.map +1 -0
- package/dist/access/types.d.ts +43 -0
- package/dist/access/types.js +21 -0
- package/dist/access/types.js.map +1 -0
- package/dist/config.d.ts +52 -0
- package/dist/config.js +179 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +4 -0
- package/dist/instructions.js +93 -0
- package/dist/instructions.js.map +1 -0
- package/dist/kubectl/runner.d.ts +32 -0
- package/dist/kubectl/runner.js +79 -0
- package/dist/kubectl/runner.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +24 -0
- package/dist/server.js.map +1 -0
- package/dist/ssh/access-client.d.ts +62 -0
- package/dist/ssh/access-client.js +470 -0
- package/dist/ssh/access-client.js.map +1 -0
- package/dist/ssh/access-errors.d.ts +53 -0
- package/dist/ssh/access-errors.js +180 -0
- package/dist/ssh/access-errors.js.map +1 -0
- package/dist/ssh/access-sftp.d.ts +14 -0
- package/dist/ssh/access-sftp.js +456 -0
- package/dist/ssh/access-sftp.js.map +1 -0
- package/dist/ssh/bastion-client.d.ts +60 -0
- package/dist/ssh/bastion-client.js +423 -0
- package/dist/ssh/bastion-client.js.map +1 -0
- package/dist/ssh/bastion-errors.d.ts +62 -0
- package/dist/ssh/bastion-errors.js +190 -0
- package/dist/ssh/bastion-errors.js.map +1 -0
- package/dist/ssh/hop1-sftp.d.ts +14 -0
- package/dist/ssh/hop1-sftp.js +437 -0
- package/dist/ssh/hop1-sftp.js.map +1 -0
- package/dist/tools/copy-job-schemas.d.ts +709 -0
- package/dist/tools/copy-job-schemas.js +48 -0
- package/dist/tools/copy-job-schemas.js.map +1 -0
- package/dist/tools/register.d.ts +14 -0
- package/dist/tools/register.js +619 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/tools/remote-schemas.d.ts +879 -0
- package/dist/tools/remote-schemas.js +214 -0
- package/dist/tools/remote-schemas.js.map +1 -0
- package/dist/utils/copy-executor.d.ts +41 -0
- package/dist/utils/copy-executor.js +231 -0
- package/dist/utils/copy-executor.js.map +1 -0
- package/dist/utils/copy-job-manager.d.ts +34 -0
- package/dist/utils/copy-job-manager.js +400 -0
- package/dist/utils/copy-job-manager.js.map +1 -0
- package/dist/utils/copy-job-store.d.ts +18 -0
- package/dist/utils/copy-job-store.js +104 -0
- package/dist/utils/copy-job-store.js.map +1 -0
- package/dist/utils/copy-job-types.d.ts +133 -0
- package/dist/utils/copy-job-types.js +37 -0
- package/dist/utils/copy-job-types.js.map +1 -0
- package/dist/utils/copy-transfer.d.ts +59 -0
- package/dist/utils/copy-transfer.js +86 -0
- package/dist/utils/copy-transfer.js.map +1 -0
- package/dist/utils/remote-copy.d.ts +14 -0
- package/dist/utils/remote-copy.js +115 -0
- package/dist/utils/remote-copy.js.map +1 -0
- package/dist/utils/remote-executor.d.ts +15 -0
- package/dist/utils/remote-executor.js +34 -0
- package/dist/utils/remote-executor.js.map +1 -0
- package/dist/utils/remote-target.d.ts +22 -0
- package/dist/utils/remote-target.js +75 -0
- package/dist/utils/remote-target.js.map +1 -0
- package/dist/utils/result.d.ts +87 -0
- package/dist/utils/result.js +81 -0
- package/dist/utils/result.js.map +1 -0
- package/dist/utils/shell-quote.d.ts +22 -0
- package/dist/utils/shell-quote.js +55 -0
- package/dist/utils/shell-quote.js.map +1 -0
- package/dist/utils/timeout.d.ts +1 -0
- package/dist/utils/timeout.js +18 -0
- package/dist/utils/timeout.js.map +1 -0
- package/dist/utils/truncate.d.ts +5 -0
- package/dist/utils/truncate.js +12 -0
- package/dist/utils/truncate.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/docs/AGENT_GUIDE.md +161 -0
- package/docs/CONFIGURATION.md +130 -0
- package/docs/COPY_SPECIALIZED_TEST_CHECKLIST.md +9 -0
- package/docs/HOP1_E2E_CHECKLIST.md +128 -0
- package/docs/HOP1_E2E_RESULTS.json +647 -0
- package/docs/PARADI_ACCESS_PLAN.md +272 -0
- package/docs/REMOTE_COPY_JOB_API.md +92 -0
- package/docs/TODO.md +66 -0
- package/docs/USER_GUIDE.zh-CN.md +93 -0
- package/docs/clients/claude-desktop.json.example +12 -0
- package/docs/clients/cursor-npx.json.example +12 -0
- package/docs/clients/cursor.json.example +12 -0
- package/docs/clients/vscode.json.example +12 -0
- package/package.json +65 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { Client } from "ssh2";
|
|
2
|
+
import { resolveAccessSshIdentity, resolveSshAuthOptions } from "../config.js";
|
|
3
|
+
import { bashSingleQuote, buildBashLcCommand } from "../utils/shell-quote.js";
|
|
4
|
+
import { throwIfAborted, } from "../utils/copy-transfer.js";
|
|
5
|
+
import { transferLocalBastion } from "./hop1-sftp.js";
|
|
6
|
+
import { AccessUnavailableError, isAccessUnavailableError, shouldRetryBastionConnect, toAccessUnavailableError, } from "./bastion-errors.js";
|
|
7
|
+
/** Positive readiness TTL after a successful probe / connect. */
|
|
8
|
+
const READY_TTL_MS = 30_000;
|
|
9
|
+
/** Negative cache after classified connect failure (avoid hammering). */
|
|
10
|
+
const UNAVAILABLE_TTL_MS = 15_000;
|
|
11
|
+
/** SSH readyTimeout + hard deadline for probe / check. */
|
|
12
|
+
const PROBE_READY_TIMEOUT_MS = 5_000;
|
|
13
|
+
/** Shell verify after SSH ready (within overall ?10s probe budget). */
|
|
14
|
+
const PROBE_SHELL_TIMEOUT_MS = 5_000;
|
|
15
|
+
/** Shared exec session connect timeout. */
|
|
16
|
+
const EXEC_CONNECT_TIMEOUT_MS = 20_000;
|
|
17
|
+
/** Max reconnects for transient stream-phase drops during exec. */
|
|
18
|
+
const MAX_RECONNECT_ATTEMPTS = 3;
|
|
19
|
+
export class BastionClient {
|
|
20
|
+
client = null;
|
|
21
|
+
connecting = null;
|
|
22
|
+
/** Serializes ensureBastionReady / check cache updates. */
|
|
23
|
+
gate = Promise.resolve();
|
|
24
|
+
config;
|
|
25
|
+
readyUntil = 0;
|
|
26
|
+
unavailableUntil = 0;
|
|
27
|
+
lastUnavailable = null;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Ensure bastion is reachable (TTL-cached). Uses an ephemeral SSH probe ?
|
|
33
|
+
* never disconnects an in-flight shared exec session on success.
|
|
34
|
+
*/
|
|
35
|
+
async ensureBastionReady() {
|
|
36
|
+
await this.withGate(async () => {
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
if (now < this.unavailableUntil && this.lastUnavailable) {
|
|
39
|
+
throw this.lastUnavailable;
|
|
40
|
+
}
|
|
41
|
+
if (this.client && now < this.readyUntil) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
await this.probeEphemeral();
|
|
46
|
+
this.markReady();
|
|
47
|
+
if (!this.client) {
|
|
48
|
+
await this.ensureConnectedUnlocked();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
throw this.markConnectUnavailable(error);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Short-timeout Local to ACCESS probe (ephemeral client; <=10s worst case).
|
|
58
|
+
* Respects negative TTL (returns cached failure). Does not sever shared exec SSH.
|
|
59
|
+
*/
|
|
60
|
+
async check() {
|
|
61
|
+
return this.withGate(async () => {
|
|
62
|
+
const identity = resolveAccessSshIdentity(this.config);
|
|
63
|
+
const host = identity.host;
|
|
64
|
+
const port = identity.port;
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
if (now < this.unavailableUntil && this.lastUnavailable) {
|
|
67
|
+
return this.lastUnavailable.toJSON();
|
|
68
|
+
}
|
|
69
|
+
const started = Date.now();
|
|
70
|
+
try {
|
|
71
|
+
await this.probeEphemeral();
|
|
72
|
+
this.markReady();
|
|
73
|
+
const kindHint = this.config.accessKind === "paradi-gateway"
|
|
74
|
+
? ` (paradi ? ${this.config.targetHost})`
|
|
75
|
+
: "";
|
|
76
|
+
return {
|
|
77
|
+
reachable: true,
|
|
78
|
+
latencyMs: Date.now() - started,
|
|
79
|
+
host,
|
|
80
|
+
port,
|
|
81
|
+
auth: "ok",
|
|
82
|
+
message: `ACCESS OK: ${host}:${port}${kindHint}`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
return this.markConnectUnavailable(error).toJSON();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async exec(command, timeoutMs, cwd, signal) {
|
|
91
|
+
const effectiveTimeout = timeoutMs ?? this.config.defaultTimeoutMs;
|
|
92
|
+
const remoteCommand = buildBashLcCommand(command, cwd);
|
|
93
|
+
const started = Date.now();
|
|
94
|
+
await this.ensureBastionReady();
|
|
95
|
+
let lastError;
|
|
96
|
+
for (let attempt = 1; attempt <= MAX_RECONNECT_ATTEMPTS; attempt++) {
|
|
97
|
+
try {
|
|
98
|
+
throwIfAborted(signal);
|
|
99
|
+
await this.ensureConnected();
|
|
100
|
+
const result = await this.execOnClient(this.requireClient(), remoteCommand, {
|
|
101
|
+
timeoutMs: effectiveTimeout,
|
|
102
|
+
signal,
|
|
103
|
+
});
|
|
104
|
+
this.markReady();
|
|
105
|
+
return { ...result, durationMs: Date.now() - started };
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
lastError = error;
|
|
109
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
110
|
+
if (signal?.aborted || msg === "Copy aborted") {
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
// Stream-phase: only elevate true bastion-down signals (not ECONNRESET/EPIPE).
|
|
114
|
+
const unavailable = toAccessUnavailableError(error, this.config.accessHost, this.config.accessPort, "stream");
|
|
115
|
+
if (unavailable) {
|
|
116
|
+
throw this.markConnectUnavailable(unavailable);
|
|
117
|
+
}
|
|
118
|
+
if (!shouldRetryBastionConnect(error)) {
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
this.disconnect();
|
|
122
|
+
if (attempt === MAX_RECONNECT_ATTEMPTS) {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
128
|
+
}
|
|
129
|
+
disconnect() {
|
|
130
|
+
if (this.client) {
|
|
131
|
+
this.client.end();
|
|
132
|
+
this.client = null;
|
|
133
|
+
}
|
|
134
|
+
this.connecting = null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Upload local path (file or directory) ? bastion via independent Hop1 SFTP.
|
|
138
|
+
* Transfer-phase errors are not reclassified into ACCESS_UNAVAILABLE.
|
|
139
|
+
*/
|
|
140
|
+
async uploadPath(localPath, remotePath, options) {
|
|
141
|
+
await this.ensureBastionReady();
|
|
142
|
+
try {
|
|
143
|
+
return await transferLocalBastion({
|
|
144
|
+
direction: "upload",
|
|
145
|
+
localPath,
|
|
146
|
+
remotePath,
|
|
147
|
+
config: this.config,
|
|
148
|
+
options,
|
|
149
|
+
}, (remote, timeoutMs) => this.remoteSha256(remote, timeoutMs));
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
// Only connect-time AccessUnavailableError from Hop1 SFTP connect is cached.
|
|
153
|
+
if (isAccessUnavailableError(error)) {
|
|
154
|
+
throw this.markConnectUnavailable(error);
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Download bastion path (file or directory) ? local via independent Hop1 SFTP.
|
|
161
|
+
*/
|
|
162
|
+
async downloadPath(remotePath, localPath, options) {
|
|
163
|
+
await this.ensureBastionReady();
|
|
164
|
+
try {
|
|
165
|
+
return await transferLocalBastion({
|
|
166
|
+
direction: "download",
|
|
167
|
+
localPath,
|
|
168
|
+
remotePath,
|
|
169
|
+
config: this.config,
|
|
170
|
+
options,
|
|
171
|
+
}, (remote, timeoutMs) => this.remoteSha256(remote, timeoutMs));
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (isAccessUnavailableError(error)) {
|
|
175
|
+
throw this.markConnectUnavailable(error);
|
|
176
|
+
}
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async withGate(fn) {
|
|
181
|
+
const prev = this.gate;
|
|
182
|
+
let release;
|
|
183
|
+
this.gate = new Promise((resolve) => {
|
|
184
|
+
release = resolve;
|
|
185
|
+
});
|
|
186
|
+
await prev;
|
|
187
|
+
try {
|
|
188
|
+
return await fn();
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
release();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
markReady() {
|
|
195
|
+
this.readyUntil = Date.now() + READY_TTL_MS;
|
|
196
|
+
this.unavailableUntil = 0;
|
|
197
|
+
this.lastUnavailable = null;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Record a connect-phase failure. Negative TTL only for classified causes
|
|
201
|
+
* (not UNKNOWN), so transient unknowns are not blackholed for 15s.
|
|
202
|
+
*/
|
|
203
|
+
markConnectUnavailable(error) {
|
|
204
|
+
const unavailable = (isAccessUnavailableError(error) ? error : null) ??
|
|
205
|
+
toAccessUnavailableError(error, this.config.accessHost, this.config.accessPort, "connect") ??
|
|
206
|
+
new AccessUnavailableError({
|
|
207
|
+
causeCode: "UNKNOWN",
|
|
208
|
+
host: this.config.accessHost,
|
|
209
|
+
port: this.config.accessPort,
|
|
210
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
211
|
+
cause: error,
|
|
212
|
+
});
|
|
213
|
+
this.disconnect();
|
|
214
|
+
this.readyUntil = 0;
|
|
215
|
+
if (unavailable.causeCode === "UNKNOWN") {
|
|
216
|
+
this.unavailableUntil = 0;
|
|
217
|
+
this.lastUnavailable = null;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
this.unavailableUntil = Date.now() + UNAVAILABLE_TTL_MS;
|
|
221
|
+
this.lastUnavailable = unavailable;
|
|
222
|
+
}
|
|
223
|
+
return unavailable;
|
|
224
|
+
}
|
|
225
|
+
/** Ephemeral SSH + shell probe; never assigns or disconnects `this.client`. */
|
|
226
|
+
async probeEphemeral() {
|
|
227
|
+
const client = await this.openSshClient(PROBE_READY_TIMEOUT_MS);
|
|
228
|
+
try {
|
|
229
|
+
const result = await this.execOnClient(client, "echo bastion_ok", {
|
|
230
|
+
timeoutMs: PROBE_SHELL_TIMEOUT_MS,
|
|
231
|
+
});
|
|
232
|
+
if (result.exitCode !== 0 || !result.stdout.includes("bastion_ok")) {
|
|
233
|
+
throw new AccessUnavailableError({
|
|
234
|
+
causeCode: "SSH_HANDSHAKE",
|
|
235
|
+
host: this.config.accessHost,
|
|
236
|
+
port: this.config.accessPort,
|
|
237
|
+
detail: `shell probe failed: exit=${result.exitCode} stdout=${result.stdout.trim()}`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
try {
|
|
243
|
+
client.end();
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// ignore
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async remoteSha256(remotePath, timeoutMs) {
|
|
251
|
+
const raw = await this.exec(`sha256sum ${bashSingleQuote(remotePath)} | awk '{print $1}'`, timeoutMs);
|
|
252
|
+
const hash = raw.stdout.trim().split(/\s+/)[0];
|
|
253
|
+
if (!/^[a-f0-9]{64}$/i.test(hash)) {
|
|
254
|
+
throw new Error(`Failed to compute remote sha256 for ${remotePath}: ${raw.stdout || raw.stderr}`);
|
|
255
|
+
}
|
|
256
|
+
return hash.toLowerCase();
|
|
257
|
+
}
|
|
258
|
+
async ensureConnected() {
|
|
259
|
+
await this.withGate(() => this.ensureConnectedUnlocked());
|
|
260
|
+
}
|
|
261
|
+
async ensureConnectedUnlocked() {
|
|
262
|
+
if (this.client) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (this.connecting) {
|
|
266
|
+
await this.connecting;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
this.connecting = (async () => {
|
|
270
|
+
try {
|
|
271
|
+
const client = await this.openSshClient(EXEC_CONNECT_TIMEOUT_MS);
|
|
272
|
+
this.client = client;
|
|
273
|
+
client.on("close", () => {
|
|
274
|
+
if (this.client === client) {
|
|
275
|
+
this.client = null;
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
throw this.markConnectUnavailable(error);
|
|
281
|
+
}
|
|
282
|
+
})();
|
|
283
|
+
try {
|
|
284
|
+
await this.connecting;
|
|
285
|
+
}
|
|
286
|
+
finally {
|
|
287
|
+
this.connecting = null;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
requireClient() {
|
|
291
|
+
if (!this.client) {
|
|
292
|
+
throw new Error("SSH client is not connected");
|
|
293
|
+
}
|
|
294
|
+
return this.client;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Open a dedicated ssh2 Client with readyTimeout + hard deadline
|
|
298
|
+
* (covers TCP blackhole where ssh2 readyTimeout alone is insufficient).
|
|
299
|
+
*/
|
|
300
|
+
openSshClient(readyTimeoutMs) {
|
|
301
|
+
const auth = resolveSshAuthOptions(this.config);
|
|
302
|
+
const identity = resolveAccessSshIdentity(this.config);
|
|
303
|
+
const connectConfig = {
|
|
304
|
+
host: identity.host,
|
|
305
|
+
port: identity.port,
|
|
306
|
+
username: identity.username,
|
|
307
|
+
readyTimeout: readyTimeoutMs,
|
|
308
|
+
};
|
|
309
|
+
if (auth.agent) {
|
|
310
|
+
connectConfig.agent = auth.agent;
|
|
311
|
+
}
|
|
312
|
+
if (auth.privateKey) {
|
|
313
|
+
connectConfig.privateKey = auth.privateKey;
|
|
314
|
+
}
|
|
315
|
+
if (auth.password) {
|
|
316
|
+
connectConfig.password = auth.password;
|
|
317
|
+
}
|
|
318
|
+
return new Promise((resolve, reject) => {
|
|
319
|
+
const client = new Client();
|
|
320
|
+
let settled = false;
|
|
321
|
+
const finish = (fn) => {
|
|
322
|
+
if (settled) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
settled = true;
|
|
326
|
+
clearTimeout(timer);
|
|
327
|
+
fn();
|
|
328
|
+
};
|
|
329
|
+
const timer = setTimeout(() => {
|
|
330
|
+
finish(() => {
|
|
331
|
+
try {
|
|
332
|
+
client.end();
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// ignore
|
|
336
|
+
}
|
|
337
|
+
reject(Object.assign(new Error("Timed out while waiting for handshake"), {
|
|
338
|
+
code: "ETIMEDOUT",
|
|
339
|
+
}));
|
|
340
|
+
});
|
|
341
|
+
}, readyTimeoutMs);
|
|
342
|
+
client
|
|
343
|
+
.on("ready", () => {
|
|
344
|
+
finish(() => resolve(client));
|
|
345
|
+
})
|
|
346
|
+
.on("error", (error) => {
|
|
347
|
+
finish(() => reject(error));
|
|
348
|
+
})
|
|
349
|
+
.on("close", () => {
|
|
350
|
+
finish(() => reject(new Error("SSH closed before ready")));
|
|
351
|
+
})
|
|
352
|
+
.connect(connectConfig);
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
execOnClient(client, command, options = { timeoutMs: 60_000 }) {
|
|
356
|
+
throwIfAborted(options.signal);
|
|
357
|
+
return new Promise((resolve, reject) => {
|
|
358
|
+
let settled = false;
|
|
359
|
+
let stream;
|
|
360
|
+
const cleanup = () => {
|
|
361
|
+
clearTimeout(timer);
|
|
362
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
363
|
+
};
|
|
364
|
+
const fail = (error) => {
|
|
365
|
+
if (settled) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
settled = true;
|
|
369
|
+
cleanup();
|
|
370
|
+
try {
|
|
371
|
+
stream?.close?.();
|
|
372
|
+
stream?.destroy?.();
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
// ignore
|
|
376
|
+
}
|
|
377
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
378
|
+
};
|
|
379
|
+
const onAbort = () => {
|
|
380
|
+
fail(new Error("Copy aborted"));
|
|
381
|
+
};
|
|
382
|
+
const timer = setTimeout(() => {
|
|
383
|
+
fail(new Error(`Operation timed out after ${options.timeoutMs}ms`));
|
|
384
|
+
}, options.timeoutMs);
|
|
385
|
+
if (options.signal) {
|
|
386
|
+
if (options.signal.aborted) {
|
|
387
|
+
onAbort();
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
391
|
+
}
|
|
392
|
+
client.exec(command, (error, execStream) => {
|
|
393
|
+
if (error) {
|
|
394
|
+
fail(error);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
stream = execStream;
|
|
398
|
+
let stdout = "";
|
|
399
|
+
let stderr = "";
|
|
400
|
+
execStream
|
|
401
|
+
.on("close", (code) => {
|
|
402
|
+
if (settled) {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
settled = true;
|
|
406
|
+
cleanup();
|
|
407
|
+
resolve({
|
|
408
|
+
stdout,
|
|
409
|
+
stderr,
|
|
410
|
+
exitCode: code ?? 1,
|
|
411
|
+
});
|
|
412
|
+
})
|
|
413
|
+
.on("data", (chunk) => {
|
|
414
|
+
stdout += chunk.toString();
|
|
415
|
+
});
|
|
416
|
+
execStream.stderr.on("data", (chunk) => {
|
|
417
|
+
stderr += chunk.toString();
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
//# sourceMappingURL=bastion-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bastion-client.js","sourceRoot":"","sources":["../../src/ssh/bastion-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
|
|
3
|
+
* Domain errors for Hop1 ACCESS connectivity (environment vs business failure).
|
|
4
|
+
|
|
5
|
+
*
|
|
6
|
+
|
|
7
|
+
* phase=connect: TCP/SSH handshake / auth — may become ACCESS_UNAVAILABLE + neg-cache
|
|
8
|
+
|
|
9
|
+
* phase=stream: mid-session channel/exec — ECONNRESET/EPIPE stay retryable, not access-down
|
|
10
|
+
|
|
11
|
+
*/
|
|
12
|
+
export type AccessUnavailableCause = "VPN_OR_NETWORK" | "AUTH_FAILED" | "SSH_HANDSHAKE" | "UNKNOWN";
|
|
13
|
+
/** Where the error was observed. */
|
|
14
|
+
export type BastionErrorPhase = "connect" | "stream";
|
|
15
|
+
export interface AccessCheckResult {
|
|
16
|
+
reachable: boolean;
|
|
17
|
+
latencyMs?: number;
|
|
18
|
+
host: string;
|
|
19
|
+
port: number;
|
|
20
|
+
auth?: "ok" | "failed";
|
|
21
|
+
reason?: AccessUnavailableCause;
|
|
22
|
+
code?: "ACCESS_UNAVAILABLE";
|
|
23
|
+
retryable?: boolean;
|
|
24
|
+
message: string;
|
|
25
|
+
hints?: string[];
|
|
26
|
+
}
|
|
27
|
+
export declare class AccessUnavailableError extends Error {
|
|
28
|
+
readonly code: "ACCESS_UNAVAILABLE";
|
|
29
|
+
readonly causeCode: AccessUnavailableCause;
|
|
30
|
+
/** Always false today — Agents must not auto-retry access-down. */
|
|
31
|
+
readonly retryable = false;
|
|
32
|
+
readonly hints: string[];
|
|
33
|
+
readonly host: string;
|
|
34
|
+
readonly port: number;
|
|
35
|
+
constructor(input: {
|
|
36
|
+
causeCode: AccessUnavailableCause;
|
|
37
|
+
host: string;
|
|
38
|
+
port: number;
|
|
39
|
+
detail?: string;
|
|
40
|
+
cause?: unknown;
|
|
41
|
+
});
|
|
42
|
+
toJSON(): AccessCheckResult;
|
|
43
|
+
}
|
|
44
|
+
export declare function isAccessUnavailableError(error: unknown): error is AccessUnavailableError;
|
|
45
|
+
/** Exec/command wall-clock timeout — not an ACCESS connectivity failure. */
|
|
46
|
+
export declare function isCommandTimeoutError(error: unknown): boolean;
|
|
47
|
+
/**
|
|
48
|
+
|
|
49
|
+
* Whether the exec reconnect loop should try again (stream-phase only).
|
|
50
|
+
|
|
51
|
+
* Connect failures never enter this path — they become AccessUnavailableError first.
|
|
52
|
+
|
|
53
|
+
*/
|
|
54
|
+
export declare function shouldRetryBastionConnect(error: unknown): boolean;
|
|
55
|
+
/**
|
|
56
|
+
|
|
57
|
+
* Map an error to AccessUnavailableError, or null if it is not an access-down signal.
|
|
58
|
+
|
|
59
|
+
* Connect-phase includes ECONNRESET/EPIPE; stream-phase does not (those stay retryable).
|
|
60
|
+
|
|
61
|
+
*/
|
|
62
|
+
export declare function toAccessUnavailableError(error: unknown, host: string, port: number, phase: BastionErrorPhase): AccessUnavailableError | null;
|