dip/examples/github.rs

66 lines
1.7 KiB
Rust
Raw Normal View History

2018-08-16 01:31:15 +00:00
extern crate dip;
extern crate secstr;
extern crate serde_json;
extern crate hmac;
extern crate sha1;
#[macro_use]
extern crate serde_derive;
extern crate generic_array;
extern crate failure;
#[macro_use]
extern crate structopt;
2018-08-16 01:44:42 +00:00
use std::iter::FromIterator;
2018-08-16 01:31:15 +00:00
use std::io::{self, Read};
use std::collections::HashMap;
use secstr::*;
use hmac::{Mac,Hmac};
use sha1::Sha1;
use generic_array::GenericArray;
use failure::{err_msg, Error};
use structopt::StructOpt;
#[derive(StructOpt)]
struct Opt {
/// JSON input
#[structopt(short = "c", long = "config")]
pub config: String,
}
#[derive(Serialize, Deserialize)]
struct Config {
secret: String,
}
#[derive(Serialize, Deserialize)]
struct Payload {
body: String,
headers: HashMap<String, String>,
}
fn main() -> Result<(), Error> {
let args = Opt::from_args();
let config: Config = serde_json::from_str(&args.config)?;
let mut payload = String::new();
io::stdin().read_to_string(&mut payload)?;
let payload: Payload = serde_json::from_str(&payload)?;
2018-08-16 01:44:42 +00:00
println!("secret = {}", config.secret);
2018-08-16 01:31:15 +00:00
2018-08-16 01:44:42 +00:00
let secret = GenericArray::from_iter(config.secret.bytes());
let mut mac = Hmac::<Sha1>::new(&secret);
2018-08-16 01:31:15 +00:00
mac.input(payload.body.as_bytes());
let signature = mac.result().code().into_iter().map(|b| format!("{:02x}", b)).collect::<Vec<_>>().join("");
2018-08-16 01:44:42 +00:00
println!("sig = {}", signature);
2018-08-16 01:31:15 +00:00
2018-08-16 01:34:28 +00:00
let auth = payload.headers.get("X-Hub-Signature").ok_or(err_msg("Missing auth header"))?;
2018-08-16 01:31:15 +00:00
let left = SecStr::from(format!("sha1={}", signature));
let right = SecStr::from(auth.bytes().collect::<Vec<_>>());
2018-08-16 01:34:28 +00:00
assert!(left == right, "HMAC signature didn't match");
2018-08-16 01:31:15 +00:00
println!("{}", payload.body);
Ok(())
}