[APP-3801] implement remote environments auth (#9331)
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
//! [`SshTransport`] uses an existing SSH ControlMaster socket to check/install
|
||||
//! the remote server binary and to launch the `remote-server-proxy` process
|
||||
//! whose stdin/stdout become the protocol channel.
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
@@ -12,8 +13,11 @@ use std::sync::Arc;
|
||||
use anyhow::Result;
|
||||
use warpui::r#async::executor;
|
||||
|
||||
use remote_server::auth::RemoteServerAuthContext;
|
||||
use remote_server::client::RemoteServerClient;
|
||||
use remote_server::setup::{self, RemotePlatform, CHECK_TIMEOUT, INSTALL_TIMEOUT};
|
||||
use remote_server::setup::{
|
||||
self, remote_server_daemon_dir, RemotePlatform, CHECK_TIMEOUT, INSTALL_TIMEOUT,
|
||||
};
|
||||
use remote_server::ssh::{run_ssh_command, run_ssh_script, ssh_args};
|
||||
use remote_server::transport::{Connection, RemoteTransport};
|
||||
|
||||
@@ -23,16 +27,54 @@ use remote_server::transport::{Connection, RemoteTransport};
|
||||
/// process (`ssh -N -o ControlMaster=yes -o ControlPath=<path>`). All SSH
|
||||
/// commands (binary check, install, proxy launch) are multiplexed through
|
||||
/// this socket without re-authenticating.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct SshTransport {
|
||||
socket_path: PathBuf,
|
||||
auth_context: Arc<RemoteServerAuthContext>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for SshTransport {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SshTransport")
|
||||
.field("socket_path", &self.socket_path)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl SshTransport {
|
||||
pub fn new(socket_path: PathBuf) -> Self {
|
||||
Self { socket_path }
|
||||
pub fn new(socket_path: PathBuf, auth_context: Arc<RemoteServerAuthContext>) -> Self {
|
||||
Self {
|
||||
socket_path,
|
||||
auth_context,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn socket_path(&self) -> &PathBuf {
|
||||
&self.socket_path
|
||||
}
|
||||
|
||||
pub fn remote_daemon_socket_path(&self) -> String {
|
||||
format!(
|
||||
"{}/server.sock",
|
||||
remote_server_daemon_dir(&self.auth_context.remote_server_identity_key())
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remote_daemon_pid_path(&self) -> String {
|
||||
format!(
|
||||
"{}/server.pid",
|
||||
remote_server_daemon_dir(&self.auth_context.remote_server_identity_key())
|
||||
)
|
||||
}
|
||||
|
||||
fn remote_proxy_command(&self) -> String {
|
||||
let binary = remote_server::setup::remote_server_binary();
|
||||
let identity_key = self.auth_context.remote_server_identity_key();
|
||||
let quoted_identity_key = shell_words::quote(&identity_key);
|
||||
format!("{binary} remote-server-proxy --identity-key {quoted_identity_key}")
|
||||
}
|
||||
}
|
||||
|
||||
impl RemoteTransport for SshTransport {
|
||||
fn detect_platform(
|
||||
&self,
|
||||
@@ -100,10 +142,10 @@ impl RemoteTransport for SshTransport {
|
||||
executor: Arc<executor::Background>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Connection>> + Send>> {
|
||||
let socket_path = self.socket_path.clone();
|
||||
let remote_proxy_command = self.remote_proxy_command();
|
||||
Box::pin(async move {
|
||||
let binary = setup::remote_server_binary();
|
||||
let mut args = ssh_args(&socket_path);
|
||||
args.push(format!("{binary} remote-server-proxy"));
|
||||
args.push(remote_proxy_command);
|
||||
|
||||
// `kill_on_drop(true)` pairs with ownership of the `Child` being
|
||||
// returned in the [`Connection`] below: the
|
||||
@@ -142,3 +184,28 @@ impl RemoteTransport for SshTransport {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use warpui::r#async::BoxFuture;
|
||||
fn static_auth_context() -> Arc<RemoteServerAuthContext> {
|
||||
Arc::new(RemoteServerAuthContext::new(
|
||||
|| -> BoxFuture<'static, Option<String>> { Box::pin(async { None }) },
|
||||
|| "user id/with spaces".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_proxy_command_quotes_identity_key() {
|
||||
let transport = SshTransport::new(
|
||||
PathBuf::from("/tmp/control-master.sock"),
|
||||
static_auth_context(),
|
||||
);
|
||||
|
||||
let command = transport.remote_proxy_command();
|
||||
|
||||
assert!(command.contains("remote-server-proxy --identity-key"));
|
||||
assert!(command.contains("'user id/with spaces'"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user