🏡 index : ~doyle/chartered.git

author Jordan Doyle <jordan@doyle.la> 2021-10-08 3:52:44.0 +01:00:00
committer Jordan Doyle <jordan@doyle.la> 2021-10-08 3:52:44.0 +01:00:00
commit
23711fa2b804feedc34eccaa7688f9613a2a9373 [patch]
tree
e55325e9936f576d6b142869ee5bc61c71a92d24
parent
0fe0925fe21384af33e930d11593a05375f20fe1
download
23711fa2b804feedc34eccaa7688f9613a2a9373.tar.gz

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(-)

diff --git a/Cargo.lock b/Cargo.lock
index 4abddc8..6afd0d8 100644
--- a/Cargo.lock
+++ a/Cargo.lock
@@ -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]]
diff --git a/chartered-git/Cargo.toml b/chartered-git/Cargo.toml
index 83143b7..72cd5f5 100644
--- a/chartered-git/Cargo.toml
+++ a/chartered-git/Cargo.toml
@@ -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"
diff --git a/chartered-git/src/main.rs b/chartered-git/src/main.rs
index 136412f..e7581ff 100644
--- a/chartered-git/src/main.rs
+++ a/chartered-git/src/main.rs
@@ -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)] // broken clippy lint
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(); // todo
            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);
            }

            // TODO: check GIT_PROTOCOL=version=2 set
            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"))?; // TODO: clap::crate_name!()/clap::crate_version!()
            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
                );

                // if the client flushed without giving us a command, we're expected to close
                // the connection or else the client will just hang
@@ -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),
                }
            }

diff --git a/chartered-git/src/git/codec.rs b/chartered-git/src/git/codec.rs
index 5d86ea8..9f5cda7 100644
--- a/chartered-git/src/git/codec.rs
+++ a/chartered-git/src/git/codec.rs
@@ -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(),
                );