Fix ssh settings not getting applied, ssh.bin being mispelled, and added ClientConnectConfig

pull/137/head
Chip Senkbeil 2 years ago
parent eadeb4c75b
commit 86b34d23c6
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- New `ClientConnectConfig` to support connect settings, specifically for ssh
### Fixed
- `ssh` option to specify external binary not working on `launch` due to the
key being mis-labeled as `ssh.bind` instead of `ssh.bin`
- All ssh settings were not being applied with manager handlers due to some key
checks being incorrect (e.g. `backend` instead of `ssh.backend`). This has
now been corrected and settings now properly get applied
## [0.17.2] - 2022-08-16
### Added

@ -362,43 +362,54 @@ impl<'a> distant_ssh2::SshAuthHandler for AuthClientSshAuthHandler<'a> {
#[cfg(any(feature = "libssh", feature = "ssh2"))]
fn load_ssh(destination: &Destination, extra: &Extra) -> io::Result<distant_ssh2::Ssh> {
trace!("load_ssh({destination}, {extra}");
use distant_ssh2::{Ssh, SshOpts};
let host = destination.to_host_string();
let opts = SshOpts {
backend: match extra.get("backend") {
backend: match extra.get("backend").or_else(|| extra.get("ssh.backend")) {
Some(s) => s.parse().map_err(|_| invalid("backend"))?,
None => Default::default(),
},
identity_files: extra
.get("identity_files")
.or_else(|| extra.get("ssh.identity_files"))
.map(|s| s.split(',').map(|s| PathBuf::from(s.trim())).collect())
.unwrap_or_default(),
identities_only: match extra.get("identities_only") {
identities_only: match extra
.get("identities_only")
.or_else(|| extra.get("ssh.identities_only"))
{
Some(s) => Some(s.parse().map_err(|_| invalid("identities_only"))?),
None => None,
},
port: destination.port(),
proxy_command: extra.get("proxy_command").cloned(),
proxy_command: extra
.get("proxy_command")
.or_else(|| extra.get("ssh.proxy_command"))
.cloned(),
user: destination.username().map(ToString::to_string),
user_known_hosts_files: extra
.get("user_known_hosts_files")
.or_else(|| extra.get("ssh.user_known_hosts_files"))
.map(|s| s.split(',').map(|s| PathBuf::from(s.trim())).collect())
.unwrap_or_default(),
verbose: match extra.get("verbose") {
verbose: match extra.get("verbose").or_else(|| extra.get("ssh.verbose")) {
Some(s) => s.parse().map_err(|_| invalid("verbose"))?,
None => false,
},
..Default::default()
};
debug!("Connecting to {host} via ssh with {opts:?}");
Ssh::connect(host, opts)
}

@ -2,10 +2,12 @@ use super::{CommonConfig, NetworkConfig};
use serde::{Deserialize, Serialize};
mod action;
mod connect;
mod launch;
mod repl;
pub use action::*;
pub use connect::*;
pub use launch::*;
pub use repl::*;
@ -16,6 +18,7 @@ pub struct ClientConfig {
pub common: CommonConfig,
pub action: ClientActionConfig,
pub connect: ClientConnectConfig,
pub launch: ClientLaunchConfig,
pub repl: ClientReplConfig,

@ -0,0 +1,80 @@
use clap::Args;
use distant_core::Map;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Args, Debug, Default, Serialize, Deserialize)]
pub struct ClientConnectConfig {
#[cfg(any(feature = "libssh", feature = "ssh2"))]
#[clap(flatten)]
#[serde(flatten)]
pub ssh: ClientConnectSshConfig,
}
impl From<Map> for ClientConnectConfig {
fn from(mut map: Map) -> Self {
Self {
#[cfg(any(feature = "libssh", feature = "ssh2"))]
ssh: ClientConnectSshConfig {
backend: map
.remove("ssh.backend")
.and_then(|x| x.parse::<distant_ssh2::SshBackend>().ok()),
username: map.remove("ssh.username"),
identity_file: map
.remove("ssh.identity_file")
.and_then(|x| x.parse::<PathBuf>().ok()),
port: map.remove("ssh.port").and_then(|x| x.parse::<u16>().ok()),
},
}
}
}
impl From<ClientConnectConfig> for Map {
fn from(config: ClientConnectConfig) -> Self {
let mut this = Self::new();
#[cfg(any(feature = "libssh", feature = "ssh2"))]
{
if let Some(x) = config.ssh.backend {
this.insert("ssh.backend".to_string(), x.to_string());
}
if let Some(x) = config.ssh.username {
this.insert("ssh.username".to_string(), x);
}
if let Some(x) = config.ssh.identity_file {
this.insert(
"ssh.identity_file".to_string(),
x.to_string_lossy().to_string(),
);
}
if let Some(x) = config.ssh.port {
this.insert("ssh.port".to_string(), x.to_string());
}
}
this
}
}
#[cfg(any(feature = "libssh", feature = "ssh2"))]
#[derive(Args, Debug, Default, Serialize, Deserialize)]
pub struct ClientConnectSshConfig {
/// Represents the backend
#[clap(name = "ssh-backend", long)]
pub backend: Option<distant_ssh2::SshBackend>,
/// Username to use when sshing into remote machine
#[clap(name = "ssh-username", short = 'u', long)]
pub username: Option<String>,
/// Explicit identity file to use with ssh
#[clap(name = "ssh-identity-file", short = 'i', long)]
pub identity_file: Option<PathBuf>,
/// Port to use for sshing into the remote machine
#[clap(name = "ssh-port", short = 'p', long)]
pub port: Option<u16>,
}

@ -30,7 +30,7 @@ impl From<Map> for ClientLaunchConfig {
.unwrap_or_default(),
},
ssh: ClientLaunchSshConfig {
bin: map.remove("ssh.bind"),
bin: map.remove("ssh.bin"),
#[cfg(any(feature = "libssh", feature = "ssh2"))]
backend: map
.remove("ssh.backend")

Loading…
Cancel
Save