@zincapp/znvault-cli 4.4.0 → 4.6.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.
Files changed (51) hide show
  1. package/dist/commands/agent/direct/ping.d.ts.map +1 -1
  2. package/dist/commands/agent/direct/ping.js +3 -1
  3. package/dist/commands/agent/direct/ping.js.map +1 -1
  4. package/dist/commands/agent/direct/plugins.d.ts.map +1 -1
  5. package/dist/commands/agent/direct/plugins.js +3 -1
  6. package/dist/commands/agent/direct/plugins.js.map +1 -1
  7. package/dist/commands/agent/direct/update-all.d.ts.map +1 -1
  8. package/dist/commands/agent/direct/update-all.js +9 -6
  9. package/dist/commands/agent/direct/update-all.js.map +1 -1
  10. package/dist/commands/agent/direct/update-plugins.d.ts.map +1 -1
  11. package/dist/commands/agent/direct/update-plugins.js +90 -64
  12. package/dist/commands/agent/direct/update-plugins.js.map +1 -1
  13. package/dist/commands/agent/direct/update.d.ts.map +1 -1
  14. package/dist/commands/agent/direct/update.js +92 -65
  15. package/dist/commands/agent/direct/update.js.map +1 -1
  16. package/dist/commands/agent/direct/version.d.ts.map +1 -1
  17. package/dist/commands/agent/direct/version.js +3 -1
  18. package/dist/commands/agent/direct/version.js.map +1 -1
  19. package/dist/commands/agent/helpers.d.ts +1 -1
  20. package/dist/commands/agent/helpers.d.ts.map +1 -1
  21. package/dist/commands/agent/helpers.js +8 -1
  22. package/dist/commands/agent/helpers.js.map +1 -1
  23. package/dist/commands/agent/types.d.ts +6 -0
  24. package/dist/commands/agent/types.d.ts.map +1 -1
  25. package/dist/commands/kmip/clients.d.ts +4 -0
  26. package/dist/commands/kmip/clients.d.ts.map +1 -1
  27. package/dist/commands/kmip/clients.js +37 -0
  28. package/dist/commands/kmip/clients.js.map +1 -1
  29. package/dist/commands/kmip/index.d.ts.map +1 -1
  30. package/dist/commands/kmip/index.js +7 -1
  31. package/dist/commands/kmip/index.js.map +1 -1
  32. package/dist/commands/kmip/types.d.ts +1 -0
  33. package/dist/commands/kmip/types.d.ts.map +1 -1
  34. package/dist/commands/ssh/connect.d.ts +22 -0
  35. package/dist/commands/ssh/connect.d.ts.map +1 -1
  36. package/dist/commands/ssh/connect.js +90 -163
  37. package/dist/commands/ssh/connect.js.map +1 -1
  38. package/dist/commands/ssh/forward.d.ts +49 -0
  39. package/dist/commands/ssh/forward.d.ts.map +1 -0
  40. package/dist/commands/ssh/forward.js +151 -0
  41. package/dist/commands/ssh/forward.js.map +1 -0
  42. package/dist/commands/ssh/index.d.ts.map +1 -1
  43. package/dist/commands/ssh/index.js +9 -1
  44. package/dist/commands/ssh/index.js.map +1 -1
  45. package/dist/index.js +13 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/lib/ssh-tunnel.d.ts +41 -0
  48. package/dist/lib/ssh-tunnel.d.ts.map +1 -0
  49. package/dist/lib/ssh-tunnel.js +144 -0
  50. package/dist/lib/ssh-tunnel.js.map +1 -0
  51. package/package.json +1 -1
@@ -4,205 +4,132 @@ import { getCurrentProfile } from '../../lib/config.js';
4
4
  import { getDefaultKeyPath, getCertificatePath, isCertificateValid, signCertificate, } from './helpers.js';
5
5
  import { resolveBookmark } from './bookmark.js';
6
6
  /**
7
- * Execute SSH connection with certificate authentication
8
- * Extracted for reuse by both `ssh connect` and `ssh <destination>` shortcuts
7
+ * Resolve the SSH key, ensure a valid vault-CA certificate (auto-signing if
8
+ * needed), and return the destination parts + base ssh args. No spawning,
9
+ * no process.exit, no stdio side effects — safe to call from any command.
10
+ *
11
+ * Mirrors the key-resolution + sign logic previously inline in executeConnect,
12
+ * so `ssh connect` and `ssh forward` share one code path.
9
13
  */
10
- export async function executeConnect(destination, remoteCommand, options) {
14
+ export async function ensureSignedSshBase(destination, options) {
11
15
  const fs = await import('fs');
12
16
  const path = await import('path');
13
- const { spawn } = await import('child_process');
14
- // Get profile config for defaults
15
17
  const profile = getCurrentProfile();
16
- // Resolve destination: could be a bookmark, user@host, or just host
17
18
  let user;
18
19
  let host;
19
20
  let port = options.port ?? '22';
20
21
  let identityOverride = options.identity;
21
22
  let principalsOverride = options.principals;
22
- // Check if destination is a bookmark
23
23
  const bookmark = resolveBookmark(destination);
24
24
  if (bookmark) {
25
25
  host = bookmark.host;
26
26
  user = bookmark.user;
27
- if (bookmark.port) {
27
+ if (bookmark.port)
28
28
  port = bookmark.port.toString();
29
- }
30
- if (bookmark.identity) {
29
+ if (bookmark.identity)
31
30
  identityOverride = bookmark.identity;
32
- }
33
31
  if (bookmark.principals && !options.principals) {
34
32
  principalsOverride = bookmark.principals.join(',');
35
33
  }
36
- if (options.verbose) {
37
- output.info(`Using bookmark '${destination}' → ${bookmark.host}`);
38
- }
39
34
  }
40
35
  else if (destination.includes('@')) {
41
36
  const parts = destination.split('@');
42
37
  user = parts[0];
43
- host = parts.slice(1).join('@'); // Handle IPv6 or multiple @
38
+ host = parts.slice(1).join('@');
44
39
  }
45
40
  else {
46
41
  host = destination;
47
- // Use default user from config if available
48
- if (profile.sshUser) {
42
+ if (profile.sshUser)
49
43
  user = profile.sshUser;
50
- }
51
44
  }
52
- // Command line options override bookmark settings
53
- if (options.port && options.port !== '22') {
45
+ if (options.port && options.port !== '22')
54
46
  port = options.port;
47
+ // Resolve key
48
+ let keyPath;
49
+ if (identityOverride) {
50
+ keyPath = path.resolve(identityOverride.replace(/^~/, process.env.HOME ?? ''));
51
+ if (!fs.existsSync(keyPath))
52
+ throw new Error(`SSH key not found: ${keyPath}`);
53
+ }
54
+ else if (profile.sshIdentity && fs.existsSync(profile.sshIdentity)) {
55
+ keyPath = profile.sshIdentity;
55
56
  }
56
- const verbose = (msg) => {
57
- if (options.verbose) {
58
- output.info(msg);
57
+ else {
58
+ const defaultKey = await getDefaultKeyPath();
59
+ if (!defaultKey) {
60
+ throw new Error('No SSH key found in ~/.ssh/ — generate one with: ssh-keygen -t ed25519');
59
61
  }
60
- };
62
+ keyPath = defaultKey;
63
+ }
64
+ const pubKeyPath = `${keyPath}.pub`;
65
+ if (!fs.existsSync(pubKeyPath))
66
+ throw new Error(`Public key not found: ${pubKeyPath}`);
67
+ // Ensure cert
68
+ const certPath = await getCertificatePath(keyPath);
69
+ const certStatus = await isCertificateValid(certPath);
70
+ if (options.forceSign || !certStatus.valid) {
71
+ await signCertificate(pubKeyPath, certPath, principalsOverride, options.ttl, options.tenant);
72
+ }
73
+ // Build base ssh args (identity + cert + optional port)
74
+ const baseSshArgs = ['-i', keyPath];
75
+ if (port && port !== '22')
76
+ baseSshArgs.push('-p', port);
77
+ baseSshArgs.push('-o', `CertificateFile=${certPath}`);
78
+ return { keyPath, certPath, user, host, port, baseSshArgs };
79
+ }
80
+ /**
81
+ * Execute SSH connection with certificate authentication
82
+ * Extracted for reuse by both `ssh connect` and `ssh <destination>` shortcuts
83
+ */
84
+ export async function executeConnect(destination, remoteCommand, options) {
85
+ const { spawn } = await import('child_process');
86
+ const verbose = (msg) => { if (options.verbose)
87
+ output.info(msg); };
88
+ let base;
61
89
  try {
62
- // Step 1: Find SSH key
63
- let keyPath;
64
- if (identityOverride) {
65
- keyPath = path.resolve(identityOverride.replace(/^~/, process.env.HOME ?? ''));
66
- if (!fs.existsSync(keyPath)) {
67
- output.error(`SSH key not found: ${keyPath}`);
68
- process.exit(1);
69
- }
70
- verbose(`Using specified key: ${keyPath}`);
71
- }
72
- else if (profile.sshIdentity && fs.existsSync(profile.sshIdentity)) {
73
- // Use configured identity from profile
74
- keyPath = profile.sshIdentity;
75
- verbose(`Using configured key: ${keyPath}`);
76
- }
77
- else {
78
- const defaultKey = await getDefaultKeyPath();
79
- if (!defaultKey) {
80
- output.error('No SSH key found in ~/.ssh/');
81
- output.info('Generate one with: ssh-keygen -t ed25519');
82
- output.info('Or specify a key with: znvault ssh -i /path/to/key user@host');
83
- process.exit(1);
84
- }
85
- keyPath = defaultKey;
86
- verbose(`Using default key: ${keyPath}`);
87
- }
88
- const pubKeyPath = `${keyPath}.pub`;
89
- if (!fs.existsSync(pubKeyPath)) {
90
- output.error(`Public key not found: ${pubKeyPath}`);
91
- process.exit(1);
92
- }
93
- // Step 2: Check certificate validity
94
- const certPath = await getCertificatePath(keyPath);
95
- verbose(`Certificate path: ${certPath}`);
96
- const certStatus = await isCertificateValid(certPath);
97
- const needsSign = options.forceSign || !certStatus.valid;
98
- if (options.verbose && !certStatus.valid) {
99
- output.warn(`Certificate needs signing: ${certStatus.reason}`);
100
- }
101
- else if (options.verbose && certStatus.valid) {
102
- output.success('Certificate is valid');
103
- }
104
- // Step 3: Sign if needed
105
- if (needsSign) {
106
- const spinner = output.spinner('Signing certificate...').start();
107
- try {
108
- await signCertificate(pubKeyPath, certPath, principalsOverride, options.ttl, options.tenant);
109
- spinner.succeed('Certificate signed');
110
- // Show certificate info
111
- if (options.verbose) {
112
- const { execSync } = await import('child_process');
113
- try {
114
- const certInfo = execSync(`ssh-keygen -L -f "${certPath}"`, { encoding: 'utf8' });
115
- const principalsMatch = certInfo.match(/Principals:\s*([\s\S]*?)(?=\s+Critical Options:)/);
116
- const validMatch = certInfo.match(/Valid:\s+from\s+(\S+)\s+to\s+(\S+)/);
117
- if (principalsMatch) {
118
- const principals = principalsMatch[1].trim().split('\n').map(p => p.trim()).filter(Boolean);
119
- output.info(`Principals: ${principals.join(', ')}`);
120
- }
121
- if (validMatch) {
122
- output.info(`Valid until: ${validMatch[2]}`);
123
- }
124
- }
125
- catch {
126
- // Ignore cert inspection errors
127
- }
128
- }
129
- }
130
- catch (err) {
131
- spinner.fail('Failed to sign certificate');
132
- output.error(err instanceof Error ? err.message : String(err));
133
- process.exit(1);
134
- }
135
- }
136
- else if (!options.verbose) {
137
- // In non-verbose mode, just mention we're using existing cert
138
- output.info('Using existing valid certificate');
139
- }
140
- // Step 4: Build SSH command
141
- const sshArgs = [];
142
- // Add identity file (this tells SSH to use our key + cert)
143
- sshArgs.push('-i', keyPath);
144
- // Add port if not default
145
- if (port && port !== '22') {
146
- sshArgs.push('-p', port);
147
- }
148
- // Add TTY allocation flags
149
- if (options.t) {
150
- sshArgs.push('-t');
151
- }
152
- else if (options.T) {
153
- sshArgs.push('-T');
154
- }
155
- // Explicitly tell SSH to use the certificate
156
- sshArgs.push('-o', `CertificateFile=${certPath}`);
157
- // Add destination
158
- if (user) {
159
- sshArgs.push(`${user}@${host}`);
160
- }
161
- else {
162
- sshArgs.push(host);
163
- }
164
- // Add remote command if specified
165
- if (remoteCommand && remoteCommand.length > 0) {
166
- sshArgs.push(...remoteCommand);
167
- }
168
- // Step 5: Execute SSH
169
- if (options.dryRun) {
170
- output.section('Dry Run');
171
- output.keyValue({
172
- 'Key': keyPath,
173
- 'Certificate': certPath,
174
- 'Host': host,
175
- 'User': user ?? '(default)',
176
- 'Port': port,
177
- 'Principals': principalsOverride ?? '(from mapping)',
178
- 'Command': remoteCommand.length > 0 ? remoteCommand.join(' ') : '(interactive shell)',
179
- });
180
- console.log();
181
- output.info(`Would execute: ssh ${sshArgs.join(' ')}`);
182
- return;
183
- }
184
- verbose(`Executing: ssh ${sshArgs.join(' ')}`);
185
- // Only print empty line for interactive sessions
186
- if (remoteCommand.length === 0) {
187
- console.log();
188
- }
189
- // Spawn SSH with stdio inherited (interactive session)
190
- const sshProcess = spawn('ssh', sshArgs, {
191
- stdio: 'inherit',
192
- env: process.env,
193
- });
194
- sshProcess.on('close', (code) => {
195
- process.exit(code ?? 0);
196
- });
197
- sshProcess.on('error', (err) => {
198
- output.error(`Failed to start SSH: ${err.message}`);
199
- process.exit(1);
200
- });
90
+ if (options.verbose)
91
+ output.info('Resolving SSH certificate...');
92
+ base = await ensureSignedSshBase(destination, options);
93
+ if (options.verbose)
94
+ output.success('Certificate ready');
201
95
  }
202
96
  catch (err) {
203
97
  output.error(err instanceof Error ? err.message : String(err));
204
98
  process.exit(1);
99
+ return;
100
+ }
101
+ // Build the interactive ssh args from the shared base
102
+ const sshArgs = [...base.baseSshArgs];
103
+ if (options.t)
104
+ sshArgs.push('-t');
105
+ else if (options.T)
106
+ sshArgs.push('-T');
107
+ sshArgs.push(base.user ? `${base.user}@${base.host}` : base.host);
108
+ if (remoteCommand && remoteCommand.length > 0)
109
+ sshArgs.push(...remoteCommand);
110
+ if (options.dryRun) {
111
+ output.section('Dry Run');
112
+ output.keyValue({
113
+ 'Key': base.keyPath,
114
+ 'Certificate': base.certPath,
115
+ 'Host': base.host,
116
+ 'User': base.user ?? '(default)',
117
+ 'Port': base.port,
118
+ 'Command': remoteCommand.length > 0 ? remoteCommand.join(' ') : '(interactive shell)',
119
+ });
120
+ console.log();
121
+ output.info(`Would execute: ssh ${sshArgs.join(' ')}`);
122
+ return;
205
123
  }
124
+ verbose(`Executing: ssh ${sshArgs.join(' ')}`);
125
+ if (remoteCommand.length === 0)
126
+ console.log();
127
+ const sshProcess = spawn('ssh', sshArgs, { stdio: 'inherit', env: process.env });
128
+ sshProcess.on('close', (code) => process.exit(code ?? 0));
129
+ sshProcess.on('error', (err) => {
130
+ output.error(`Failed to start SSH: ${err.message}`);
131
+ process.exit(1);
132
+ });
206
133
  }
207
134
  export function registerConnectCommand(parent) {
208
135
  parent
@@ -1 +1 @@
1
- {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/commands/ssh/connect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/commands/ssh/connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * SSH local port-forward with vault-CA certificate authentication.
3
+ *
4
+ * `znvault ssh forward -L 127.0.0.1:<lport>:<rhost>:<rport> <destination>`
5
+ * opens `ssh -N -L ...` using an auto-signed vault SSH certificate. The
6
+ * `--print-port` machine mode binds an OS-chosen local port and prints a
7
+ * single JSON line so callers (e.g. the payara deploy plugin) can consume it.
8
+ */
9
+ import type { Command } from 'commander';
10
+ import type { ConnectOptions } from './types.js';
11
+ import type { SignedSshBase } from './connect.js';
12
+ /**
13
+ * Ask the OS for a free TCP port by binding :0 then releasing it.
14
+ * Small TOCTOU window between release and ssh re-binding it — acceptable
15
+ * for a deploy tool (the race would only surface as an ssh bind error, which
16
+ * is reported and the host marked unreachable).
17
+ */
18
+ export declare function pickFreePort(): Promise<number>;
19
+ /** A local-forward specification: bind 127.0.0.1:lport → rhost:rport over the ssh channel. */
20
+ export interface ForwardSpec {
21
+ bindHost: string;
22
+ localPort: number;
23
+ remoteHost: string;
24
+ remotePort: number;
25
+ }
26
+ /**
27
+ * Build the `ssh -N -L ...` argv from a signed base and a forward spec.
28
+ * Uses BatchMode + ConnectTimeout to match the codebase idiom (haproxy.ts).
29
+ */
30
+ export declare function buildForwardArgs(base: SignedSshBase, spec: ForwardSpec, connectTimeoutSeconds: number): string[];
31
+ /** Options accepted by `znvault ssh forward`. Extends ConnectOptions with forward-specific fields. */
32
+ export interface ForwardOptions extends ConnectOptions {
33
+ /** -L spec: "[bindHost:]lport:rhost:rport". lport 0 = OS-assigned. */
34
+ L?: string;
35
+ /** Print one JSON line with the chosen local port and keep running. */
36
+ printPort?: boolean;
37
+ }
38
+ /**
39
+ * Parse a `-L` forward spec. Accepts 4-part (bindHost:lport:rhost:rport) or
40
+ * 3-part (lport:rhost:rport, bindHost defaults to 127.0.0.1).
41
+ */
42
+ export declare function parseForwardOption(spec: string): ForwardSpec;
43
+ /**
44
+ * Run the forward: sign the cert, pick a port if lport==0, spawn `ssh -N -L`,
45
+ * and (in --print-port mode) emit one JSON line to stdout then hold the tunnel.
46
+ */
47
+ export declare function runForward(destination: string, options: ForwardOptions): Promise<void>;
48
+ export declare function registerForwardCommand(parent: Command): void;
49
+ //# sourceMappingURL=forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward.d.ts","sourceRoot":"","sources":["../../../src/commands/ssh/forward.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAc9C;AAED,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,WAAW,EACjB,qBAAqB,EAAE,MAAM,GAC5B,MAAM,EAAE,CAQV;AAED,sGAAsG;AACtG,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,sEAAsE;IACtE,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAmB5D;AAKD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAwEf;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAiB5D"}
@@ -0,0 +1,151 @@
1
+ // Path: src/commands/ssh/forward.ts
2
+ import * as net from 'node:net';
3
+ import * as output from '../../lib/output.js';
4
+ import { ensureSignedSshBase } from './connect.js';
5
+ /**
6
+ * Ask the OS for a free TCP port by binding :0 then releasing it.
7
+ * Small TOCTOU window between release and ssh re-binding it — acceptable
8
+ * for a deploy tool (the race would only surface as an ssh bind error, which
9
+ * is reported and the host marked unreachable).
10
+ */
11
+ export function pickFreePort() {
12
+ return new Promise((resolve, reject) => {
13
+ const srv = net.createServer();
14
+ srv.once('error', reject);
15
+ srv.listen(0, '127.0.0.1', () => {
16
+ const addr = srv.address();
17
+ if (addr && typeof addr === 'object') {
18
+ const port = addr.port;
19
+ srv.close(() => { resolve(port); });
20
+ }
21
+ else {
22
+ srv.close(() => { reject(new Error('Failed to obtain a free port')); });
23
+ }
24
+ });
25
+ });
26
+ }
27
+ /**
28
+ * Build the `ssh -N -L ...` argv from a signed base and a forward spec.
29
+ * Uses BatchMode + ConnectTimeout to match the codebase idiom (haproxy.ts).
30
+ */
31
+ export function buildForwardArgs(base, spec, connectTimeoutSeconds) {
32
+ const args = [...base.baseSshArgs];
33
+ args.push('-o', 'BatchMode=yes');
34
+ args.push('-o', `ConnectTimeout=${connectTimeoutSeconds}`);
35
+ args.push('-N');
36
+ args.push('-L', `${spec.bindHost}:${spec.localPort}:${spec.remoteHost}:${spec.remotePort}`);
37
+ args.push(base.user ? `${base.user}@${base.host}` : base.host);
38
+ return args;
39
+ }
40
+ /**
41
+ * Parse a `-L` forward spec. Accepts 4-part (bindHost:lport:rhost:rport) or
42
+ * 3-part (lport:rhost:rport, bindHost defaults to 127.0.0.1).
43
+ */
44
+ export function parseForwardOption(spec) {
45
+ const parts = spec.split(':');
46
+ if (parts.length === 4) {
47
+ return {
48
+ bindHost: parts[0],
49
+ localPort: Number(parts[1]),
50
+ remoteHost: parts[2],
51
+ remotePort: Number(parts[3]),
52
+ };
53
+ }
54
+ if (parts.length === 3) {
55
+ return {
56
+ bindHost: '127.0.0.1',
57
+ localPort: Number(parts[0]),
58
+ remoteHost: parts[1],
59
+ remotePort: Number(parts[2]),
60
+ };
61
+ }
62
+ throw new Error(`Invalid forward spec "${spec}". Use "[bindHost:]localPort:remoteHost:remotePort".`);
63
+ }
64
+ const DEFAULT_FORWARD_REMOTE_PORT = 9100;
65
+ const FORWARD_CONNECT_TIMEOUT_SECONDS = 10;
66
+ /**
67
+ * Run the forward: sign the cert, pick a port if lport==0, spawn `ssh -N -L`,
68
+ * and (in --print-port mode) emit one JSON line to stdout then hold the tunnel.
69
+ */
70
+ export async function runForward(destination, options) {
71
+ const { spawn } = await import('child_process');
72
+ const spec = options.L
73
+ ? parseForwardOption(options.L)
74
+ : { bindHost: '127.0.0.1', localPort: 0, remoteHost: '127.0.0.1', remotePort: DEFAULT_FORWARD_REMOTE_PORT };
75
+ // Resolve a concrete local port (O1): pick a free one when 0 was requested.
76
+ if (spec.localPort === 0) {
77
+ spec.localPort = await pickFreePort();
78
+ }
79
+ let base;
80
+ try {
81
+ base = await ensureSignedSshBase(destination, options);
82
+ }
83
+ catch (err) {
84
+ output.error(err instanceof Error ? err.message : String(err));
85
+ process.exit(1);
86
+ return;
87
+ }
88
+ const sshArgs = buildForwardArgs(base, spec, FORWARD_CONNECT_TIMEOUT_SECONDS);
89
+ if (options.dryRun) {
90
+ output.section('Dry Run');
91
+ output.keyValue({
92
+ 'Key': base.keyPath,
93
+ 'Certificate': base.certPath,
94
+ 'Forward': `${spec.bindHost}:${spec.localPort} → ${base.host}:${spec.remotePort}`,
95
+ 'User': base.user ?? '(default)',
96
+ });
97
+ console.log();
98
+ output.info(`Would execute: ssh ${sshArgs.join(' ')}`);
99
+ return;
100
+ }
101
+ // All human/log output goes to STDERR so stdout stays a clean machine channel.
102
+ const sshProcess = spawn('ssh', sshArgs, {
103
+ stdio: ['ignore', 'ignore', 'inherit'],
104
+ env: process.env,
105
+ });
106
+ let exited = false;
107
+ sshProcess.on('error', (err) => {
108
+ exited = true;
109
+ process.stderr.write(`Failed to start SSH: ${err.message}\n`);
110
+ process.exit(1);
111
+ });
112
+ sshProcess.on('close', (code) => {
113
+ exited = true;
114
+ process.exit(code ?? 0);
115
+ });
116
+ // Teardown on our own termination so we never orphan the ssh -N child.
117
+ const cleanup = () => { if (!exited && sshProcess.pid)
118
+ sshProcess.kill('SIGTERM'); };
119
+ process.on('SIGINT', () => { cleanup(); process.exit(0); });
120
+ process.on('SIGTERM', () => { cleanup(); process.exit(0); });
121
+ if (options.printPort) {
122
+ // ssh -N has no "ready" signal on stdout; give it a moment to establish,
123
+ // then emit the contract line. forwardUp = ssh started + port bound by us.
124
+ await new Promise((r) => setTimeout(r, 300));
125
+ if (!exited) {
126
+ process.stdout.write(JSON.stringify({ localPort: spec.localPort, pid: sshProcess.pid, forwardUp: true }) + '\n');
127
+ }
128
+ }
129
+ else {
130
+ process.stderr.write(`Forwarding 127.0.0.1:${spec.localPort} → ${base.host}:${spec.remotePort} (Ctrl-C to stop)\n`);
131
+ }
132
+ }
133
+ export function registerForwardCommand(parent) {
134
+ parent
135
+ .command('forward <destination>')
136
+ .description('Open an SSH local port-forward authenticated by the vault SSH CA')
137
+ .option('-L <spec>', 'Forward spec: [bindHost:]localPort:remoteHost:remotePort (localPort 0 = auto)')
138
+ .option('--print-port', 'Print {"localPort","pid","forwardUp"} JSON then hold the tunnel (machine mode)')
139
+ .option('-i, --identity <file>', 'Path to SSH private key')
140
+ .option('-p, --port <port>', 'SSH port', '22')
141
+ .option('--principals <principals>', 'Principals for signing (comma-separated)')
142
+ .option('--ttl <ttl>', 'Certificate TTL (e.g., 8h, 1d)')
143
+ .option('--tenant <id>', 'Tenant ID (superadmin only)')
144
+ .option('--force-sign', 'Force re-signing even if certificate is valid')
145
+ .option('--dry-run', 'Show what would be done without executing SSH')
146
+ .option('-v, --verbose', 'Show verbose output')
147
+ .action(async (destination, options) => {
148
+ await runForward(destination, options);
149
+ });
150
+ }
151
+ //# sourceMappingURL=forward.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward.js","sourceRoot":"","sources":["../../../src/commands/ssh/forward.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ssh/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AAkDtC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,IAAI,CAuDjF;AAGD,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,QAAQ,EACR,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ssh/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AAkDtC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,IAAI,CA8DjF;AAGD,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,QAAQ,EACR,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -5,6 +5,7 @@ import { registerMappingCommands } from './mapping.js';
5
5
  import { registerServerGroupCommands } from './server-group.js';
6
6
  import { registerConfigCommands } from './config.js';
7
7
  import { registerConnectCommand, executeConnect } from './connect.js';
8
+ import { registerForwardCommand } from './forward.js';
8
9
  import { registerBookmarkCommands, resolveBookmark } from './bookmark.js';
9
10
  import { registerSCPCommand } from './scp.js';
10
11
  import { registerHostsCommand } from './hosts.js';
@@ -13,7 +14,7 @@ import { resolveContext, withRegisterContext, } from '../../lib/command-context.
13
14
  // Known subcommands that should NOT be treated as destinations
14
15
  const SSH_SUBCOMMANDS = new Set([
15
16
  'ca', 'cert', 'mapping', 'server-group', 'config',
16
- 'bookmark', 'bm', 'hosts', 'scp', 'connect', 'exec',
17
+ 'bookmark', 'bm', 'hosts', 'scp', 'connect', 'exec', 'forward',
17
18
  'help', '--help', '-h',
18
19
  ]);
19
20
  /**
@@ -55,6 +56,12 @@ export function registerSSHCommands(parent, opts) {
55
56
  const ssh = parent
56
57
  .command('ssh')
57
58
  .description('SSH CA management and quick connect (znvault ssh user@host)')
59
+ // Parse options relative to position: options that appear AFTER a subcommand
60
+ // name (e.g. `ssh connect --dry-run ...`) are handed to the subcommand rather
61
+ // than being swallowed by this parent (which also declares --dry-run/--ttl/-i
62
+ // for the `ssh user@host` shortcut). Without this, Commander attributes those
63
+ // options to the parent and the subcommand's action sees them as undefined.
64
+ .enablePositionalOptions()
58
65
  .argument('[destination]', 'Host to connect to (user@host or bookmark name)')
59
66
  .argument('[command...]', 'Remote command to execute')
60
67
  .option('-i, --identity <file>', 'Path to SSH private key')
@@ -102,6 +109,7 @@ export function registerSSHCommands(parent, opts) {
102
109
  registerHostsCommand(ssh);
103
110
  registerSCPCommand(ssh);
104
111
  registerConnectCommand(ssh);
112
+ registerForwardCommand(ssh);
105
113
  registerExecCommand(ssh);
106
114
  });
107
115
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/ssh/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/ssh/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -49,6 +49,12 @@ const program = new Command();
49
49
  program
50
50
  .name('znvault')
51
51
  .description('ZnVault Administration CLI')
52
+ // Enable positional options on the root program so that options appearing after
53
+ // a subcommand name are parsed relative to position. Commander requires this on
54
+ // ancestor commands for nested positional parsing to reach grandchild commands
55
+ // (e.g. `znvault ssh connect --dry-run`), where the `ssh` parent also declares
56
+ // its own options for the `ssh user@host` shortcut. See src/commands/ssh/index.ts.
57
+ .enablePositionalOptions()
52
58
  .version(getVersion())
53
59
  .option('--url <url>', 'Vault server URL')
54
60
  .option('--insecure', 'Skip TLS certificate verification')
@@ -80,6 +86,13 @@ program
80
86
  if (parentName === 'completion' || cmdPath === 'completion') {
81
87
  return;
82
88
  }
89
+ // Skip profile indicator for `ssh forward --print-port` — its stdout is a
90
+ // machine channel (JSON contract line) consumed by the deploy tunnel manager.
91
+ if (cmdPath === 'forward' &&
92
+ parentName === 'ssh' &&
93
+ actionCommand.opts().printPort === true) {
94
+ return;
95
+ }
83
96
  // Show current profile indicator
84
97
  const config = getConfig();
85
98
  profileIndicator(getActiveProfileName(), config.url);