blob: f75fd39c5313237b052aecae3f02d85e6309dd8e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
/// A very thin wrapper on top of `ssh2`.
use anyhow::{Context, Result};
use ssh2::Session;
use std::{
io::Read,
net::{IpAddr, SocketAddr, TcpStream},
};
/// Default `ssh` port.
const PORT: u16 = 22;
/// Handle to an `ssh` session.
pub struct SSHSession {
session: ssh2::Session,
}
impl SSHSession {
/// Create a new `ssh` session.
/// This function is blocking while connecting.
///
/// The tunnel is closed when the `SSHSession` is dropped.
pub fn connect(username: String, password: String, ip: IpAddr) -> Result<Self> {
// Set up the SSH connection
log::info!("initializing a new SSH session ..");
let stream = TcpStream::connect(SocketAddr::new(ip, PORT)).context("TCP connect failed")?;
let mut session = Session::new().context("Failed to connect to SSH server")?;
session.set_tcp_stream(stream);
session.handshake()?;
session
.userauth_password(&username, &password)
.context("SSH auth failed")?;
Ok(Self { session })
}
/// Execute an arbitrary string of commands via ssh.
pub fn exec_blocking(&self, command: &str) -> Result<String> {
let session = &self.session;
let mut channel = session.channel_session()?;
channel.exec(command)?;
let mut output = String::new();
channel.read_to_string(&mut output)?;
channel.send_eof()?;
channel.wait_eof()?;
channel.wait_close()?;
Ok(output)
}
}
|