Skip to content

Latest commit

 

History

History
869 lines (708 loc) · 49.1 KB

File metadata and controls

869 lines (708 loc) · 49.1 KB

Changelog

All notable changes to bssh will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

[2.1.5] - Unreleased

Fixed

  • --password prompt is now collected once up-front and shared across all parallel connection tasks (#201, closes #200). Previously each per-node SSH task prompted for the password independently, racing each other for stdin and interleaving with the progress UI. The dispatcher now collects the password before any executor or indicatif UI is initialized and threads an Arc<Password> to every per-node auth task — matching the existing -S (SudoPassword) pattern. The BSSH_PASSWORD environment variable is supported for automation scenarios (discouraged; see security notes below).
  • -S / --sudo-password warning now routes to stderr when passed to subcommands where it has no effect (ping, upload, download, list, cache-stats, and interactive shells), keeping stdout clean for scripts that consume bssh output (#201, follow-up to #200).

2.1.4 - 2026-05-10

Performance

  • Stream SFTP uploads/downloads instead of buffering whole files in memory (#195). Previously upload_file/upload_dir_recursive loaded the entire local file into a Vec<u8> via tokio::fs::read before calling write_all, and download_file/download_dir_recursive called read_to_end into a pooled buffer plus a clone() to a separate Vec before writing locally. Multi-GB transfers therefore had peak RSS that scaled with file size and large files OOM'd the client. Each path now uses a small stream_copy() helper looping on 255 KiB reads/writes through the existing AsyncRead/AsyncWrite impls on tokio::fs::File and russh_sftp::client::fs::File. Buffer size matches the SFTP MAX_WRITE_LENGTH so each chunk maps to a single SFTP packet without further fragmentation. Verified locally on macOS arm64 against bssh-server v2.1.3 over loopback with a 1 GiB file: upload peak RSS drops from ~3.23 GB to ~20 MB and wall time from 38.6 s to 3.5 s; download peak RSS drops from ~2.17 GB to ~16 MB and wall time from 3.93 s to 3.41 s.
  • Pipeline up to 64 concurrent SFTP requests for upload and download (#196). Bounded pipelined SFTP upload/download helpers replace the previous strictly-sequential request/response loop. Review follow-ups also: cap server-advertised read/write lengths against local maxima to avoid oversized allocations from untrusted SFTP metadata, bound the download reorder queue across both in-flight and pending out-of-order responses, use fstat size information where available to avoid reads past EOF and validate unexpected short reads, and preserve remote download handle shutdown after syncing with main. Added SFTP crate tests for chunk-size capping and in-memory pipelined upload/download behavior.
  • Raise bssh-server SFTP MAX_READ_SIZE to the 255 KiB SFTP standard (#197). The server previously hard-capped every SFTP READ reply at 64 KiB regardless of what the client requested, while bssh-russh-sftp and OpenSSH's sftp-server both use the SFTP standard MAX_READ_LENGTH = 261120 (255 KiB) for request sizing. A client asking for a 256 KiB chunk only ever got 64 KiB back, forcing four extra requests per byte stream. Bumped to 261120 so server replies match the chunk size used by the rest of the stack. Combined with client-side pipelining (#196), this directly cuts the per-MiB request count on downloads from 16 to 4. Memory exposure stays bounded: handles are still capped at MAX_HANDLES = 1000 per session and each in-flight read still uses a single per-request buffer of this size.

2.1.3 - 2026-04-30

Added

  • Internal fork of russh-sftp as crates/bssh-russh-sftp with a serde_bytes performance fix for SSH_FXP_WRITE and SSH_FXP_DATA packets. The upstream serde derive routes Vec<u8> through deserialize_seq (byte-by-byte), accounting for ~42% of server CPU during 1 GiB SFTP uploads in perf profiling. Annotating the data fields with #[serde(with = "serde_bytes")] and implementing wire-compatible serialize_bytes on the SFTP Serializer routes through the existing bulk deserialize_byte_buf/try_get_bytes path. Measured impact on a CPU-bound host (Xeon Silver 4214): 1 GiB SFTP upload throughput improves from 74.8 MiB/s to 96.4 MiB/s (+29%), closing the gap to OpenSSH sftp-server from ~26% to ~5%. (#188)
  • scp.root configuration field. SCP transfers now honor a chroot setting separate from SFTP. When unset, SCP falls back to sftp.root, so a single top-level chroot setting governs both subsystems unless an admin explicitly wants them split. (#186)

Changed

  • Switched the top-level russh-sftp dependency from crates.io russh-sftp = "2.1.1" to russh-sftp = { package = "bssh-russh-sftp", version = "2.1.1", path = "crates/bssh-russh-sftp" }. All existing use russh_sftp::... imports continue to work unchanged. (#188)
  • Default file-transfer behavior is no longer chrooted to the user's home directory. With sftp.root/scp.root unset (the default), absolute client paths are honored verbatim and relative paths resolve from the user's home directory, matching OpenSSH sftp-server/scp defaults. Deployments that intentionally want chroot-at-home-dir must now set sftp.root: <home dir> (or equivalent) explicitly. (#186)
  • Forward-ported unreleased upstream russh fixes (#193): exclude SHA-1 MACs from Preferred::DEFAULT/COMPRESSED (upstream russh #690) and fix channel write ordering when pending_data is non-empty (upstream russh #693). Refactored sync-upstream.sh to iterate patches/ and reverse-apply --dry-run first so already-merged patches are auto-skipped.
  • Bumped dependencies: tokio 1.52.1, clap 4.6.1, tracing 0.1.44, lru 0.17, uuid 1.23.1, tokio-util 0.7.18, aws-lc-rs 1.16.3, ecdsa rc.17, elliptic-curve rc.31, p256/p384/p521 rc.9. Pinned pkcs5="=0.8.0-rc.13" because pkcs8 0.11.0-rc.11 still calls the rc.13-era Parameters::recommended API. (#193)

Fixed

  • bssh-server SCP/SFTP path doubling on absolute client paths (#186). ScpHandler::resolve_path and SftpHandler::resolve_path_static previously re-rooted every absolute client path under the user's home directory, so scp local user@host:/home/work/file.bin wrote to /home/work/home/work/file.bin and bssh upload local /abs/remote.bin failed with No such file. The resolver now treats absolute client paths verbatim when no chroot is configured and rejects out-of-chroot absolute paths with permission_denied when one is. Path-traversal and symlink-escape protections continue to apply.
  • SCP single-file destinations no longer have the source filename appended (#186). ScpHandler::receive_file now consults target_is_directory (parsed from -d/-r) and the filesystem state of the resolved target. scp local.bin user@host:/tmp/dest.bin now writes to /tmp/dest.bin instead of /tmp/dest.bin/local.bin. Directory destinations (/tmp/dir/, existing directory, or -d/-r flag) keep the previous filename-appending behavior.
  • Configured sftp.root is no longer dead code (#186). The handler-construction sites in SshHandler previously hard-coded user_info.home_dir as the chroot root and ignored config.sftp.root entirely. Setting sftp.root in the YAML configuration now actually changes the SFTP chroot. The same plumbing now exists for scp.root.
  • Chroot bypass via intermediate-directory symlink. The chroot resolver previously checked only lexical containment for paths whose final component did not exist (typical for new-file creates and mkdir). A symlink inside the chroot pointing to a directory outside the chroot would let a client target chroot/escape/newfile and have open(...)/create_dir(...) follow the symlink, writing outside the chroot. Both ScpHandler::resolve_path and SftpHandler::resolve_path_static now canonicalize the closest existing ancestor of the target path and verify it stays inside the canonicalized chroot, blocking the parent-symlink escape. Found during PR #194 review.

Documentation

  • Standardize man page trailers across bssh.1, bssh-keygen.1, and bssh-server.8 into a consistent BUGS / AUTHORS / COPYRIGHT / SEE ALSO order matching common Unix manual conventions. Author attribution, contact email, Apache-2.0 license notice, and project homepage link are now uniform across all three pages. (#192)
  • Document sftp.root and scp.root in bssh-server.8 configuration sections, and add intermediate-directory-symlink chroot protection to SECURITY CONSIDERATIONS.

CI/CD

  • Bump GitHub Actions to Node.js 24-compatible versions to address Node.js 20 deprecation warnings: actions/checkout v4 -> v6, actions/cache v4 -> v5, actions/upload-artifact v4 -> v7, apple-actions/import-codesign-certs v3 -> v7. (#191)

2.1.2 - 2026-04-27

Fixed

  • PTY session mouse tracking leak: after a PTY session disconnects (normal exit, Ctrl+C, network drop, or panic), the local terminal no longer prints raw SGR mouse escape sequences when the mouse is moved. All cleanup paths (TerminalStateGuard::Drop, force_terminal_cleanup, and the panic hook via TerminalGuard) now emit the full set of mouse-tracking-off sequences (modes 1000, 1002, 1003, 1006, 1015) plus cursor-show and alternate-screen-exit on teardown. (#189, #190)
  • Panic-hook safety in terminal cleanup: force_terminal_cleanup() now uses try_lock() instead of lock() so the panic hook path (TerminalGuard::restore_terminalforce_terminal_cleanup) cannot deadlock if the panicking thread already holds TERMINAL_MUTEX, and a previously poisoned mutex no longer triggers a secondary panic. The lock only serializes concurrent teardown; the underlying stdout writes and disable_raw_mode are individually safe. (#190)

Changed

  • Centralized terminal teardown logic: TerminalGuard::restore_terminal() in interactive_signal.rs now delegates to force_terminal_cleanup() instead of carrying its own incomplete cleanup, closing the gap on the panic-hook path.

Tests

  • Added unit tests for force_terminal_cleanup() covering idempotency, poisoned-mutex resilience, and held-mutex resilience (using local Mutex instances rather than the global TERMINAL_MUTEX to keep the global state undisturbed).

CI/CD

  • Trigger the Homebrew formula update workflow only after the official release: release.yml now calls update_homebrew_formula.yml via workflow_call from the publish-release job (which converts pre-release to official), instead of workflow_run firing on every Release workflow completion (including pre-release builds).
  • Prevent the release workflow from being triggered twice: removed the published event type from the trigger list since publish-release already handles the pre-release → official conversion. workflow_dispatch continues to cover manual runs.

2.1.1 - 2026-04-17

Fixed

  • bssh-server panic on client connection: new_client_with_addr called block_on() inside the tokio async runtime to check the auth rate limiter ban list, causing an immediate "Cannot start a runtime from within a runtime" panic on every incoming connection. Added non-blocking AuthRateLimiter::try_is_banned() using RwLock::try_read(). (#185)
  • bssh-server auth rejection after successful verification: All SshHandler constructors created a local SessionInfo that was never registered with SessionManager. After public key or password verification succeeded, authenticate_session() returned SessionNotFound, rejecting the client. Fixed by deferring session creation to the authentication flow via SessionManager::create_session(). (#185)

Changed

  • Improved Launchpad PPA packaging for Rust 2024 edition: updated debian/rules variants, added debian/sanitize-vendor.py for vendored crate checksum sanitization, fixed hidden path handling
  • Added .pyc files to .gitignore

2.1.0 - 2026-04-14

Added

  • EnvGuard RAII wrapper (src/test_helpers/env_guard.rs) for safe environment variable handling in tests, with Drop-based restore semantics and soundness contract documentation (#179, #181)
  • Test Environment-Variable Mutation Pattern section in ARCHITECTURE.md documenting the EnvGuard soundness contract and #[serial] usage

Changed

  • Migrated bssh and the bundled bssh-russh crate to the Rust 2024 edition
  • Applied 2024 edition clippy improvements: collapsed 38 nested if let statements into guard-clause form (if let Some(x) = y && condition) across bssh-russh client/server/keys/kex modules
  • Replaced 177 ad-hoc unsafe { env::set_var/remove_var } call sites across 17 test-bearing files with EnvGuard::set / EnvGuard::remove plus #[serial] from the serial_test crate
  • Removed hand-rolled ENV_MUTEX / once_cell::sync::Lazy<Mutex<()>> pattern in integration tests in favor of #[serial]
  • Pinned bytes dependency to v1.11.1

Fixed

  • Fixed pattern matching for Rust 2024 edition: removed explicit ref / ref mut bindings in if let patterns in src/server/handler.rs and src/server/shell.rs

2.0.1 - 2026-04-13

Added

  • bssh-keygen now included in Debian package build pipeline for all architectures

Changed

  • Bumped bssh-russh from 0.60.0 to 0.60.1 with security updates

Fixed

  • Fixed GitHub Actions debian_build.yml distro configuration (questing -> resolute)
  • Fixed debian_build.yml matrix validation issue causing workflow failures

Security

  • Updated rsa to 0.10.0-rc.17 (fixes RUSTSEC-2023-0071 RSA Marvin Attack)
  • Updated RC dependencies to latest versions: elliptic-curve 0.14.0-rc.30, p256/p384/p521 0.14.0-rc.8, ml-kem 0.3.0-rc.2, spki 0.8.0 (stable)

2.0.0 - 2026-04-13

Added

  • bssh-server SSH Server - A lightweight SSH server designed for container environments

    • Full SSH, SFTP, and SCP protocol support
    • PTY/shell session support with terminal handling
    • Password and public key authentication
    • YAML-based comprehensive configuration system
    • Command execution handler with security controls
  • Audit Logging Infrastructure

    • File-based audit exporter (JSON Lines format)
    • OpenTelemetry audit exporter for observability platforms
    • Logstash audit exporter for ELK stack integration
    • Configurable audit event types and logging levels
  • Security Features

    • IP-based access control (allow/deny lists)
    • Authentication rate limiting (fail2ban-like protection)
    • Session management and connection limits
    • Path traversal prevention in SFTP handler
  • File Transfer Filtering

    • Path-based filter rules for upload/download control
    • Pattern-based filtering with glob support
    • Configurable filter actions (allow/deny)
  • bssh-keygen Tool

    • SSH key pair generation utility
    • Support for RSA, Ed25519, and ECDSA key types
    • Configurable key sizes and comments
  • Server Configuration

    • Per-jump-host SSH private key configuration
    • SSH config Host alias reference in jump_host configuration
    • SSH keepalive settings in interactive mode
  • Separate Packaging

    • bssh and bssh-server now distributed as separate packages
    • Independent Debian packages for client and server
    • Separate Homebrew formulas for each component

Changed

  • Documentation: Added comprehensive server configuration manual and manpages
  • CI/CD: Updated release workflow for dual-package distribution; Teams release notification added
  • Dependencies: Synced bssh-russh fork with upstream warp-tech/russh v0.60.0, which brings the RustCrypto chain migration — rand 0.9 → 0.10 stable, signature 3.0.0-rc.10, ed25519-dalek 3.0.0-pre.6, elliptic-curve 0.14.0-rc.28, p256/p384/p521 0.14.0-rc.7, ecdsa 0.17.0-rc.16, curve25519-dalek 5.0.0-pre.6, der 0.8, sec1 0.8, pkcs8 0.11.0-rc.11, pkcs5 0.8.0-rc.13, spki 0.8.0-rc.4, ml-kem 0.3.0-rc.1, ssh-key 0.6.18, tokio 1.51.1, socket2 0.6.3, signal-hook 0.4.4, fastrand 2.4.1
  • Cluster flag help: Help examples and man pages now correctly show -C (uppercase) for the cluster flag; running the previous -c examples failed with clap's "unexpected argument" error

Fixed

  • SSH idle disconnects: Interactive sessions could disconnect inconsistently after idle time — sometimes within minutes, sometimes ~10 minutes
    • russh::Config::inactivity_timeout (10-minute client-side ceiling) is now explicitly set to None when keepalive is enabled so the keepalive mechanism alone decides peer liveness
    • TCP-level SO_KEEPALIVE (via socket2::TcpKeepalive) is now applied to every SSH socket so the kernel can detect broken paths even when SSH keepalive replies are dropped by middleboxes
    • The exec-mode code path previously dropped the user-configured SshConnectionConfig at the ConnectionConfig boundary; it now flows through connect_direct / connect_via_jump_hosts / the jump chain, so server_alive_interval actually takes effect in non-interactive runs
  • bssh-server: Use consistent source package name in Debian control file so dual-package builds resolve correctly
  • bssh-server: Use type inference for ioctl to support both glibc and musl builds

Technical Details

  • Shared module structure for client/server code reuse
  • russh-based SSH server handler implementation
  • Modular audit exporter architecture with trait-based design
  • SshConnectionConfig::to_russh_config() now overrides inactivity_timeout based on keepalive state; to_tcp_keepalive() derives a kernel TCP keepalive config from the same settings
  • Client::connect_with_config rewritten around russh::client::connect_stream, building the TcpStream manually so SO_KEEPALIVE can be applied before the SSH handshake
  • Dropped the ssh_key::rand_core::OsRng workaround in key-generation sites; now pass &mut rand::rng() (rand 0.10's thread RNG implements the new rand_core 0.10 CryptoRng trait directly)

1.7.0 - 2026-01-09

Added

  • SSH Keepalive Support (Issue #122)
    • --server-alive-interval option: Configure keepalive interval in seconds (default: 60, 0 to disable)
    • --server-alive-count-max option: Maximum keepalive messages without response before disconnect (default: 3)
    • Configuration support in config.yaml via server_alive_interval and server_alive_count_max fields
    • Helps maintain long-running sessions through firewalls and NATs that drop idle connections
    • Full integration with exec, interactive, and file transfer modes

Changed

  • Documentation: Added GitHub downloads badge to README

Dependencies

  • Updated russh from 0.55.0 to 0.56.0
  • Updated ratatui from 0.29.0 to 0.30.0
  • Updated signal-hook from 0.3.18 to 0.4.1
  • Updated whoami from 1.6.1 to 2.0.1
  • Updated unicode-width from 0.2.0 to 0.2.2

Technical Details

  • Implemented SSH keepalive packet sending at configurable intervals
  • Automatic connection termination after max retries without response
  • Keepalive settings work with jump host connections
  • Adapted to whoami 2.0 API changes (username() now returns Result)

1.6.0 - 2025-12-19

Added

  • Jump Host Configuration Support in YAML (Issue #115, PR #120)
    • Global defaults level: defaults.jump_host for all clusters
    • Cluster level: clusters.<name>.jump_host for cluster-specific settings
    • Node level: Per-node jump_host in detailed node configuration
    • Environment variable expansion supported (${VAR} or $VAR syntax)
    • Empty string ("") explicitly disables jump host inheritance
    • CLI -J option always takes precedence over configuration

Changed

  • SSH Config ProxyJump Directive (Issue #117, PR #119)
    • ProxyJump directive from SSH config now properly applied when -J option not specified
    • Priority order: CLI -J > config.yaml jump_host > SSH config ProxyJump
  • Documentation Improvements
    • Added comprehensive jump_host configuration documentation to README.md
    • Updated docs/architecture/ssh-jump-hosts.md with detailed architecture
    • Updated example-config.yaml with all jump_host configuration patterns
  • CI/CD
    • Updated GitHub workflows

Fixed

  • Jump Host Authentication (Issue #116, PR #118)
    • Properly handle empty SSH agent when authenticating through jump hosts
    • Fall back to key-based authentication when agent has no identities
  • Config Fallback (PR #120)
    • Environment variables now properly expanded in jump_host values via expand_env_vars
    • Configuration jump_host properly used in exec and interactive modes

Technical Details

  • Added ConfigResolver::resolve_jump_host() method for centralized jump host resolution
  • Jump host priority: CLI > Node > Cluster > Global defaults
  • Comprehensive test coverage: 424 lines of tests for jump_host configuration
  • Integration tests for all priority levels and edge cases

1.5.1 - 2025-12-18

Fixed

  • SSH Disconnect Error Handling (Issue #113, PR #114)
    • Handle SshError(Disconnect) during authentication for password fallback
    • Fixed handling of SSH disconnect errors during authentication phase
    • Enables proper password fallback when SSH connection is disconnected during auth

1.5.0 - 2025-12-18

Added

  • pdsh Compatibility Mode (Issues #100-103, #105, #107, #110)

    • Full pdsh-style command line compatibility when invoked as pdsh or with --pdsh-compat
    • -w hosts option mapped to -H hosts for target host specification
    • -x hosts option mapped to --exclude hosts for host exclusion
    • -f N option mapped to --parallel N for fanout control
    • -l user option for remote username
    • -t N option mapped to --connect-timeout N for connection timeout
    • -u N option mapped to --timeout N for command timeout
    • -N option mapped to --no-prefix for disabling hostname prefix in output
    • -b option mapped to --batch for single Ctrl+C termination
    • -k option mapped to --fail-fast for stop on first failure
    • -q query mode to show target hosts and exit
    • -S option mapped to --any-failure for returning largest exit code
  • Hostlist Expressions (Issue #107)

    • pdsh-style range expansion: node[1-5] → node1, node2, node3, node4, node5
    • Zero-padded ranges: node[01-05] → node01, node02, node03, node04, node05
    • Comma-separated values: node[1,3,5] → node1, node3, node5
    • Cartesian product: rack[1-2]-node[1-3] → 6 hosts
    • Domain suffix support: web[1-3].example.com
    • User and port preservation: admin@db[01-03]:5432
    • File input with ^/path/to/hostfile
  • In-TUI Log Panel (Issue #106)

    • Toggle visibility with l key
    • Color-coded by level: ERROR (red), WARN (yellow), INFO (white), DEBUG (gray)
    • Configurable buffer size via BSSH_TUI_LOG_MAX_ENTRIES (default: 1000, max: 10000)
    • Panel height adjustable from 3-10 lines with +/- keys
    • Scroll with j/k keys, toggle timestamps with t
  • --fail-fast Option (Issue #103)

    • -k / --fail-fast flag to stop immediately on first failure
    • Compatible with pdsh -k option
    • Cancels pending commands when any node fails
    • Can be combined with --require-all-success for strict error handling
  • --batch Option (Issue #102)

    • -b / --batch flag for single Ctrl+C termination
    • Compatible with pdsh -b option
    • Useful for non-interactive scripts and CI/CD pipelines
  • --exclude Option (Issue #100)

    • --exclude / -x for host exclusion
    • Supports wildcards, glob patterns, and hostlist expressions
    • Applied after --filter option
  • --no-prefix Option (Issue #101)

    • -N / --no-prefix for disabling hostname prefix in output
    • Compatible with pdsh -N option
    • Works with both stream mode and file mode
  • --connect-timeout Option (PR #103)

    • Separate connection timeout from command execution timeout
    • Default: 30 seconds, minimum: 1 second
    • Useful for fast failure detection on unreachable hosts

Changed

  • CI Workflow Simplification
    • Merged multiple jobs into single pipeline for efficiency

Fixed

  • --timeout 0 Handling (Issue #112)

    • Fixed --timeout 0 to correctly treat as unlimited execution time
    • Previously the 0 value was being ignored, causing unexpected timeout behavior
    • Added explicit CLI test to prevent regression
  • Environment Variable Test Race Conditions

    • Added #[serial] attribute to env var tests to prevent race conditions
    • Tests now run sequentially when accessing shared environment state
  • Connect Timeout Propagation

    • Fixed connect_timeout not being propagated through all SSH connection paths

Documentation

  • Architecture Restructure (Issue #109)

    • Restructured ARCHITECTURE.md into modular documentation
    • Removed residual dates and fixed incomplete sentences
  • pdsh Compatibility Documentation (Issue #110)

    • Added comprehensive pdsh migration guide (docs/pdsh-migration.md)
    • Added pdsh options reference (docs/pdsh-options.md)
    • Added pdsh usage examples (docs/pdsh-examples.md)
    • Added installation scripts for pdsh symlink setup

1.4.2 - 2025-12-16

Fixed

  • PTY Session Terminal Handling (PR #90)
    • Fixed terminal escape sequence responses displayed on first prompt when starting tmux
    • Improved terminal compatibility with multiplexers
  • PTY Session Paste (PR #89)
    • Fixed paste not working in PTY sessions
    • Improved clipboard/paste functionality in interactive terminal sessions

Changed

  • Dependencies
    • Bumped dependencies to latest versions for security and compatibility

1.4.1 - 2025-12-16

Added

  • Comprehensive Test Suite (Issue #82, PR #86)
    • tests/tui_snapshot_tests.rs: 20 tests for TUI rendering using ratatui's TestBackend
    • tests/tui_event_tests.rs: 36 tests for keyboard navigation, scroll behavior, and view transitions
    • tests/streaming_integration_tests.rs: 28 tests for NodeStream, MultiNodeStreamManager, and streaming execution
    • benches/large_output_benchmark.rs: Performance benchmarks for large output handling
    • Total: 84 new tests added

Fixed

  • SSH Agent Password Fallback (Issue #84, PR #85)
    • Extended password fallback to handle all SSH agent authentication failures
    • Now correctly triggers for: AgentAuthenticationFailed, AgentNoIdentities, AgentConnectionFailed, AgentRequestIdentitiesFailed
    • Added is_auth_error_for_password_fallback() helper function for testability
    • Added unit tests and integration tests for all error types

Documentation

  • TUI Module Documentation (Issue #81, PR #83)
    • Added comprehensive TUI architecture section to ARCHITECTURE.md
    • Enhanced README.md with keyboard shortcuts reference table
    • Added view modes description table
    • Added TUI activation conditions and requirements
    • Added missing "1-9: Jump to node N" shortcut in detail view help text

Dependencies

  • Added insta 1.34 (snapshot testing)
  • Added criterion 0.5 (benchmarking)
  • Added mockall 0.12 (mocking for integration tests)

Technical Details

  • Refactored test code quality: removed unused functions, replaced panic! with matches! macro
  • Added Unicode test cases (Korean, Chinese, Emoji)
  • Improved assertion messages for better debugging

1.4.0 - 2025-12-15

Added

  • Sudo Password Support (Issue #74, PR #78)
    • -S/--sudo-password flag for automated sudo authentication
    • Securely prompts for sudo password before command execution
    • Automatically detects and responds to sudo password prompts
    • Works with both streaming and non-streaming execution modes
    • BSSH_SUDO_PASSWORD environment variable support (with security warnings)
    • Uses secrecy crate for secure memory handling
    • Password cleared from memory immediately after use
  • Developer Tooling
    • Added githooks for development workflow
    • Setup script for githooks configuration

Fixed

  • Password Fallback (PR #80)
    • Improved SSH debugging for better compatibility
    • Enhanced password authentication fallback logic
  • Fixed clippy warnings for useless_vec and same_item_push

1.3.0 - 2025-12-10

Added

  • Interactive TUI (Terminal User Interface) (Phase 3 of #68)
    • Summary view: All nodes at a glance with progress bars
    • Detail view (1-9): Full output from specific node with scrolling
    • Split view (s): Monitor 2-4 nodes simultaneously
    • Diff view (d): Compare output from two nodes side-by-side
    • Auto-scroll (f): Toggle automatic scrolling
    • Navigation: Arrow keys, PgUp/PgDn, Home/End
    • Help (?): Show keyboard shortcuts
    • Press q to quit
  • Multi-node Stream Management (Phase 2 of #68)
    • Real-time output modes for multi-node operations
    • Stream mode with [node] prefixes for real-time monitoring
    • Enhanced streaming infrastructure for real-time updates

Fixed

  • PTY Escape Sequence Filtering (PR #77)
    • Filter terminal escape sequence responses in PTY sessions
    • Fixed issue with terminal response codes appearing in output

Technical Details

  • Implemented ratatui-based TUI rendering
  • Added multi-node output aggregation and display
  • Performance optimizations for real-time output streaming

1.2.2 - 2025-10-29

Fixed

  • Backend.AI Auto-detection (PR #66)
    • Improved host heuristics for Backend.AI environments
    • Added localhost and localhost.localdomain detection
    • Added IPv4 address validation (127.0.0.1, 192.168.x.x, etc.)
    • Enhanced detection for user@host, host:port, FQDN, IPv6 patterns
    • Users can now use bssh localhost "command" naturally in Backend.AI

Technical Details

  • Extracted testable looks_like_host_specification() function
  • Added is_ipv4_address() helper with strict validation
  • Performance optimized with early returns
  • 16 comprehensive tests added for host detection logic

1.2.1 - 2025-10-28

Fixed

  • Password Authentication Fallback in Interactive Mode (PR #65)
    • Re-implemented password authentication fallback logic for interactive mode
    • Fixed issue where password prompt was not appearing after key-based authentication failed
    • Ensured proper authentication flow in interactive sessions
  • Test Race Condition (commit d2e8ce9)
    • Added #[serial] attribute to tests calling RankDetector to prevent environment variable race conditions
    • Tests now run sequentially when accessing shared environment state
    • Prevents intermittent test failures due to concurrent environment variable access

1.2.0 - 2025-10-27

BREAKING CHANGES

  • Exit code behavior changed (Issue #62)
    • Old behavior (v1.0-v1.1): Returns 0 only if all nodes succeeded, 1 if any failed
    • New behavior (v1.2.0+): Returns main rank's actual exit code (matches MPI standard: mpirun, srun, mpiexec)
    • Impact: Users relying on "all nodes must succeed" semantics must add --require-all-success flag
    • Benefit: Preserves actual exit codes (139=SIGSEGV, 137=OOM, 124=timeout) for better diagnostics
    • MPI users: No changes needed - behavior improved and matches standard tools
    • Health checks: Add --require-all-success flag to preserve old behavior

Added

  • Exit Code Strategy (Issue #62)
    • Main rank exit code returned by default (matches MPI standard: mpirun, srun, mpiexec)
    • Preserves actual exit codes: 139 (SIGSEGV), 137 (OOM), 124 (timeout), etc.
    • --require-all-success flag for v1.0-v1.1 behavior (returns 0 only if all nodes succeed)
    • --check-all-nodes flag for hybrid mode (main rank code + all-node check)
    • Automatic main rank detection via BACKENDAI_CLUSTER_ROLE environment variable
    • Example scripts: examples/mpi_exit_code.sh, examples/health_check.sh

Changed

  • Exit code behavior now aligns with HPC and distributed computing best practices
  • Enables sophisticated error handling in shell scripts and CI/CD pipelines

1.1.0 - 2025-10-24

Added

  • macOS Keychain Integration (Issue #59, PR #61)
    • Automatic passphrase storage in macOS Keychain after successful SSH key authentication
    • Automatic passphrase retrieval before prompting user
    • Secure memory handling with Zeroizing for all sensitive data
    • Integration with SSH config UseKeychain option per host
    • New module src/ssh/keychain_macos.rs with complete Keychain API wrapper
  • ProxyUseFdpass SSH Option (Issue #58, PR #60)
    • Added ProxyUseFdpass SSH configuration option support
    • Optimizes ProxyCommand usage by passing connected file descriptors back to ssh
    • Reduces overhead from lingering processes and extra read/write operations
  • Password Authentication Fallback
    • Automatic password retry when publickey authentication fails
    • Matches OpenSSH standard behavior for seamless user experience
    • Interactive terminal detection with TTY checks
    • Works for both exec and interactive modes

Security

  • SSH Key File Ownership Validation (PR #61)
    • Prevents storing passphrases for SSH keys owned by other users
    • Added macOS user ID checks using libc
    • World-readable SSH key permission warnings
  • User Consent for Password Fallback (PR #61)
    • Explicit user consent prompt before attempting password authentication
    • 30-second timeout for consent prompt
    • Prevents unexpected password prompts that could lead to credential exposure
  • Rate Limiting (PR #61)
    • 100ms delay before initial connection attempts
    • 1 second delay before password fallback
    • Prevents brute-force attacks and fail2ban triggers

Improved

  • Code Quality (PR #61)
    • Eliminated 251 lines of code duplication in connection logic
    • Created establish_connection() helper function
    • Centralized authentication logic in auth module
    • 60% reduction in connection.rs complexity
  • Cross-Platform Support
    • All macOS-specific code properly isolated with #[cfg(target_os = "macos")]
    • Conditional imports to prevent unused code warnings on non-macOS platforms
    • Stub functions for API consistency across platforms

Fixed

  • Fixed clippy warnings on non-macOS platforms (unused_mut, unused_imports, dead_code)
    • Variable shadowing for macOS-specific code paths
    • Conditional imports for platform-specific functions
  • Fixed interactive mode missing use_keychain field causing authentication failures
  • Fixed password prompt not appearing when connecting to new servers in interactive mode

Dependencies

  • Added security-framework = "2.12.1" for macOS Keychain API integration
  • Added libc for macOS user ID checks (conditional on macOS)

1.0.0 - 2025-10-24

Added

  • SSH Configuration: Certificate Authentication Options

    • CertificateFile - Specify SSH certificate files for PKI authentication (maximum 100 certificates)
    • CASignatureAlgorithms - Define CA signature algorithms for certificate validation (maximum 50 algorithms)
    • HostbasedAuthentication - Enable/disable host-based authentication
    • HostbasedAcceptedAlgorithms - Specify accepted algorithms for host-based authentication (maximum 50 algorithms)
  • SSH Configuration: Advanced Port Forwarding Control

    • GatewayPorts - Control remote port forwarding access (yes/no/clientspecified)
    • ExitOnForwardFailure - Terminate connection when port forwarding fails
    • PermitRemoteOpen - Specify allowed destinations for remote TCP port forwarding (maximum 1000 entries)
  • SSH Configuration: Command Execution and Automation Options

    • PermitLocalCommand - Allow execution of local commands after successful SSH connection (yes/no, default: no)
    • LocalCommand - Execute local command after connection with token substitution support (%h, %H, %n, %p, %r, %u, %%)
    • RemoteCommand - Execute command on remote host instead of starting interactive shell
    • KnownHostsCommand - Execute command to obtain host keys dynamically (supports token substitution)
    • ForkAfterAuthentication - Fork SSH process to background after successful authentication (yes/no)
    • SessionType - Specify session type: none (port forwarding only), subsystem (e.g., SFTP), or default (shell)
    • StdinNull - Redirect stdin from /dev/null for background operations and scripting (yes/no)
  • SSH Configuration: Host Key Verification & Security Options

    • NoHostAuthenticationForLocalhost - Skip host key verification for localhost connections (convenient for local development, default: no)
    • HashKnownHosts - Hash hostnames in known_hosts file to prevent hostname disclosure if compromised (default: no)
    • CheckHostIP - Check host IP address in known_hosts for DNS spoofing detection (deprecated in OpenSSH 8.5+, retained for legacy compatibility)
    • VisualHostKey - Display ASCII art of host key fingerprint for visual verification (default: no)
    • HostKeyAlias - Specify alias for host key lookup in known_hosts (useful for load-balanced services with shared keys)
    • VerifyHostKeyDNS - Verify host keys using DNS SSHFP records (yes/no/ask, default: no)
    • UpdateHostKeys - Accept updated host keys from server automatically (yes/no/ask, default: no)
  • SSH Configuration: Additional Authentication Options

    • NumberOfPasswordPrompts - Control password authentication retry attempts (valid range: 1-10, default: 3)
    • EnableSSHKeysign - Enable ssh-keysign for host-based authentication (yes/no, default: no)
  • SSH Configuration: Network & Connection Options

    • BindInterface - Bind SSH connection to specific network interface (alternative to BindAddress for multi-homed hosts)
    • IPQoS - Set IP type-of-service/DSCP values for interactive and bulk traffic (e.g., "lowdelay throughput")
    • RekeyLimit - Control SSH session key renegotiation frequency (format: "data [time]", e.g., "1G 1h")
  • SSH Configuration: X11 Forwarding Options

    • ForwardX11Timeout - Set timeout for untrusted X11 forwarding connections (time interval, default: 0 = no timeout)
    • ForwardX11Trusted - Enable trusted X11 forwarding with full display access (yes/no, default: no)
  • Security Enhancements

    • Path validation to prevent usage of sensitive system files (e.g., /etc/passwd, /etc/shadow)
    • Memory exhaustion prevention with entry limits for certificates and forwarding rules
    • Algorithm list validation with maximum entry limits
    • Deduplication for certificate files and remote forwarding destinations
    • Command injection prevention for LocalCommand and KnownHostsCommand
    • Token validation to prevent invalid substitution patterns
    • Dangerous character detection in command strings (semicolons, backticks, pipes, etc.)

Changed

  • SSH Config Parser: Refactored into modular structure for better maintainability
    • Split oversized parser.rs (1706 lines) into category-based modules (~200-350 lines each)
    • Organized option parsing by categories: authentication, security, forwarding, connection, etc.
    • Improved code organization and maintainability

Technical Details

  • Enhanced SSH configuration merging logic with proper priority handling
  • Support for both "Option Value" and "Option=Value" syntax
  • Scalar options override in later blocks, vector options accumulate with deduplication
  • SSH Configuration Coverage: ~71 options (~69% of OpenSSH's 103 options)
    • Basic options + Include + Match directives (structural)
    • Certificate authentication and port forwarding (7 options)
    • Command execution and automation (7 options)
    • Host key verification, authentication, network, and X11 options (15 options)
  • Comprehensive test coverage: 278 tests including parser, resolver, integration, and security tests
  • Validation: NumberOfPasswordPrompts range checking (1-10), CheckHostIP deprecation warnings

0.9.1 - 2025-10-14

Added

None

Changed

  • PTY Terminal Modes: Complete implementation of PTY terminal modes for better interactive session support
  • Shift Key Input Support: Full Shift key input handling in PTY mode for proper terminal behavior

Fixed

  • Terminal mode implementation for PTY sessions
  • Shift key input handling in interactive mode

Technical Details

  • Enhanced terminal mode settings for PTY allocation
  • Implemented proper terminal flag handling for interactive sessions
  • Improved keyboard input processing for special keys

0.9.0 - 2025-10-14

Added

  • Configurable Jump Host Limit: Maximum number of jump hosts can now be configured via environment variable

    • BSSH_MAX_JUMP_HOSTS environment variable for dynamic limit configuration
    • Default: 10 jump hosts, Absolute maximum: 30 (security cap)
    • Invalid/zero values fall back to default with warning logs
    • Example: BSSH_MAX_JUMP_HOSTS=20 bssh -J host1,...,host20 target
    • Prevents resource exhaustion attacks while allowing flexible configurations
  • Jump Host File Transfer Support: Added complete file transfer operations through SSH jump hosts

    • upload_file_with_jump_hosts() - Upload single files through jump host chains
    • download_file_with_jump_hosts() - Download single files through jump hosts
    • upload_dir_with_jump_hosts() - Upload directories recursively through jump hosts
    • download_dir_with_jump_hosts() - Download directories through jump hosts
    • All file transfer operations now fully support multi-hop SSH connections
  • Jump Host Interactive Mode Support: Interactive shell sessions now work through jump hosts

    • Added jump_hosts field to InteractiveCommand structure
    • Dynamic timeout calculation based on hop count (30s base + 15s per hop)
    • Prevents premature timeouts on multi-hop connections
    • Full authentication support (SSH keys, agent, password) for each hop
  • Parallel Executor Integration: Jump host support across all parallel operations

    • Updated executor.rs to propagate jump_hosts to all node operations
    • Maintains backward compatibility with Option<&str> type
    • All *_to_node() functions now accept jump_hosts parameter

Changed

  • Interactive Mode: Now includes jump host support with automatic timeout adjustment

    • Connection timeout scales with hop count for reliability
    • Example timeouts: Direct (30s), 1 hop (45s), 2 hops (60s), 3 hops (75s)
  • Test Coverage: Updated all test files to include jump_hosts parameter

    • tests/interactive_test.rs: Added jump_hosts: None to test cases
    • tests/interactive_integration_test.rs: Updated all 9 test instances
    • examples/interactive_demo.rs: Updated example with jump_hosts field
  • Dependencies: Updated various dependencies for security patches and stability

Fixed

  • Interactive mode timeout issues when connecting through jump hosts
  • File transfer operations not working with jump host chains

Security

  • Added serial_test dependency for thread-safe environment variable testing
  • Comprehensive test coverage for environment variable functionality (6 new tests)

Technical Details

  • Files Modified: 8 files
  • Lines Added: +623
  • Lines Removed: -26
  • Net Change: +597 lines
  • Test Results: All 132 tests passing

0.8.0 - 2025-09-12

Added

  • Comprehensive SSH port forwarding support
    • Local port forwarding (-L) for tunneling to remote services
    • Remote port forwarding (-R) for exposing local services
    • Dynamic port forwarding (-D) for SOCKS4/5 proxy functionality
  • Improved error messages with better context and recovery suggestions

Changed

  • Removed dangerous unwrap() calls throughout codebase
  • Enhanced error handling with detailed failure reasons

0.7.0 - 2025-08-30

Added

  • SSH jump host infrastructure (-J option)
    • OpenSSH ProxyJump format parsing
    • Multiple jump hosts support (comma-separated)
    • IPv6 address handling with bracket notation
    • Jump host chain management and connection establishment

Changed

  • Improved Ubuntu PPA support with better packaging
  • Fixed deprecated GitHub Actions workflows

0.6.1 - 2025-08-28

Changed

  • Rebranded from "Backend.AI SSH" to "Broadcast SSH"
    • Emphasizes core broadcast/parallel functionality
    • Better reflects the tool's primary purpose

0.6.0 - 2025-08-28

Added

  • SSH configuration file support (-F option)
    • Auto-loads from ~/.ssh/config by default
    • Supports 40+ SSH directives
    • Wildcard pattern matching and negation
    • Environment variable expansion in paths
  • PTY allocation for interactive sessions (-t/-T options)
  • SSH configuration caching for improved performance
    • LRU cache with configurable size and TTL
    • File modification detection
    • 10-100x faster repeated operations

Changed

  • Enhanced security with improved host key verification
  • Performance improvements across core operations
  • SSH-compatible command-line interface (drop-in replacement)

0.5.4 - 2025-08-27

Fixed

  • Parallel configuration value handling issues
  • Interactive mode authentication alignment with exec mode

0.5.3 - 2025-08-27

Changed

  • Backend.AI cluster auto-detection now uses cluster SSH key configuration

0.5.2 - 2025-08-27

Fixed

  • Configuration file loading priority issues
  • Backend.AI environment variable handling improvements

Changed

  • Now uses cluster SSH key configuration when available

0.5.1 - 2025-08-25

Added

  • Configurable command timeout support
    • Set timeout via --timeout flag or configuration file
    • Support for unlimited execution time (timeout=0)
    • Default timeout: 300 seconds (5 minutes)

0.5.0 - 2025-08-22

Added

  • Interactive mode with PTY support
    • Single-node mode for focused interaction
    • Multiplex mode for parallel command execution
    • Node switching commands (!node1, !node2, etc.)
    • Broadcast command (!broadcast <cmd>)
    • Visual status indicators (● active, ○ inactive)
    • Command history with rustyline
    • Configurable prompts and settings

Changed

  • Improved Backend.AI cluster auto-detection
  • Enhanced interactive shell capabilities

0.4.0 - 2025-08-22

Added

  • Password authentication support (-P flag)
  • SSH key passphrase support with secure prompting
  • Modern UI with semantic colors and Unicode symbols
  • Debian package distribution (.deb)

Changed

  • XDG Base Directory specification compliance
  • Improved configuration management
  • Enhanced visual feedback and progress indicators

0.3.0 - 2025-08-22

Added

  • Native SFTP directory operations
  • Recursive file transfer support
    • Upload directories with -r flag
    • Download entire directory trees
    • Glob pattern support for batch operations

0.2.0 - 2025-08-21

Added

  • Backend.AI multi-node session support
    • Automatic cluster detection from environment variables
    • Default SSH port 2200 for Backend.AI clusters
  • SSH authentication enhancements
    • SSH agent authentication with auto-detection
    • Host key verification with known_hosts support
    • Multiple authentication method fallback
  • Environment variable expansion in configuration files
  • Connection and command timeout configuration
  • SFTP file transfer (upload/download)
    • SCP-compatible file copy functionality
    • Progress tracking for file operations

Changed

  • Improved error messages and diagnostics
  • Enhanced security with host key verification

0.1.0 - 2025-08-21

Added

  • Initial release of bssh
  • Parallel SSH command execution across multiple nodes
  • Cluster configuration management via YAML files
  • Node specification via CLI (-H flag)
  • SSH key-based authentication
  • Real-time progress tracking with progress bars
  • Per-node output collection and aggregation
  • Configurable parallel execution limits
  • Connectivity testing (ping command)
  • Cluster listing (list command)

Features

  • Built with Rust for performance and safety
  • Async/await pattern for maximum concurrency
  • Tokio runtime for efficient I/O operations
  • russh library for native SSH implementation
  • Cross-platform support (Linux and macOS)