CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ssh2

SSH2 client and server modules written in pure JavaScript for node.js

Pending
Overview
Eval results
Files

ssh-agents.mddocs/

SSH Agents

Comprehensive SSH agent integration supporting OpenSSH, Windows Pageant, and Cygwin agents for secure key management and authentication.

Capabilities

BaseAgent Class

Abstract base class defining the SSH agent interface.

/**
 * Abstract base class for SSH agents
 * Provides standard interface for key management and signing operations
 */
class BaseAgent {
  /**
   * Get list of identities (keys) available in the agent
   * @param callback - Callback receiving array of available keys
   */
  getIdentities(callback: IdentitiesCallback): void;
  
  /**
   * Sign data using a key from the agent
   * @param pubKey - Public key to use for signing
   * @param data - Data to sign
   * @param options - Optional signing options
   * @param callback - Callback receiving signature
   */
  sign(pubKey: ParsedKey, data: Buffer, options?: SignOptions, callback?: SignCallback): void;
  sign(pubKey: ParsedKey, data: Buffer, callback: SignCallback): void;
}

interface SignOptions {
  hash?: string;
}

type IdentitiesCallback = (err: Error | null, keys?: ParsedKey[]) => void;
type SignCallback = (err: Error | null, signature?: Buffer) => void;

OpenSSHAgent Class

OpenSSH SSH agent implementation for Unix-like systems.

/**
 * OpenSSH SSH agent implementation
 * Connects to SSH agent via Unix domain socket
 */
class OpenSSHAgent extends BaseAgent {
  /**
   * Create OpenSSH agent instance
   * @param socketPath - Path to SSH agent socket (default: SSH_AUTH_SOCK env var)
   */
  constructor(socketPath?: string);
  
  /**
   * Get connection stream to SSH agent
   * @param callback - Callback receiving agent connection stream
   */
  getStream(callback: StreamCallback): void;
}

type StreamCallback = (err: Error | null, stream?: Duplex) => void;

Usage Examples:

const { OpenSSHAgent } = require('ssh2');

// Connect to default SSH agent
const agent = new OpenSSHAgent();

// List available keys
agent.getIdentities((err, keys) => {
  if (err) throw err;
  
  console.log('Available keys:');
  keys.forEach((key, index) => {
    console.log(`${index}: ${key.type} ${key.comment || '(no comment)'}`);
  });
  
  // Sign data with first key
  if (keys.length > 0) {
    const data = Buffer.from('Hello, SSH agent!');
    agent.sign(keys[0], data, (err, signature) => {
      if (err) throw err;
      console.log('Signature:', signature.toString('base64'));
    });
  }
});

// Connect to specific agent socket
const customAgent = new OpenSSHAgent('/custom/path/to/agent.sock');

PageantAgent Class

Windows Pageant SSH agent implementation.

/**
 * Windows Pageant SSH agent implementation
 * Communicates with Pageant via Windows messaging
 */
class PageantAgent extends OpenSSHAgent {
  constructor();
}

Usage Example:

// Windows Pageant agent (Windows only)
const { PageantAgent } = require('ssh2');

const agent = new PageantAgent();

agent.getIdentities((err, keys) => {
  if (err) {
    console.error('Pageant not available or no keys loaded');
    return;
  }
  
  console.log(`Found ${keys.length} keys in Pageant`);
});

CygwinAgent Class

Cygwin SSH agent implementation for Cygwin environments.

/**
 * Cygwin SSH agent implementation
 * Handles Cygwin-specific agent communication
 */
class CygwinAgent extends OpenSSHAgent {
  constructor();
}

AgentProtocol Class

Low-level SSH agent protocol implementation for creating custom agents.

/**
 * SSH agent protocol implementation
 * Handles SSH agent wire protocol for client and server modes
 */
class AgentProtocol extends EventEmitter {
  /**
   * Create agent protocol instance
   * @param isClient - true for client mode, false for server mode
   */
  constructor(isClient: boolean);
}

Client Mode Methods

/**
 * Request identities from agent (client mode)
 * @param callback - Callback receiving available keys
 */
getIdentities(callback: IdentitiesCallback): void;

/**
 * Request signature from agent (client mode)
 * @param pubKey - Public key to use for signing
 * @param data - Data to sign
 * @param options - Optional signing options
 * @param callback - Callback receiving signature
 */
sign(pubKey: ParsedKey, data: Buffer, options?: SignOptions, callback?: SignCallback): void;
sign(pubKey: ParsedKey, data: Buffer, callback: SignCallback): void;

Server Mode Methods

/**
 * Send failure response (server mode)
 * @param reqId - Request ID to respond to
 */
failureReply(reqId: number): void;

/**
 * Send identities response (server mode)
 * @param reqId - Request ID to respond to
 * @param keys - Array of available keys
 */
getIdentitiesReply(reqId: number, keys: ParsedKey[]): void;

/**
 * Send signature response (server mode)
 * @param reqId - Request ID to respond to
 * @param signature - Signature data
 */
signReply(reqId: number, signature: Buffer): void;

AgentContext Class

Helper class for iterating through agent keys during authentication.

/**
 * Helper for iterating through SSH agent keys
 * Simplifies multi-key authentication attempts
 */
class AgentContext {
  /**
   * Create agent context wrapper
   * @param agent - SSH agent instance to wrap
   */
  constructor(agent: BaseAgent);
  
  /**
   * Initialize key list from agent
   * @param callback - Callback with initialization result
   */
  init(callback: InitCallback): void;
  
  /**
   * Move to next available key
   * @returns true if next key available, false if at end
   */
  nextKey(): boolean;
  
  /**
   * Get current key
   * @returns Current key or null if none available
   */
  currentKey(): ParsedKey | null;
  
  /**
   * Get current position in key list
   * @returns Current key index
   */
  pos(): number;
  
  /**
   * Reset to first key
   */
  reset(): void;
  
  /**
   * Sign data with current key
   * @param data - Data to sign
   * @param options - Optional signing options
   * @param callback - Callback receiving signature
   */
  sign(data: Buffer, options?: SignOptions, callback?: SignCallback): void;
  sign(data: Buffer, callback: SignCallback): void;
}

type InitCallback = (err: Error | null) => void;

Usage Example:

const { OpenSSHAgent, AgentContext } = require('ssh2');

const agent = new OpenSSHAgent();
const agentCtx = new AgentContext(agent);

agentCtx.init((err) => {
  if (err) throw err;
  
  console.log('Trying agent keys...');
  
  function tryNextKey() {
    const key = agentCtx.currentKey();
    if (!key) {
      console.log('No more keys to try');
      return;
    }
    
    console.log(`Trying key: ${key.type} ${key.comment || '(no comment)'}`);
    
    // Simulate authentication attempt
    const authData = Buffer.from('authentication challenge');
    agentCtx.sign(authData, (err, signature) => {
      if (err) {
        console.log('Key failed, trying next...');
        if (agentCtx.nextKey()) {
          tryNextKey();
        } else {
          console.log('All keys exhausted');
        }
      } else {
        console.log('Authentication successful!');
      }
    });
  }
  
  if (agentCtx.currentKey()) {
    tryNextKey();
  }
});

createAgent Function

Utility function to create appropriate agent instance based on environment.

/**
 * Create appropriate SSH agent instance
 * Auto-detects agent type based on environment and input
 * @param agent - Agent socket path, existing agent instance, or 'pageant'
 * @returns Appropriate agent instance
 */
function createAgent(agent: string | BaseAgent): BaseAgent;

Usage Examples:

const { createAgent } = require('ssh2');

// Auto-detect from environment
const agent1 = createAgent(process.env.SSH_AUTH_SOCK);

// Use specific socket path
const agent2 = createAgent('/tmp/ssh-agent.sock');

// Use Pageant on Windows
const agent3 = createAgent('pageant');

// Use existing agent instance
const existingAgent = new OpenSSHAgent();
const agent4 = createAgent(existingAgent);

// Use in SSH client
const conn = new Client();
conn.connect({
  host: 'example.com',
  username: 'user',
  agent: createAgent(process.env.SSH_AUTH_SOCK),
  agentForward: true
});

Integration with SSH Client

Using SSH agents with the SSH client for automatic key-based authentication.

// Client configuration with agent
interface ClientConfigWithAgent {
  agent?: string | BaseAgent;
  agentForward?: boolean;
  allowAgentFwd?: boolean;
}

Client Integration Examples:

const { Client, OpenSSHAgent } = require('ssh2');

// Method 1: Use environment variable
const conn1 = new Client();
conn1.connect({
  host: 'server.com',
  username: 'user',
  agent: process.env.SSH_AUTH_SOCK,
  agentForward: true  // Forward agent to remote server
});

// Method 2: Create agent explicitly  
const agent = new OpenSSHAgent();
const conn2 = new Client();
conn2.connect({
  host: 'server.com',
  username: 'user',
  agent: agent,
  agentForward: true
});

// Method 3: Use specific agent socket
const conn3 = new Client();
conn3.connect({
  host: 'server.com',
  username: 'user',
  agent: '/custom/agent/socket'
});

// Method 4: Pageant on Windows
const conn4 = new Client();
conn4.connect({
  host: 'server.com', 
  username: 'user',
  agent: 'pageant'
});

Agent Events

SSH agents emit events for connection and operation status.

interface AgentEvents {
  /**
   * Emitted when agent connection is established
   */
  'connect': () => void;
  
  /**
   * Emitted when agent connection ends
   */
  'end': () => void;
  
  /**
   * Emitted when agent connection is closed
   */
  'close': () => void;
  
  /**
   * Emitted when agent error occurs
   */
  'error': (err: Error) => void;
}

Type Definitions

Agent-Related Types

interface ParsedKey {
  type: string;
  comment?: string;
  public: Buffer;
  private?: Buffer;
  
  // Key methods
  getPrivatePEM(): string;
  getPublicPEM(): string;
  getPublicSSH(): Buffer;
  sign(data: Buffer, hashAlgo?: string): Buffer | Error;
  verify(data: Buffer, signature: Buffer, hashAlgo?: string): boolean | Error;
}

// Agent detection helper
function isAgent(obj: any): obj is BaseAgent;

Environment Variables

SSH agents typically use environment variables for configuration:

  • SSH_AUTH_SOCK: Path to SSH agent socket (Unix/Linux/macOS)
  • SSH_AGENT_PID: Process ID of SSH agent (for cleanup)
// Check if agent is available
if (process.env.SSH_AUTH_SOCK) {
  console.log('SSH agent available at:', process.env.SSH_AUTH_SOCK);
  const agent = new OpenSSHAgent(process.env.SSH_AUTH_SOCK);
} else {
  console.log('No SSH agent configured');
}

Platform Support

  • Unix/Linux/macOS: OpenSSHAgent via Unix domain sockets
  • Windows: PageantAgent via Windows messaging, OpenSSHAgent via named pipes
  • Cygwin: CygwinAgent with Cygwin-specific socket handling
// Platform-specific agent selection
const { platform } = require('os');

let agent;
switch (platform()) {
  case 'win32':
    agent = new PageantAgent();
    break;
  case 'linux':
  case 'darwin':
  case 'freebsd':
    agent = new OpenSSHAgent();
    break;  
  default:
    agent = createAgent(process.env.SSH_AUTH_SOCK);
}

Install with Tessl CLI

npx tessl i tessl/npm-ssh2

docs

http-tunneling.md

index.md

key-management.md

port-forwarding.md

sftp-operations.md

ssh-agents.md

ssh-client.md

ssh-server.md

tile.json