diff --git a/Cargo.lock b/Cargo.lock index 3c9ca43..7c41c95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -192,6 +192,7 @@ dependencies = [ "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mktemp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "secstr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -504,6 +505,14 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mktemp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "net2" version = "0.2.33" @@ -569,6 +578,16 @@ dependencies = [ "proc-macro2 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.4.2" @@ -617,6 +636,11 @@ name = "rustc-demangle" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.2.3" @@ -960,6 +984,15 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "uuid" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vec_map" version = "0.8.1" @@ -1090,6 +1123,7 @@ dependencies = [ "checksum mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4fcfcb32d63961fb6f367bfd5d21e4600b92cd310f71f9dca25acae196eb1560" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum mktemp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77001ceb9eed65439f3dc2a2543f9ba1417d912686bf224a7738d0966e6dcd69" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" @@ -1097,12 +1131,14 @@ dependencies = [ "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum proc-macro2 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "762eea716b821300a86da08870a64b597304866ceb9f54a11d67b4cf56459c6a" "checksum quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ed7d650913520df631972f21e104a4fa2f9c82a14afc65d17b388a2e29731e7c" +"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "16aa12da69951804cddf5f74d96abcc414a31b064e610dc81e37c1536082f491" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" @@ -1144,6 +1180,7 @@ dependencies = [ "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index 38924da..b0c4e6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ sha-1 = "0.7" failure = "0.1" futures = "0.1" hyper = "0.12" +mktemp = "0.3" lazy_static = "1.1" notify = "4.0" regex = "1.0" diff --git a/examples/github.rs b/examples/github.rs index 33d5459..8be1917 100644 --- a/examples/github.rs +++ b/examples/github.rs @@ -11,9 +11,11 @@ extern crate generic_array; extern crate structopt; use std::collections::HashMap; +use std::env; use std::io::{self, Read}; use std::iter::FromIterator; use std::path::PathBuf; +use std::process::Command; use failure::{err_msg, Error}; use generic_array::GenericArray; @@ -32,7 +34,6 @@ struct Opt { #[derive(Debug, Serialize, Deserialize)] struct Config { secret: String, - outdir: PathBuf, #[serde(default)] disable_hmac_verify: bool, } @@ -43,6 +44,16 @@ struct Payload { headers: HashMap, } +#[derive(Debug, Serialize, Deserialize)] +struct RepositoryInfo { + clone_url: String, +} + +#[derive(Debug, Serialize, Deserialize)] +struct GithubPayload { + repository: RepositoryInfo, +} + fn main() -> Result<(), Error> { let args = Opt::from_args(); let config: Config = serde_json::from_str(&args.config)?; @@ -50,9 +61,7 @@ fn main() -> Result<(), Error> { let mut payload = String::new(); io::stdin().read_to_string(&mut payload)?; - println!("raw payload: {}", payload); let payload: Payload = serde_json::from_str(&payload)?; - println!("processed payload: {}", payload.body); if !config.disable_hmac_verify { let secret = GenericArray::from_iter(config.secret.bytes()); @@ -75,6 +84,17 @@ fn main() -> Result<(), Error> { assert!(left == right, "HMAC signature didn't match",); } - println!("gonna clone it to {:?}", config.outdir); + let payload: GithubPayload = serde_json::from_str(&payload.body)?; + let mut target_path = PathBuf::from(env::var("DIP_WORKDIR")?); + target_path.push("repository"); + println!("{:?}", &target_path); + Command::new("git") + .arg("clone") + .arg(&payload.repository.clone_url) + .arg("--recursive") + .arg("--depth") + .arg("1") + .arg(&target_path) + .output()?; Ok(()) } diff --git a/src/handler.rs b/src/handler.rs index 4f713b2..4ef61e8 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -40,6 +40,11 @@ impl Handler { let program = programs .get(handler) .ok_or(err_msg(format!("'{}' is not a valid executable", handler))) + .and_then(|value| { + value + .canonicalize() + .map_err(|_| err_msg("failed to canonicalize the path")) + }) .map(|value| value.clone())?; Action::Exec(program) } @@ -47,7 +52,8 @@ impl Handler { let config = config.clone(); Ok(Handler { config, action }) } - pub fn run(&self, input: JsonValue) -> Result { + + pub fn run(&self, temp_path: &PathBuf, input: JsonValue) -> Result { let config = { let mut buf: Vec = Vec::new(); { @@ -61,7 +67,9 @@ impl Handler { Action::Command(ref cmd) => { // TODO: allow some kind of simple variable replacement let output = Command::new("/bin/bash") + .current_dir(&temp_path) .env("DIP_ROOT", "lol") + .env("DIP_WORKDIR", temp_path) .arg("-c") .arg(cmd) .output()?; @@ -79,7 +87,9 @@ impl Handler { } Action::Exec(ref path) => { let mut child = Command::new(&path) + .current_dir(&temp_path) .env("DIP_ROOT", "") + .env("DIP_WORKDIR", temp_path) .arg("--config") .arg(config) .stdin(Stdio::piped()) @@ -108,11 +118,12 @@ impl Handler { output } }; + let stdout = String::from_utf8(output.stdout).unwrap_or_else(|_| String::new()); let stderr = String::from_utf8(output.stderr).unwrap_or_else(|_| String::new()); Ok(json!({ - "stdout": stdout, - "stderr": stderr, - })) + "stdout": stdout, + "stderr": stderr, + })) } } diff --git a/src/lib.rs b/src/lib.rs index 721b09d..047a6aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ extern crate failure; extern crate futures; extern crate hyper; +extern crate mktemp; extern crate serde; #[macro_use] extern crate serde_json; diff --git a/src/service.rs b/src/service.rs index b5ccd2d..47d36d7 100644 --- a/src/service.rs +++ b/src/service.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use futures::{future, Future, Stream}; use hyper::{Body, Error, Request, Response, StatusCode}; +use mktemp::Temp; use {HOOKS, URIPATTERN}; @@ -51,26 +52,33 @@ pub fn dip_service(req: Request) -> Box, Erro "method": method, }); let hooks = HOOKS.lock().unwrap(); - let hook = hooks.get(&name).unwrap(); - let (code, msg) = hook.iter() - .fold(Ok(req_obj), |prev, handler| { - prev.and_then(|val| handler.run(val)) - }) - .map(|res| { - ( - StatusCode::ACCEPTED, - format!( - "stdout:\n{}\n\nstderr:\n{}", - res.get("stdout").and_then(|v| v.as_str()).unwrap_or(""), - res.get("stderr").and_then(|v| v.as_str()).unwrap_or(""), - ), - ) - }) - .unwrap_or_else(|err| (StatusCode::BAD_REQUEST, format!("Error: {}", err))); - Response::builder() - .status(code) - .body(Body::from(msg)) - .unwrap_or_else(|err| Response::new(Body::from(format!("{}", err)))) + { + let mut temp_dir = Temp::new_dir().unwrap(); + let temp_path = temp_dir.to_path_buf(); + assert!(temp_path.exists()); + + let hook = hooks.get(&name).unwrap(); + let (code, msg) = hook.iter() + .fold(Ok(req_obj), |prev, handler| { + prev.and_then(|val| handler.run(&temp_path, val)) + }) + .map(|res| { + ( + StatusCode::ACCEPTED, + format!( + "stdout:\n{}\n\nstderr:\n{}", + res.get("stdout").and_then(|v| v.as_str()).unwrap_or(""), + res.get("stderr").and_then(|v| v.as_str()).unwrap_or(""), + ), + ) + }) + .unwrap_or_else(|err| (StatusCode::BAD_REQUEST, format!("Error: {:?}", err))); + temp_dir.release(); + Response::builder() + .status(code) + .body(Body::from(msg)) + .unwrap_or_else(|err| Response::new(Body::from(format!("{}", err)))) + } })) }