-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Problem / Background
Currently bssh supports jump hosts through:
- CLI
-J/--jump-hostoption - SSH config file
~/.ssh/configwithProxyJumpdirective
However, there are several limitations:
Issue 1: No config.yaml support for jump hosts
bssh's own config.yaml does NOT support jump host configuration. Users cannot specify jump hosts per-cluster or per-node in the configuration file, which limits the usefulness of the configuration system for networks that require bastion hosts.
Issue 2: Commands missing -J support
Several commands do not pass through the CLI -J option:
| Command | -J Support |
Location | Issue |
|---|---|---|---|
exec |
✅ Works | - | - |
interactive |
✅ Works | - | - |
ping |
❌ Missing | src/commands/ping.rs:57 |
Hardcoded .with_jump_hosts(None) |
upload |
❌ Missing | src/commands/upload.rs |
FileTransferParams lacks jump_hosts field |
download |
❌ Missing | src/commands/download.rs |
FileTransferParams lacks jump_hosts field |
Proposed Solution
Part A: Add jump_host field to config.yaml
Add jump_host field support at three levels:
1. Global Default Level (Defaults struct)
Add jump_host: Option<String> to apply to all clusters by default.
2. Cluster Level (ClusterDefaults struct)
Add jump_host: Option<String> to override global default for specific clusters.
3. Node Level (NodeConfig::Detailed variant)
Add jump_host: Option<String> to override cluster default for specific nodes.
Example config.yaml format:
defaults:
user: ubuntu
port: 22
jump_host: bastion.example.com # Global default jump host
clusters:
production:
nodes:
- host: prod1.internal
- host: prod2.internal
jump_host: prod-bastion.example.com # Cluster-level override
staging:
nodes:
- host: staging1.internal
jump_host: staging-bastion:2222 # Node-level override
- host: staging2.internal # Uses cluster jump_host
jump_host: staging-bastion.example.com
development:
nodes:
- host: dev1.example.com # No jump host needed (direct access)
jump_host: "" # Explicitly disable jump host for this node
- host: dev2.internal # Uses global default jump_hostPriority Order (highest to lowest):
- Node-level
jump_host(inNodeConfig::Detailed) - Cluster-level
jump_host(inClusterDefaults) - Global default
jump_host(inDefaults) - CLI
-Joption (fallback when config doesn't specify)
Empty string ("") should explicitly disable jump host inheritance.
Part B: Enable -J support for ping/upload/download commands
- Add
jump_hosts: Option<String>field toFileTransferParamsstruct - Pass
cli.jump_hoststhrough dispatcher for upload/download commands - Replace hardcoded
Nonein ping command with actual jump_hosts value
Acceptance Criteria
Config.yaml Support
- Add
jump_host: Option<String>field toDefaultsstruct insrc/config/types.rs - Add
jump_host: Option<String>field toClusterDefaultsstruct insrc/config/types.rs - Add
jump_host: Option<String>field toNodeConfig::Detailedvariant insrc/config/types.rs - Implement
get_jump_host()resolution method insrc/config/resolver.rsfollowing priority order - Update
src/app/dispatcher.rsto integrate config-based jump_hosts with CLI override logic
Command Support
- Add
jump_hosts: Option<String>toFileTransferParamsinsrc/commands/upload.rs - Update
src/commands/ping.rs:57- Replace.with_jump_hosts(None)with resolved jump_hosts - Update
src/app/dispatcher.rsping handler to pass jump_hosts - Update
src/app/dispatcher.rsupload handler to pass jump_hosts - Update
src/app/dispatcher.rsdownload handler to pass jump_hosts
Testing & Documentation
- Add unit tests for jump_host resolution with various priority combinations
- Update example configuration in documentation
- Ensure backward compatibility (existing configs without jump_host continue to work)
Technical Considerations
Implementation Locations
src/config/types.rs- Add fields toDefaults,ClusterDefaults, andNodeConfig::Detailedsrc/config/resolver.rs- Addget_jump_host()methodsrc/commands/ping.rs:57- Replace hardcodedNonesrc/commands/upload.rs:25-33- Add field toFileTransferParamssrc/app/dispatcher.rs:82-94- Pass jump_hosts to ping_nodessrc/app/dispatcher.rs:109-118- Pass jump_hosts to upload handlersrc/app/dispatcher.rs:133-142- Pass jump_hosts to download handler
Resolution Logic Example
/// Get jump host for a specific node in a cluster.
pub fn get_jump_host(&self, cluster_name: &str, node_index: usize) -> Option<String> {
if let Some(cluster) = self.get_cluster(cluster_name) {
// Check node-level first
if let Some(NodeConfig::Detailed { jump_host: Some(jh), .. }) = cluster.nodes.get(node_index) {
if jh.is_empty() {
return None; // Explicitly disabled
}
return Some(jh.clone());
}
// Check cluster-level
if let Some(jh) = &cluster.defaults.jump_host {
if \!jh.is_empty() {
return Some(jh.clone());
}
}
}
// Fall back to global default
self.defaults.jump_host.clone().filter(|s| \!s.is_empty())
}Additional Context
Related code:
src/cli/bssh.rs:119-pub jump_hosts: Option<String>src/jump/module - Jump host parsing and chain management already implementedsrc/executor/parallel.rs:156-157-with_jump_hosts()builder method exists
This feature would enable full declarative configuration of complex network topologies with bastion hosts, matching the capabilities of traditional SSH config files while providing the additional benefits of bssh's cluster management.