0
# SSH Agents
1
2
Comprehensive SSH agent integration supporting OpenSSH, Windows Pageant, and Cygwin agents for secure key management and authentication.
3
4
## Capabilities
5
6
### BaseAgent Class
7
8
Abstract base class defining the SSH agent interface.
9
10
```javascript { .api }
11
/**
12
* Abstract base class for SSH agents
13
* Provides standard interface for key management and signing operations
14
*/
15
class BaseAgent {
16
/**
17
* Get list of identities (keys) available in the agent
18
* @param callback - Callback receiving array of available keys
19
*/
20
getIdentities(callback: IdentitiesCallback): void;
21
22
/**
23
* Sign data using a key from the agent
24
* @param pubKey - Public key to use for signing
25
* @param data - Data to sign
26
* @param options - Optional signing options
27
* @param callback - Callback receiving signature
28
*/
29
sign(pubKey: ParsedKey, data: Buffer, options?: SignOptions, callback?: SignCallback): void;
30
sign(pubKey: ParsedKey, data: Buffer, callback: SignCallback): void;
31
}
32
33
interface SignOptions {
34
hash?: string;
35
}
36
37
type IdentitiesCallback = (err: Error | null, keys?: ParsedKey[]) => void;
38
type SignCallback = (err: Error | null, signature?: Buffer) => void;
39
```
40
41
### OpenSSHAgent Class
42
43
OpenSSH SSH agent implementation for Unix-like systems.
44
45
```javascript { .api }
46
/**
47
* OpenSSH SSH agent implementation
48
* Connects to SSH agent via Unix domain socket
49
*/
50
class OpenSSHAgent extends BaseAgent {
51
/**
52
* Create OpenSSH agent instance
53
* @param socketPath - Path to SSH agent socket (default: SSH_AUTH_SOCK env var)
54
*/
55
constructor(socketPath?: string);
56
57
/**
58
* Get connection stream to SSH agent
59
* @param callback - Callback receiving agent connection stream
60
*/
61
getStream(callback: StreamCallback): void;
62
}
63
64
type StreamCallback = (err: Error | null, stream?: Duplex) => void;
65
```
66
67
**Usage Examples:**
68
69
```javascript
70
const { OpenSSHAgent } = require('ssh2');
71
72
// Connect to default SSH agent
73
const agent = new OpenSSHAgent();
74
75
// List available keys
76
agent.getIdentities((err, keys) => {
77
if (err) throw err;
78
79
console.log('Available keys:');
80
keys.forEach((key, index) => {
81
console.log(`${index}: ${key.type} ${key.comment || '(no comment)'}`);
82
});
83
84
// Sign data with first key
85
if (keys.length > 0) {
86
const data = Buffer.from('Hello, SSH agent!');
87
agent.sign(keys[0], data, (err, signature) => {
88
if (err) throw err;
89
console.log('Signature:', signature.toString('base64'));
90
});
91
}
92
});
93
94
// Connect to specific agent socket
95
const customAgent = new OpenSSHAgent('/custom/path/to/agent.sock');
96
```
97
98
### PageantAgent Class
99
100
Windows Pageant SSH agent implementation.
101
102
```javascript { .api }
103
/**
104
* Windows Pageant SSH agent implementation
105
* Communicates with Pageant via Windows messaging
106
*/
107
class PageantAgent extends OpenSSHAgent {
108
constructor();
109
}
110
```
111
112
**Usage Example:**
113
114
```javascript
115
// Windows Pageant agent (Windows only)
116
const { PageantAgent } = require('ssh2');
117
118
const agent = new PageantAgent();
119
120
agent.getIdentities((err, keys) => {
121
if (err) {
122
console.error('Pageant not available or no keys loaded');
123
return;
124
}
125
126
console.log(`Found ${keys.length} keys in Pageant`);
127
});
128
```
129
130
### CygwinAgent Class
131
132
Cygwin SSH agent implementation for Cygwin environments.
133
134
```javascript { .api }
135
/**
136
* Cygwin SSH agent implementation
137
* Handles Cygwin-specific agent communication
138
*/
139
class CygwinAgent extends OpenSSHAgent {
140
constructor();
141
}
142
```
143
144
### AgentProtocol Class
145
146
Low-level SSH agent protocol implementation for creating custom agents.
147
148
```javascript { .api }
149
/**
150
* SSH agent protocol implementation
151
* Handles SSH agent wire protocol for client and server modes
152
*/
153
class AgentProtocol extends EventEmitter {
154
/**
155
* Create agent protocol instance
156
* @param isClient - true for client mode, false for server mode
157
*/
158
constructor(isClient: boolean);
159
}
160
```
161
162
#### Client Mode Methods
163
164
```javascript { .api }
165
/**
166
* Request identities from agent (client mode)
167
* @param callback - Callback receiving available keys
168
*/
169
getIdentities(callback: IdentitiesCallback): void;
170
171
/**
172
* Request signature from agent (client mode)
173
* @param pubKey - Public key to use for signing
174
* @param data - Data to sign
175
* @param options - Optional signing options
176
* @param callback - Callback receiving signature
177
*/
178
sign(pubKey: ParsedKey, data: Buffer, options?: SignOptions, callback?: SignCallback): void;
179
sign(pubKey: ParsedKey, data: Buffer, callback: SignCallback): void;
180
```
181
182
#### Server Mode Methods
183
184
```javascript { .api }
185
/**
186
* Send failure response (server mode)
187
* @param reqId - Request ID to respond to
188
*/
189
failureReply(reqId: number): void;
190
191
/**
192
* Send identities response (server mode)
193
* @param reqId - Request ID to respond to
194
* @param keys - Array of available keys
195
*/
196
getIdentitiesReply(reqId: number, keys: ParsedKey[]): void;
197
198
/**
199
* Send signature response (server mode)
200
* @param reqId - Request ID to respond to
201
* @param signature - Signature data
202
*/
203
signReply(reqId: number, signature: Buffer): void;
204
```
205
206
### AgentContext Class
207
208
Helper class for iterating through agent keys during authentication.
209
210
```javascript { .api }
211
/**
212
* Helper for iterating through SSH agent keys
213
* Simplifies multi-key authentication attempts
214
*/
215
class AgentContext {
216
/**
217
* Create agent context wrapper
218
* @param agent - SSH agent instance to wrap
219
*/
220
constructor(agent: BaseAgent);
221
222
/**
223
* Initialize key list from agent
224
* @param callback - Callback with initialization result
225
*/
226
init(callback: InitCallback): void;
227
228
/**
229
* Move to next available key
230
* @returns true if next key available, false if at end
231
*/
232
nextKey(): boolean;
233
234
/**
235
* Get current key
236
* @returns Current key or null if none available
237
*/
238
currentKey(): ParsedKey | null;
239
240
/**
241
* Get current position in key list
242
* @returns Current key index
243
*/
244
pos(): number;
245
246
/**
247
* Reset to first key
248
*/
249
reset(): void;
250
251
/**
252
* Sign data with current key
253
* @param data - Data to sign
254
* @param options - Optional signing options
255
* @param callback - Callback receiving signature
256
*/
257
sign(data: Buffer, options?: SignOptions, callback?: SignCallback): void;
258
sign(data: Buffer, callback: SignCallback): void;
259
}
260
261
type InitCallback = (err: Error | null) => void;
262
```
263
264
**Usage Example:**
265
266
```javascript
267
const { OpenSSHAgent, AgentContext } = require('ssh2');
268
269
const agent = new OpenSSHAgent();
270
const agentCtx = new AgentContext(agent);
271
272
agentCtx.init((err) => {
273
if (err) throw err;
274
275
console.log('Trying agent keys...');
276
277
function tryNextKey() {
278
const key = agentCtx.currentKey();
279
if (!key) {
280
console.log('No more keys to try');
281
return;
282
}
283
284
console.log(`Trying key: ${key.type} ${key.comment || '(no comment)'}`);
285
286
// Simulate authentication attempt
287
const authData = Buffer.from('authentication challenge');
288
agentCtx.sign(authData, (err, signature) => {
289
if (err) {
290
console.log('Key failed, trying next...');
291
if (agentCtx.nextKey()) {
292
tryNextKey();
293
} else {
294
console.log('All keys exhausted');
295
}
296
} else {
297
console.log('Authentication successful!');
298
}
299
});
300
}
301
302
if (agentCtx.currentKey()) {
303
tryNextKey();
304
}
305
});
306
```
307
308
### createAgent Function
309
310
Utility function to create appropriate agent instance based on environment.
311
312
```javascript { .api }
313
/**
314
* Create appropriate SSH agent instance
315
* Auto-detects agent type based on environment and input
316
* @param agent - Agent socket path, existing agent instance, or 'pageant'
317
* @returns Appropriate agent instance
318
*/
319
function createAgent(agent: string | BaseAgent): BaseAgent;
320
```
321
322
**Usage Examples:**
323
324
```javascript
325
const { createAgent } = require('ssh2');
326
327
// Auto-detect from environment
328
const agent1 = createAgent(process.env.SSH_AUTH_SOCK);
329
330
// Use specific socket path
331
const agent2 = createAgent('/tmp/ssh-agent.sock');
332
333
// Use Pageant on Windows
334
const agent3 = createAgent('pageant');
335
336
// Use existing agent instance
337
const existingAgent = new OpenSSHAgent();
338
const agent4 = createAgent(existingAgent);
339
340
// Use in SSH client
341
const conn = new Client();
342
conn.connect({
343
host: 'example.com',
344
username: 'user',
345
agent: createAgent(process.env.SSH_AUTH_SOCK),
346
agentForward: true
347
});
348
```
349
350
## Integration with SSH Client
351
352
Using SSH agents with the SSH client for automatic key-based authentication.
353
354
```javascript { .api }
355
// Client configuration with agent
356
interface ClientConfigWithAgent {
357
agent?: string | BaseAgent;
358
agentForward?: boolean;
359
allowAgentFwd?: boolean;
360
}
361
```
362
363
**Client Integration Examples:**
364
365
```javascript
366
const { Client, OpenSSHAgent } = require('ssh2');
367
368
// Method 1: Use environment variable
369
const conn1 = new Client();
370
conn1.connect({
371
host: 'server.com',
372
username: 'user',
373
agent: process.env.SSH_AUTH_SOCK,
374
agentForward: true // Forward agent to remote server
375
});
376
377
// Method 2: Create agent explicitly
378
const agent = new OpenSSHAgent();
379
const conn2 = new Client();
380
conn2.connect({
381
host: 'server.com',
382
username: 'user',
383
agent: agent,
384
agentForward: true
385
});
386
387
// Method 3: Use specific agent socket
388
const conn3 = new Client();
389
conn3.connect({
390
host: 'server.com',
391
username: 'user',
392
agent: '/custom/agent/socket'
393
});
394
395
// Method 4: Pageant on Windows
396
const conn4 = new Client();
397
conn4.connect({
398
host: 'server.com',
399
username: 'user',
400
agent: 'pageant'
401
});
402
```
403
404
## Agent Events
405
406
SSH agents emit events for connection and operation status.
407
408
```javascript { .api }
409
interface AgentEvents {
410
/**
411
* Emitted when agent connection is established
412
*/
413
'connect': () => void;
414
415
/**
416
* Emitted when agent connection ends
417
*/
418
'end': () => void;
419
420
/**
421
* Emitted when agent connection is closed
422
*/
423
'close': () => void;
424
425
/**
426
* Emitted when agent error occurs
427
*/
428
'error': (err: Error) => void;
429
}
430
```
431
432
## Type Definitions
433
434
### Agent-Related Types
435
436
```javascript { .api }
437
interface ParsedKey {
438
type: string;
439
comment?: string;
440
public: Buffer;
441
private?: Buffer;
442
443
// Key methods
444
getPrivatePEM(): string;
445
getPublicPEM(): string;
446
getPublicSSH(): Buffer;
447
sign(data: Buffer, hashAlgo?: string): Buffer | Error;
448
verify(data: Buffer, signature: Buffer, hashAlgo?: string): boolean | Error;
449
}
450
451
// Agent detection helper
452
function isAgent(obj: any): obj is BaseAgent;
453
```
454
455
## Environment Variables
456
457
SSH agents typically use environment variables for configuration:
458
459
- **SSH_AUTH_SOCK**: Path to SSH agent socket (Unix/Linux/macOS)
460
- **SSH_AGENT_PID**: Process ID of SSH agent (for cleanup)
461
462
```javascript
463
// Check if agent is available
464
if (process.env.SSH_AUTH_SOCK) {
465
console.log('SSH agent available at:', process.env.SSH_AUTH_SOCK);
466
const agent = new OpenSSHAgent(process.env.SSH_AUTH_SOCK);
467
} else {
468
console.log('No SSH agent configured');
469
}
470
```
471
472
## Platform Support
473
474
- **Unix/Linux/macOS**: OpenSSHAgent via Unix domain sockets
475
- **Windows**: PageantAgent via Windows messaging, OpenSSHAgent via named pipes
476
- **Cygwin**: CygwinAgent with Cygwin-specific socket handling
477
478
```javascript
479
// Platform-specific agent selection
480
const { platform } = require('os');
481
482
let agent;
483
switch (platform()) {
484
case 'win32':
485
agent = new PageantAgent();
486
break;
487
case 'linux':
488
case 'darwin':
489
case 'freebsd':
490
agent = new OpenSSHAgent();
491
break;
492
default:
493
agent = createAgent(process.env.SSH_AUTH_SOCK);
494
}
495
```