Some checks failed
Build and deploy / Build container and manifests (push) Failing after 57s
90 lines
2.9 KiB
Rust
90 lines
2.9 KiB
Rust
use std::net::SocketAddr;
|
|
use std::path::Path;
|
|
|
|
use color_eyre::eyre::Context;
|
|
use dotenvy::dotenv;
|
|
use git_version::git_version;
|
|
use hyper::server::conn::http1::{self};
|
|
use hyper_util::rt::TokioIo;
|
|
use rand::rngs::OsRng;
|
|
use tokio::net::TcpListener;
|
|
use tracing::{error, info, warn};
|
|
use tracing_subscriber::EnvFilter;
|
|
use tracing_subscriber::layer::SubscriberExt;
|
|
use tracing_subscriber::util::SubscriberInitExt;
|
|
use tunnel_rs::ldap::Ldap;
|
|
use tunnel_rs::ssh::Server;
|
|
use tunnel_rs::tunnel::Registry;
|
|
use tunnel_rs::web::{ForwardAuth, Service};
|
|
|
|
#[tokio::main]
|
|
async fn main() -> color_eyre::Result<()> {
|
|
color_eyre::install()?;
|
|
dotenv().ok();
|
|
|
|
let env_filter = EnvFilter::try_from_default_env().or_else(|_| EnvFilter::try_new("info"))?;
|
|
|
|
let logger = tracing_subscriber::fmt::layer().compact();
|
|
tracing_subscriber::Registry::default()
|
|
.with(logger)
|
|
.with(env_filter)
|
|
.init();
|
|
|
|
info!(
|
|
"Starting {} ({})",
|
|
std::env!("CARGO_PKG_NAME"),
|
|
git_version!(),
|
|
);
|
|
|
|
let key = if let Ok(path) = std::env::var("PRIVATE_KEY_FILE") {
|
|
russh::keys::PrivateKey::read_openssh_file(Path::new(&path))
|
|
.wrap_err_with(|| format!("failed to read ssh key: {path}"))?
|
|
} else {
|
|
warn!("No private key file specified, generating a new key");
|
|
russh::keys::PrivateKey::random(&mut OsRng, russh::keys::Algorithm::Ed25519)?
|
|
};
|
|
|
|
let http_port = std::env::var("HTTP_PORT")
|
|
.map(|port| port.parse())
|
|
.unwrap_or(Ok(3000))?;
|
|
let ssh_port = std::env::var("SSH_PORT")
|
|
.map(|port| port.parse())
|
|
.unwrap_or(Ok(2222))?;
|
|
|
|
let domain =
|
|
std::env::var("TUNNEL_DOMAIN").unwrap_or_else(|_| format!("localhost:{http_port}"));
|
|
let authz_address = std::env::var("AUTHZ_ENDPOINT").wrap_err("AUTHZ_ENDPOINT is not set")?;
|
|
|
|
let ldap = Ldap::start_from_env().await?;
|
|
let registry = Registry::new(domain);
|
|
let mut ssh = Server::new(ldap, registry.clone());
|
|
let addr = SocketAddr::from(([0, 0, 0, 0], ssh_port));
|
|
tokio::spawn(async move { ssh.run(key, addr).await });
|
|
info!("SSH is available on {addr}");
|
|
|
|
let auth = ForwardAuth::new(authz_address);
|
|
let service = Service::new(registry, auth);
|
|
let addr = SocketAddr::from(([0, 0, 0, 0], http_port));
|
|
let listener = TcpListener::bind(addr).await?;
|
|
info!("HTTP is available on {addr}");
|
|
|
|
// TODO: Graceful shutdown
|
|
loop {
|
|
let (stream, _) = listener.accept().await?;
|
|
let io = TokioIo::new(stream);
|
|
|
|
let service = service.clone();
|
|
tokio::spawn(async move {
|
|
if let Err(err) = http1::Builder::new()
|
|
.preserve_header_case(true)
|
|
.title_case_headers(true)
|
|
.serve_connection(io, service)
|
|
.with_upgrades()
|
|
.await
|
|
{
|
|
error!("Failed to serve connection: {err:?}");
|
|
}
|
|
});
|
|
}
|
|
}
|