Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

174 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Maven Central

REMOTE SESSION UTILITIES

Remote Session is a small collection of utility classes for interacting with remote systems via Secure Shell (SSH) protocol. Built around the JSch library from JCraft, available functions include:

  • Secure file transfer
  • Remote interactive shell
  • Remote command execution

Remote Session wraps the capabilities of JSch in a simplified API that handles many of the details related to setting up and managing remote sessions. Originated by Mykhaylo Adamovych, the implementation was copied verbatim from a post on Stack Overflow. JavaDoc has been added for completeness and comprehensibility.

Continuing Development

The last release of the JSch library from the original SourceForge project was published 2018-NOV-26. Continuing development of this project has been taken up by Matthias Wiedemann here, with new releases published at these artifact coordinates:

Maven
<dependency>
  <groupId>com.github.mwiede</groupId>
  <artifactId>jsch</artifactId>
  <version>2.28.5</version>
</dependency>
Gradle
dependencies {
  compile 'com.github.mwiede:jsch:2.28.5'
}

This new incarnation of the JSch project is a drop-in replacement for artifacts published from the original project. However, support for older or deprecated algorithms is disabled by default. Information on compatibility and configuration can be found on the project's README page.

Authentication

Remote Session supports two ways to authenticate to a remote host: embedding credentials in the connection URI, or configuring them through Remote Session settings. The examples elsewhere in this README use the URI form for brevity, but SSH key-based authentication is generally preferable for anything beyond quick, interactive use.

Password Authentication (URI)

Embed the account credentials directly in the connection URI:

    SshUtils.exec("ssh://user:pass@host", "ls -la");
SSH Key Authentication

Omit the password from the URI and let Remote Session locate your SSH private key instead. By default, this is ~/.ssh/id_rsa:

    SshUtils.exec("ssh://user@host", "ls -la");

The user name can still come from the URI as shown above, or be supplied via the ACCOUNT_USERNAME setting instead — in which case the URI need only specify the host:

    // remote.properties: remote.account.username=user
    SshUtils.exec("ssh://host", "ls -la");

To use a private key file other than the default, or one that's encrypted, configure the relevant settings — for example, via remote.properties:

remote.ssh.key.name=/path/to/id_ed25519
remote.ssh.key.pass=key-passphrase

If the corresponding public key doesn't follow the <private-key>.pub naming convention, specify its path explicitly with SSH_PUB_NAME. See Remote Session Settings below for the complete set of authentication- and host-trust-related settings, including USERINFO_CLASS and TRUST_STRATEGY for interactive host-key confirmation.

NOTE: Whichever method is used, a private key is only attempted if getKeyPath() resolves to an existing file — if no key, password, or UserInfo implementation is available, SshUtils raises RemoteCredentialsUnspecifiedException.

Secure File Transfer

Remote Session enables clients to upload and download files via secure file transfer protocol (SFTP).

    SshUtils.sftp("file:/C:/home/file.txt", "ssh://user:pass@host/home");
    SshUtils.sftp("ssh://user:pass@host/home/file.txt", "file:/C:/home");

NOTE: The transferred file retains its original name. If specified, the name component of toUrl will be ignored.
NOTE: As indicated by the examples, source and target URIs must refer to opposing locations: file for local file system and ssh for remote file system.

  • For upload: fromUri = file; toUri = ssh
  • For download: fromUri = ssh; toUri = file

Remote Interactive Shell

Remote Session supports interacting with remote systems via a secure shell channel, in which input and output are streamed between local and remote systems. Each of the three methods provided for secure shell interaction exhibit different operational characteristics.

Unbounded Stream I/O
import com.nordstrom.remote.SshUtils;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import org.apache.commons.io.IOUtils;

...

    public void example() {
        InputStream is = System.in;
        OutputStream os = System.out;
        SshUtils.shell("ssh://user:pass@host", is, os);
        PrintStream ps = new PrintStream(is, true);
        ps.println("ls -la");
        ps.println("exit");
        System.out.println(IOUtils.toString(os, Charset.defaultCharset()));
    }

With unbounded stream I/O, the channel remains open until the input stream is closed or an exit command is submitted.

Submit Specified Command
    String remoteOutput = SshUtils.shell("ssh://user:pass@host/work/dir/path", "ls");

From the client perspective, this is effectively equivalent to exec(String, String). The primary difference is the channel used for communication (shell instead of exec).

Submit Command with Streamed Output
import com.nordstrom.remote.SshUtils;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.commons.io.IOUtils;

...

    public void example() {
        OutputStream os = System.out;
        SshUtils.shell("ssh://user:pass@host", "ls -la", os);
        System.out.println(IOUtils.toString(os, Charset.defaultCharset()));
    }

This is essentially a hybrid of the previous two secure-shell methods, well-suited for long-running commands that you'd like to leave running while you handle other tasks.

Remote Command Execution

Remote Session enables you to submit commands to remote systems atomically. Instead of submitting commands through an input stream, you specify each command as a property of the channel and execute it.

Execute Specified Command
    System.out.println(SshUtils.exec("ssh://user:pass@host/work/dir/path", "ls -t | head -n1"));
Execute Command
import java.net.URI;
import com.nordstrom.remote.SshUtils.SessionHolder;
import com.nordstrom.remote.SshUtils.ChannelType;
import com.jcraft.jsch.ChannelExec;

...

    public void example() {
        String connectUri = "ssh://user:pass@host/work/dir/path";
        String command = "ls -t | head -n1";
        try (SessionHolder<ChannelExec> session = new SessionHolder<>(ChannelType.EXEC, URI.create(connectUri))) {
            String workDir = session.getWorkDir();
            if (workDir != null) command = "cd " + workDir + " && " + command;
            System.out.println(session, command);
        }
    }

JSch Reference Implementation (BatchUtils)

BatchUtils is a reference implementation of a JSch client. It enables you to execute the specified command, optionally executing an initial command to switch to an alternate user first.

    String userName = "user";
    String password = "password";
    String hostName = "host";
    String sudoCmd = "sudo su - admin";
    String batchDir = "/work/dir/path";
    String batchCmd = "./script.ksh parm1 parm2";
    String output = BatchUtils.executeBatch(userName, password, hostName, sudoCmd, batchDir, batchCmd);
    System.out.println(output);

The implementation of BatchUtils demonstrates how to use a couple of important Remote Session classes:

  • SessionHolder - This is a wrapper class for objects that extend the Channel class. The wrapper implements the Closeable interface, and BatchUtils uses a "try-with-resources" block to ensure that the channel is always closed regardless of the outcome of command execution. SessionHolder includes these methods (among others):
    • getChannel - Get the channel to the remote session created for this SessionHolder.
    • getChannelStream - Get a new channel stream object for this session.
    • disconnect - Disconnect channel and session.
    • assertExitStatus - Verifies that the remote task completed normally.
  • ChannelStreams - This class encapsulates input/output operation for the channel attached to this session. It includes these methods:
    • waitForInput - Wait for input to be available.
    • writeln - Write the specified string to the remote host, followed by a carriage return.
    • waitForPrompt - Wait for the specified prompt to be received from the remote host.
    • readChannel - Read the input from the channel.

Remote Session Settings

Remote Session provides a number of important settings that can be configured through system properties or a corresponding properties file (remote.properties). The library provides default values for all settings in the RemoteConfig class.

Setting Property Name Default
ACCOUNT_USERNAME remote.account.username (none)
ACCOUNT_PASSWORD remote.account.password (none)
SSH_KEY_NAME remote.ssh.key.name id_rsa
SSH_PUB_NAME remote.ssh.pub.name (none)
SSH_KEY_PASS remote.ssh.key.pass (none)
USERINFO_CLASS remote.userinfo.class (none)
KNOWN_HOSTS_NAME remote.known.hosts.path known_hosts
TRUST_STRATEGY remote.trust.strategy yes
SESSION_CONNECT_TIMEOUT remote.session.connect.timeout 5000
SSH_PORT_NUMBER remote.ssh.port.number 22
TERMINAL_HEIGHT remote.terminal.height 24
TERMINAL_WIDTH remote.terminal.width 132
TERMINAL_H_RESOLUTION remote.terminal.h.resolution 924
TERMINAL_V_RESOLUTION remote.terminal.v.resolution 216
COMPLETION_CHECK_INTERVAL remote.completion.check.interval 100
DISCONNECT_CHECK_ATTEMPTS remote.disconnect.check.attempts 600
DISCONNECT_CHECK_INTERVAL remote.disconnect.check.interval 100
CHANNEL_CHECK_INTERVAL remote.channel.check.interval 100
CHANNEL_BUFFER_SIZE remote.channel.buffer.size 102400

Setting Details

The ACCOUNT_USERNAME and ACCOUNT_PASSWORD settings specify the credentials used for password-based authentication to the remote host.

The SSH_KEY_NAME setting specifies the path to an SSH private key file for public-key authentication. If the key file is specified by full path, this is used as-is. Otherwise, the key file must be located in the .ssh folder of the active user's HOME directory. If the key file is encrypted, you must provide the decryption passphrase in the SSH_KEY_PASS setting. The corresponding public key is normally derived by appending .pub to the private key path, but an explicit path can be supplied via SSH_PUB_NAME instead.

The USERINFO_CLASS setting specifies the fully-qualified name of a UserInfo implementation used to service interactive prompts from JSch (for example, when the host trust strategy is INTERACTIVE).

The TRUST_STRATEGY setting controls how the identity of the remote host is verified, corresponding directly to the JSch StrictHostKeyChecking configuration:

Strategy JSch value Behavior
STRICT (default) yes The host's public key must exist in the known_hosts file; the connection is rejected if it's missing or doesn't match.
INTERACTIVE ask Unknown hosts are confirmed via a UserInfo implementation (see USERINFO_CLASS); accepted keys are appended to the known_hosts file.
ANONYMOUS no Any host key is trusted blindly; the known_hosts file is ignored. Warning: insecure — use only in trusted, transient, or isolated test environments.

The KNOWN_HOSTS_NAME setting specifies the path to the known_hosts file used for host verification under the STRICT and INTERACTIVE strategies. If specified by full path, this is used as-is; otherwise it's resolved as a sibling of the SSH key file, then as a child of the .ssh folder of the active user's HOME directory. STRICT mode requires a resolvable known_hosts file; INTERACTIVE mode requires that file to be writable.

NOTE: If credentials are specified in the remote host URL, the SSH_KEY_NAME and SSH_KEY_PASS settings are ignored. Also, no attempt is made to locate a known_hosts file for JSch.

The SESSION_CONNECT_TIMEOUT setting is the interval in milliseconds that JSch will wait for socket connection operations to complete. If this value is set to 0, no timeout will be established.

The COMPLETION_CHECK_INTERVAL setting is the interval in milliseconds between END-OF-FILE checks for remote command execution.

The DISCONNECT_CHECK_INTERVAL setting is the interval in milliseconds between checks for the closure of the remote session channel.

The CHANNEL_CHECK_INTERVAL setting is the interval in milliseconds between checks for available input from the remote session channel.

The CHANNEL_BUFFER_SIZE setting is the size in bytes of the buffer used for channel I/O.

About

Remote Session is a small collection of utility classes for interacting with remote systems via Secure Shell (SSH) protocol.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages