0
# SSH Operations
1
2
Comprehensive SSH utilities for secure remote operations including session management, command execution, file transfer, and port forwarding. The SSH system is essential for cluster initialization, remote job management, and secure communication with provisioned infrastructure across different cloud platforms and environments.
3
4
## Capabilities
5
6
### SSH Context
7
8
Main entry point for SSH operations providing key management and session creation capabilities.
9
10
```java { .api }
11
/**
12
* Provides SSH keys and session access for remote operations
13
* Main interface for establishing SSH connections and managing credentials
14
*/
15
interface SSHContext {
16
/**
17
* Generate a 2048-bit RSA key pair for the specified user
18
* @param user Username for the key pair
19
* @return Generated SSH key pair
20
* @throws KeyException if key generation fails
21
*/
22
SSHKeyPair generate(String user) throws KeyException;
23
24
/**
25
* Generate an RSA key pair with specified key size
26
* @param user Username for the key pair
27
* @param keySize Key size in bits (e.g., 2048, 4096)
28
* @return Generated SSH key pair
29
* @throws KeyException if key generation fails
30
*/
31
SSHKeyPair generate(String user, int keySize) throws KeyException;
32
33
/**
34
* Set the SSH key pair to use for connections
35
* @param keyPair SSH key pair to use
36
*/
37
void setSSHKeyPair(SSHKeyPair keyPair);
38
39
/**
40
* Get the currently configured SSH key pair
41
* @return SSH key pair if set, empty otherwise
42
*/
43
Optional<SSHKeyPair> getSSHKeyPair();
44
45
/**
46
* Create SSH session to specified host using configured key pair
47
* @param host Target host address
48
* @return SSH session instance
49
* @throws IOException if connection fails
50
*/
51
SSHSession createSSHSession(String host) throws IOException;
52
53
/**
54
* Create SSH session using specific key pair
55
* @param keyPair SSH key pair to use for authentication
56
* @param host Target host address
57
* @return SSH session instance
58
* @throws IOException if connection fails
59
*/
60
SSHSession createSSHSession(SSHKeyPair keyPair, String host) throws IOException;
61
62
/**
63
* Create SSH session with full configuration
64
* @param user Username for connection
65
* @param privateKeySupplier Supplier for private key bytes
66
* @param host Target host address
67
* @param port SSH port number
68
* @param configs Additional SSH configuration properties
69
* @return SSH session instance
70
* @throws IOException if connection fails
71
*/
72
SSHSession createSSHSession(String user,
73
Supplier<byte[]> privateKeySupplier,
74
String host,
75
int port,
76
Map<String, String> configs) throws IOException;
77
}
78
```
79
80
**Usage Example:**
81
82
```java
83
// Generate and configure SSH keys
84
SSHContext sshContext = // ... obtained from context
85
SSHKeyPair keyPair = sshContext.generate("cdap-user", 2048);
86
sshContext.setSSHKeyPair(keyPair);
87
88
// Create SSH session
89
try (SSHSession session = sshContext.createSSHSession("cluster-master.example.com")) {
90
// Use session for remote operations
91
SSHProcess process = session.executeAndWait("echo", "Hello from remote host");
92
System.out.println("Exit code: " + process.exitValue());
93
}
94
```
95
96
### SSH Session
97
98
Interface for managing SSH connections and performing remote operations.
99
100
```java { .api }
101
/**
102
* SSH session for remote commands and file operations
103
* Must be closed to release connection resources
104
*/
105
interface SSHSession extends Closeable {
106
/**
107
* Check if SSH session is still alive
108
* @return true if session is connected
109
*/
110
boolean isAlive();
111
112
/**
113
* Get remote address of this session
114
* @return Socket address of remote host
115
*/
116
InetSocketAddress getAddress();
117
118
/**
119
* Get username used for this session
120
* @return Username string
121
*/
122
String getUsername();
123
124
/**
125
* Execute commands asynchronously
126
* @param commands Command arguments to execute
127
* @return SSH process handle
128
* @throws Exception if execution fails
129
*/
130
SSHProcess execute(String... commands) throws Exception;
131
132
/**
133
* Execute command list asynchronously
134
* @param commands List of command arguments
135
* @return SSH process handle
136
* @throws Exception if execution fails
137
*/
138
SSHProcess execute(List<String> commands) throws Exception;
139
140
/**
141
* Execute commands and wait for completion
142
* @param commands Command arguments to execute
143
* @return SSH process handle (already completed)
144
* @throws Exception if execution fails
145
*/
146
SSHProcess executeAndWait(String... commands) throws Exception;
147
148
/**
149
* Execute command list and wait for completion
150
* @param commands List of command arguments
151
* @return SSH process handle (already completed)
152
* @throws Exception if execution fails
153
*/
154
SSHProcess executeAndWait(List<String> commands) throws Exception;
155
156
/**
157
* Copy local file to remote host
158
* @param localFile Local file path
159
* @param remotePath Remote destination path
160
* @throws Exception if copy fails
161
*/
162
void copy(Path localFile, String remotePath) throws Exception;
163
164
/**
165
* Copy input stream to remote file with full options
166
* @param input Input stream to copy
167
* @param targetFile Remote target file path
168
* @param targetName Remote target file name
169
* @param length Number of bytes to copy
170
* @param permission File permissions (octal)
171
* @param lastModifiedTime Last modified timestamp (optional)
172
* @param lastAccessTime Last access timestamp (optional)
173
* @throws Exception if copy fails
174
*/
175
void copy(InputStream input,
176
String targetFile,
177
String targetName,
178
long length,
179
int permission,
180
Long lastModifiedTime,
181
Long lastAccessTime) throws Exception;
182
183
/**
184
* Create local port forwarding tunnel
185
* @param remoteHost Remote host to forward to
186
* @param remotePort Remote port to forward to
187
* @param localPort Local port to listen on
188
* @param dataConsumer Consumer for forwarded data
189
* @return Port forwarding channel
190
* @throws Exception if forwarding setup fails
191
*/
192
PortForwarding createLocalPortForward(String remoteHost,
193
int remotePort,
194
int localPort,
195
PortForwarding.DataConsumer dataConsumer) throws Exception;
196
197
/**
198
* Create remote port forwarding tunnel
199
* @param remotePort Remote port to listen on
200
* @param localPort Local port to forward to
201
* @return Remote port forwarding handle
202
* @throws Exception if forwarding setup fails
203
*/
204
RemotePortForwarding createRemotePortForward(int remotePort, int localPort) throws Exception;
205
206
/** Close SSH session and release resources */
207
void close() throws IOException;
208
}
209
```
210
211
**Usage Examples:**
212
213
```java
214
// Execute commands
215
try (SSHSession session = sshContext.createSSHSession("worker-1.example.com")) {
216
// Simple command execution
217
SSHProcess process = session.executeAndWait("ls", "-la", "/opt/cdap");
218
219
try (BufferedReader reader = new BufferedReader(
220
new InputStreamReader(process.getInputStream()))) {
221
String line;
222
while ((line = reader.readLine()) != null) {
223
System.out.println(line);
224
}
225
}
226
227
// File copy operations
228
Path localConfig = Paths.get("/local/config/app.properties");
229
session.copy(localConfig, "/opt/cdap/conf/app.properties");
230
231
// Port forwarding for web UI access
232
PortForwarding webTunnel = session.createLocalPortForward(
233
"localhost", 8080, 18080,
234
new PortForwarding.DataConsumer() {
235
@Override
236
public void received(ByteBuffer data) {
237
// Handle received data
238
}
239
240
@Override
241
public void flushed() {
242
// Handle flush events
243
}
244
245
@Override
246
public void finished() {
247
// Handle completion
248
}
249
});
250
}
251
```
252
253
### SSH Process
254
255
Interface representing a remote process launched via SSH.
256
257
```java { .api }
258
/**
259
* Represents a remote process launched via SSH
260
* Provides access to process streams and status
261
*/
262
interface SSHProcess {
263
/**
264
* Get output stream for writing to process stdin
265
* @return Output stream to process
266
*/
267
OutputStream getOutputStream();
268
269
/**
270
* Get input stream for reading process stdout
271
* @return Input stream from process
272
*/
273
InputStream getInputStream();
274
275
/**
276
* Get input stream for reading process stderr
277
* @return Error stream from process
278
*/
279
InputStream getErrorStream();
280
281
/**
282
* Wait for process completion
283
* @return Process exit code
284
* @throws InterruptedException if wait is interrupted
285
*/
286
int waitFor() throws InterruptedException;
287
288
/**
289
* Wait for process completion with timeout
290
* @param timeout Maximum time to wait
291
* @param unit Time unit for timeout
292
* @return true if process completed, false if timeout
293
* @throws InterruptedException if wait is interrupted
294
*/
295
boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException;
296
297
/**
298
* Get process exit code (only valid after process completion)
299
* @return Exit code
300
* @throws IllegalThreadStateException if process not completed
301
*/
302
int exitValue();
303
304
/**
305
* Stop the remote process
306
*/
307
void destroy();
308
}
309
```
310
311
**Usage Example:**
312
313
```java
314
// Interactive process execution
315
SSHProcess process = session.execute("python3", "/opt/scripts/data_processor.py");
316
317
// Send input to process
318
try (PrintWriter writer = new PrintWriter(process.getOutputStream())) {
319
writer.println("process_data /input/data.csv");
320
writer.flush();
321
}
322
323
// Read process output
324
try (BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
325
BufferedReader stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
326
327
// Wait for completion with timeout
328
boolean completed = process.waitFor(30, TimeUnit.MINUTES);
329
330
if (completed) {
331
int exitCode = process.exitValue();
332
System.out.println("Process completed with exit code: " + exitCode);
333
334
// Read any remaining output
335
String line;
336
while ((line = stdout.readLine()) != null) {
337
System.out.println("STDOUT: " + line);
338
}
339
while ((line = stderr.readLine()) != null) {
340
System.out.println("STDERR: " + line);
341
}
342
} else {
343
System.out.println("Process timed out, destroying...");
344
process.destroy();
345
}
346
}
347
```
348
349
### Port Forwarding
350
351
Interface for SSH port forwarding channels with data handling capabilities.
352
353
```java { .api }
354
/**
355
* SSH port forwarding channel for tunneling network traffic
356
* Implements WritableByteChannel for sending data
357
*/
358
interface PortForwarding extends WritableByteChannel, Flushable {
359
/**
360
* Write data to the forwarding channel
361
* @param src Buffer containing data to write
362
* @return Number of bytes written
363
* @throws IOException if write fails
364
*/
365
int write(ByteBuffer src) throws IOException;
366
367
/**
368
* Flush any buffered data
369
* @throws IOException if flush fails
370
*/
371
void flush() throws IOException;
372
373
/**
374
* Check if channel is open
375
* @return true if channel is open
376
*/
377
boolean isOpen();
378
379
/** Close the forwarding channel */
380
void close() throws IOException;
381
382
/**
383
* Abstract consumer for handling forwarded data
384
*/
385
abstract class DataConsumer {
386
/**
387
* Called when data is received through the tunnel
388
* @param data Buffer containing received data
389
*/
390
public abstract void received(ByteBuffer data);
391
392
/**
393
* Called when data has been flushed
394
*/
395
public abstract void flushed();
396
397
/**
398
* Called when forwarding is finished
399
*/
400
public abstract void finished();
401
}
402
}
403
```
404
405
### Remote Port Forwarding
406
407
Interface for managing remote port forwarding tunnels.
408
409
```java { .api }
410
/**
411
* SSH remote port forwarding handle
412
* Must be closed to stop forwarding
413
*/
414
interface RemotePortForwarding extends Closeable {
415
/**
416
* Get the remote port being forwarded
417
* @return Remote port number
418
*/
419
int getRemotePort();
420
421
/** Stop remote port forwarding */
422
void close() throws IOException;
423
}
424
```
425
426
**Port Forwarding Usage Example:**
427
428
```java
429
// Set up database tunnel
430
RemotePortForwarding dbTunnel = session.createRemotePortForward(5432, 15432);
431
432
try {
433
// Now can connect to remote database via localhost:15432
434
String jdbcUrl = "jdbc:postgresql://localhost:15432/cdap_db";
435
Connection conn = DriverManager.getConnection(jdbcUrl, "user", "password");
436
437
// Use database connection...
438
439
} finally {
440
dbTunnel.close(); // Clean up tunnel
441
}
442
```
443
444
### SSH Key Management
445
446
Data classes for managing SSH key pairs and public keys.
447
448
```java { .api }
449
/**
450
* Public-private key pair for SSH authentication
451
*/
452
class SSHKeyPair {
453
/**
454
* Get public key information
455
* @return SSH public key
456
*/
457
SSHPublicKey getPublicKey();
458
459
/**
460
* Get supplier for private key bytes
461
* @return Supplier providing private key data
462
*/
463
Supplier<byte[]> getPrivateKeySupplier();
464
}
465
466
/**
467
* SSH public key information
468
*/
469
class SSHPublicKey {
470
/**
471
* Get username associated with this key
472
* @return Username string
473
*/
474
String getUser();
475
476
/**
477
* Get public key in RFC-4253 format
478
* @return Public key string (e.g., "ssh-rsa AAAAB3Nza...")
479
*/
480
String getKey();
481
}
482
```
483
484
**Key Management Usage Example:**
485
486
```java
487
// Generate new key pair
488
SSHKeyPair keyPair = sshContext.generate("cdap-service", 4096);
489
490
// Extract public key for deployment
491
SSHPublicKey publicKey = keyPair.getPublicKey();
492
String authorizedKeyEntry = publicKey.getKey() + " " + publicKey.getUser() + "@cdap-cluster";
493
494
// Deploy public key to remote hosts (pseudo-code)
495
deployPublicKeyToCluster(authorizedKeyEntry);
496
497
// Use key pair for connections
498
sshContext.setSSHKeyPair(keyPair);
499
try (SSHSession session = sshContext.createSSHSession("cluster-node.example.com")) {
500
// Authenticated session ready for use
501
}
502
```