Use slog for chartered-git
Diff
Cargo.lock | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
chartered-git/Cargo.toml | 8 +++++---
chartered-git/src/main.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
chartered-git/src/git/codec.rs | 2 --
4 files changed, 162 insertions(+), 16 deletions(-)
@@ -303,9 +303,9 @@
"chartered-db",
"chartered-types",
"chrono",
"clap",
"const-sha1",
"crc",
"env_logger",
"flate2",
"format-bytes",
"futures",
@@ -313,11 +313,13 @@
"indexmap",
"indoc",
"itoa",
"log",
"serde",
"serde_json",
"sha-1",
"shlex",
"slog",
"slog-async",
"slog-term",
"thrussh",
"thrussh-keys",
"tokio",
@@ -471,8 +473,28 @@
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
@@ -575,10 +597,31 @@
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
@@ -1714,6 +1757,12 @@
"web-sys",
"winapi",
]
[[package]]
name = "rustversion"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
[[package]]
name = "ryu"
@@ -1868,6 +1917,37 @@
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
[[package]]
name = "slog"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06"
[[package]]
name = "slog-async"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "766c59b252e62a34651412870ff55d8c4e6d04df19b43eecb2703e417b097ffe"
dependencies = [
"crossbeam-channel",
"slog",
"take_mut",
"thread_local",
]
[[package]]
name = "slog-term"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95c1e7e5aab61ced6006149ea772770b84a0d16ce0f7885def313e4829946d76"
dependencies = [
"atty",
"chrono",
"slog",
"term",
"thread_local",
]
[[package]]
name = "smallvec"
@@ -1921,6 +2001,12 @@
checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
[[package]]
name = "take_mut"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1931,6 +2017,17 @@
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "term"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
dependencies = [
"dirs-next",
"rustversion",
"winapi",
]
@@ -1970,6 +2067,15 @@
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
dependencies = [
"once_cell",
]
[[package]]
@@ -11,12 +11,12 @@
anyhow = "1"
arrayvec = "0.7"
async-trait = "0"
async-trait = "0.1"
bytes = "1"
clap = "3.0.0-beta.4"
chrono = "0.4"
const-sha1 = "0.2"
crc = "2"
env_logger = "0.9"
flate2 = "1.0"
format-bytes = "0.2"
futures = "0.3"
@@ -24,7 +24,9 @@
indexmap = "1"
indoc = "1.0"
itoa = "0.4"
log = "0.4"
slog = { version = "2.7", features = ["max_level_trace", "release_max_level_info"] }
slog-async = "2.7"
slog-term = "2.8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
shlex = "1"
@@ -19,7 +19,7 @@
use arrayvec::ArrayVec;
use bytes::BytesMut;
use futures::future::Future;
use log::warn;
use slog::{debug, error, info, o, warn, Drain, Logger};
use std::{fmt::Write, pin::Pin, sync::Arc};
use thrussh::{
server::{self, Auth, Session},
@@ -32,7 +32,10 @@
#[tokio::main]
#[allow(clippy::semicolon_if_nothing_returned)]
async fn main() {
env_logger::init();
let decorator = slog_term::TermDecorator::new().build();
let drain = slog_term::FullFormat::new(decorator).build().fuse();
let drain = slog_async::Async::new(drain).build().fuse();
let log = slog::Logger::root(drain, o!());
let config = Arc::new(thrussh::server::Config {
methods: thrussh::MethodSet::PUBLICKEY,
@@ -42,6 +45,7 @@
let server = Server {
db: chartered_db::init().unwrap(),
log,
};
thrussh::server::run(config, "127.0.0.1:2233", server)
@@ -52,32 +56,40 @@
#[derive(Clone)]
struct Server {
db: chartered_db::ConnectionPool,
log: Logger,
}
impl server::Server for Server {
type Handler = Handler;
fn new(&mut self, ip: Option<std::net::SocketAddr>) -> Self::Handler {
let log = self.log.new(o!("ip" => ip));
info!(log, "Connection received");
Handler {
ip,
log,
codec: GitCodec::default(),
input_bytes: BytesMut::default(),
output_bytes: BytesMut::default(),
db: self.db.clone(),
authed: None,
organisation: None,
is_git_protocol_v2: false,
}
}
}
struct Handler {
ip: Option<std::net::SocketAddr>,
log: Logger,
codec: GitCodec,
input_bytes: BytesMut,
output_bytes: BytesMut,
db: chartered_db::ConnectionPool,
organisation: Option<String>,
authed: Option<Authed>,
is_git_protocol_v2: bool,
}
struct Authed {
@@ -131,10 +143,29 @@
fn finished(self, s: Session) -> Self::FutureUnit {
Box::pin(futures::future::ready(Ok((self, s))))
}
fn env_request(
mut self,
_channel: ChannelId,
name: &str,
value: &str,
session: Session,
) -> Self::FutureUnit {
debug!(&self.log, "env set {}={}", name, value);
match (name, value) {
("GIT_PROTOCOL", "version=2") => self.is_git_protocol_v2 = true,
_ => {}
}
Box::pin(futures::future::ready(Ok((self, session))))
}
fn shell_request(mut self, channel: ChannelId, mut session: Session) -> Self::FutureUnit {
Box::pin(async move {
error!(&self.log, "Attempted to open a shell, rejecting connection");
let username = self.authed()?.user.username.clone();
write!(&mut self.output_bytes, "Hi there, {}! You've successfully authenticated, but chartered does not provide shell access.\r\n", username)?;
self.flush(&mut session, channel);
@@ -154,8 +185,14 @@
Err(e) => return Box::pin(futures::future::err(e.into())),
};
let args = shlex::split(data);
debug!(&self.log, "exec {}", data);
Box::pin(async move {
if !self.is_git_protocol_v2 {
anyhow::bail!("not git protocol v2");
}
let mut args = args.into_iter().flat_map(Vec::into_iter);
if args.next().as_deref() != Some("git-upload-pack") {
@@ -177,9 +214,8 @@
session.close(channel);
}
self.write(PktLine::Data(b"version 2\n"))?;
self.write(PktLine::Data(b"agent=chartered/0.1.0\n"))?;
self.write(PktLine::Data(b"agent=chartered/0.1.0\n"))?;
self.write(PktLine::Data(b"ls-refs=unborn\n"))?;
self.write(PktLine::Data(b"fetch=shallow wait-for-done\n"))?;
self.write(PktLine::Data(b"server-option\n"))?;
@@ -194,10 +230,9 @@
fn subsystem_request(
self,
_channel: ChannelId,
data: &str,
_data: &str,
session: Session,
) -> Self::FutureUnit {
eprintln!("subsystem req: {}", data);
Box::pin(futures::future::ready(Ok((self, session))))
}
@@ -215,7 +250,7 @@
let ssh_key = Arc::new(ssh_key);
if let Err(e) = ssh_key.clone().update_last_used(self.db.clone()).await {
warn!("Failed to update last used key: {:?}", e);
warn!(&self.log, "Failed to update last used key: {:?}", e);
}
let auth_key = ssh_key
@@ -252,7 +287,10 @@
Box::pin(async move {
while let Some(frame) = self.codec.decode(&mut self.input_bytes)? {
eprintln!("{:#?}", frame);
debug!(
&self.log,
"decoded frame command={:?} metadata={:?}", frame.command, frame.metadata
);
@@ -302,8 +340,10 @@
packfile_entries,
)
.await?
}
v => {
error!(&self.log, "Client sent unknown command, ignoring"; "command" => std::str::from_utf8(v).unwrap_or("invalid utf8"))
}
v => eprintln!("unknown command {:?}", v),
}
}
@@ -49,10 +49,8 @@
return Ok(Some(std::mem::take(&mut self.command)));
} else if length == 1 || length == 2 {
src.advance(4);
eprintln!("magic packet = {}", length);
continue;
} else if !(4..=65520).contains(&length) {
eprintln!("protocol abuse");
return Err(
std::io::Error::new(std::io::ErrorKind::InvalidData, "protocol abuse").into(),
);