Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model result macro #14

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "chef"
version = "0.1.0"
version = "0.2.0"
authors = ["Thom May <[email protected]>"]
readme = "README.md"
description = "Models for Chef Server objects"
Expand All @@ -11,17 +11,23 @@ edition = "2018"
[dependencies]
chef_api = { version = "0.2", path = "chef_api" }
clippy = {version = "0", optional = true}
env_logger = "0.4"
env_logger = "0.10"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
log = "0.3"
log = "0.4"
chrono = "0.4"
failure = "0.1"

[dev-dependencies]
serde = { version = "1.0", features = ["derive"]}

[features]
default = []
dev = ["clippy"]

[workspace]
members = [ "chef_api" ]

[package.metadata.release]
publish = false
24 changes: 13 additions & 11 deletions chef_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ license = "Apache-2.0"
edition = "2018"

[dependencies]
time = "0.1"
log = "0.3"
rustc-serialize = "0.3"
time = "0.3"
log = "0.4"

futures = "0.1"
tokio-core = "0.1"
hyper = "0.11"
hyper-openssl = "0.5"
futures = "0.3"
tokio = { version = "1", features = [ "rt", "rt-multi-thread" ]}
hyper = { version = "0.14", features = [ "client", "http1" ]}
hyper-openssl = "0.9"

url = "1.6"
url = "2"
chrono = "0.4"
openssl = "0.10"
env_logger = "0.4"
env_logger = "0.10"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

failure = "0.1"

toml = "0.4"
dirs = "1.0"
toml = "0.7"
dirs = "5"
hyper-tls = "0.5.0"
base64 = "0.21.0"
itertools = "0.10.5"
16 changes: 3 additions & 13 deletions chef_api/src/api_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ use crate::credentials::Config;

use hyper::client::HttpConnector;
use hyper::Client as HyperClient;
use hyper_openssl::HttpsConnector;

use tokio_core::reactor::Core;
use hyper_tls::HttpsConnector;

use failure::Error;
use serde::ser::*;
use serde_json::Value;
use std::cell::RefCell;
use std::rc::Rc;

use crate::requests::*;
Expand All @@ -21,24 +18,17 @@ pub struct ApiClient {
pub config: Config,
/// The Hyper HTTP Client.
pub client: Rc<HyperClient<HttpsConnector<HttpConnector>>>,
/// The async core
pub core: Rc<RefCell<Core>>,
}

impl ApiClient {
/// Create a new ApiClient struct. It takes a `Config` type. Typically one would use
/// `from_credentials` rather than calling this directly.
pub fn new(config: Config) -> Result<Self, Error> {
let core = Core::new()?;
let handle = core.handle();

let client = HyperClient::configure()
.connector(HttpsConnector::new(4, &handle)?)
.build(&handle);
let https = HttpsConnector::new();
let client = HyperClient::builder().build(https);

Ok(Self {
config,
core: Rc::new(RefCell::new(core)),
client: Rc::new(client),
})
}
Expand Down
49 changes: 28 additions & 21 deletions chef_api/src/authentication/auth11.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::authentication::BASE64_AUTH;
use crate::http_headers::*;
use crate::utils::{expand_string, squeeze_path};
use base64::{engine::general_purpose, Engine as _};
use chrono::*;
use failure::Error;
use hyper::header::Headers;
use hyper::header::{HeaderMap, HeaderName, HeaderValue};
use itertools::Itertools;
use openssl::hash::{hash, MessageDigest};
use openssl::rsa::Padding;
use openssl::rsa::Rsa;
use rustc_serialize::base64::ToBase64;
use std::convert::TryFrom;
use std::fmt;

pub struct Auth11 {
Expand Down Expand Up @@ -59,20 +59,22 @@ impl Auth11 {

fn hashed_path(&self) -> Result<String, Error> {
debug!("Path is: {:?}", self.path);
let hash = hash(MessageDigest::sha1(), self.path.as_bytes())?.to_base64(BASE64_AUTH);
let hash = hash(MessageDigest::sha1(), self.path.as_bytes())?;
let hash = general_purpose::STANDARD.encode(hash);
Ok(hash)
}

fn content_hash(&self) -> Result<String, Error> {
let body = expand_string(&self.body);
let content = hash(MessageDigest::sha1(), body.as_bytes())?.to_base64(BASE64_AUTH);
let content = hash(MessageDigest::sha1(), body.as_bytes())?;
let content = general_purpose::STANDARD.encode(content);
debug!("{:?}", content);
Ok(content)
}

fn canonical_user_id(&self) -> Result<String, Error> {
hash(MessageDigest::sha1(), self.userid.as_bytes())
.and_then(|res| Ok(res.to_base64(BASE64_AUTH)))
.and_then(|res| Ok(general_purpose::STANDARD.encode(res)))
.map_err(|res| res.into())
}

Expand All @@ -99,22 +101,28 @@ impl Auth11 {

let mut hash: Vec<u8> = vec![0; key.size() as usize];
key.private_encrypt(cr, &mut hash, Padding::PKCS1)?;
Ok(hash.to_base64(BASE64_AUTH))
Ok(general_purpose::STANDARD.encode(hash))
}

pub fn build(self, headers: &mut Headers) -> Result<(), Error> {
pub fn build(self, headers: &mut HeaderMap) -> Result<(), Error> {
let hsh = self.content_hash()?;
headers.set(OpsContentHash(hsh));
headers.insert("X-Ops-Content-Hash", HeaderValue::from_str(&hsh)?);

headers.set(OpsSign(String::from("algorithm=sha1;version=1.1")));
headers.set(OpsTimestamp(self.date.clone()));
headers.set(OpsUserId(self.userid.clone()));
headers.insert(
"X-Ops-Sign",
HeaderValue::from_str("algorithm=sha1;version=1.1")?,
);
headers.insert("X-Ops-Timestamp", HeaderValue::from_str(&self.date)?);
headers.insert("X-Ops-Userid", HeaderValue::from_str(&self.userid)?);

let enc = self.encrypted_request()?;
let mut i = 1;
for h in enc.split('\n') {
for h in &enc.bytes().chunks(60) {
let key = format!("X-Ops-Authorization-{}", i);
headers.set_raw(key, vec![h.as_bytes().to_vec()]);
headers.insert(
HeaderName::try_from(key)?,
HeaderValue::from_bytes(&h.collect::<Vec<_>>())?,
);
i += 1;
}
Ok(())
Expand Down Expand Up @@ -192,13 +200,12 @@ mod tests {
};
assert_eq!(
&auth.encrypted_request().unwrap(),
"UfZD9dRz6rFu6LbP5Mo1oNHcWYxpNIcUfFCffJS1FQa0GtfU/vkt3/O5HuCM\n\
1wIFl/U0f5faH9EWpXWY5NwKR031Myxcabw4t4ZLO69CIh/3qx1XnjcZvt2w\n\
c2R9bx/43IWA/r8w8Q6decuu0f6ZlNheJeJhaYPI8piX/aH+uHBH8zTACZu8\n\
vMnl5MF3/OIlsZc8cemq6eKYstp8a8KYq9OmkB5IXIX6qVMJHA6fRvQEB/7j\n\
281Q7oI/O+lE8AmVyBbwruPb7Mp6s4839eYiOdjbDwFjYtbS3XgAjrHlaD7W\n\
"UfZD9dRz6rFu6LbP5Mo1oNHcWYxpNIcUfFCffJS1FQa0GtfU/vkt3/O5HuCM\
1wIFl/U0f5faH9EWpXWY5NwKR031Myxcabw4t4ZLO69CIh/3qx1XnjcZvt2w\
c2R9bx/43IWA/r8w8Q6decuu0f6ZlNheJeJhaYPI8piX/aH+uHBH8zTACZu8\
vMnl5MF3/OIlsZc8cemq6eKYstp8a8KYq9OmkB5IXIX6qVMJHA6fRvQEB/7j\
281Q7oI/O+lE8AmVyBbwruPb7Mp6s4839eYiOdjbDwFjYtbS3XgAjrHlaD7W\
FDlbAG7H8Dmvo+wBxmtNkszhzbBnEYtuwQqT8nM/8A=="
)
}

}
48 changes: 27 additions & 21 deletions chef_api/src/authentication/auth13.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::authentication::BASE64_AUTH;
use crate::http_headers::*;
use crate::utils::{expand_string, squeeze_path};
use base64::{engine::general_purpose, Engine as _};
use chrono::*;
use failure::Error;
use hyper::header::Headers;
use hyper::header::{HeaderMap, HeaderName, HeaderValue};
use itertools::Itertools;
use openssl::hash::{hash, MessageDigest};
use openssl::pkey::PKey;
use openssl::sign::Signer;
use rustc_serialize::base64::ToBase64;
use std::convert::TryFrom;
use std::fmt;

pub struct Auth13 {
Expand Down Expand Up @@ -59,7 +59,8 @@ impl Auth13 {
fn content_hash(&self) -> Result<String, Error> {
let body = expand_string(&self.body);
debug!("Content body is: {:?}", body);
let content = hash(MessageDigest::sha256(), body.as_bytes())?.to_base64(BASE64_AUTH);
let content = hash(MessageDigest::sha256(), body.as_bytes())?;
let content = general_purpose::STANDARD.encode(content);
debug!("Content hash is: {:?}", content);
Ok(content)
}
Expand Down Expand Up @@ -89,23 +90,29 @@ impl Auth13 {
let mut signer = Signer::new(MessageDigest::sha256(), &key)?;
signer.update(cr).unwrap();
let result = signer.sign_to_vec()?;
let result = result.to_base64(BASE64_AUTH);
let result = general_purpose::STANDARD.encode(result);
debug!("base64 encoded result is {:?}", result);
Ok(result)
}

pub fn build(self, headers: &mut Headers) -> Result<(), Error> {
pub fn build(self, headers: &mut HeaderMap) -> Result<(), Error> {
let hsh = self.content_hash()?;
headers.set(OpsContentHash(hsh));
headers.set(OpsSign(String::from("algorithm=sha256;version=1.3")));
headers.set(OpsTimestamp(self.date.clone()));
headers.set(OpsUserId(self.userid.clone()));

headers.insert("X-Ops-Content-Hash", HeaderValue::from_str(&hsh)?);
headers.insert(
"X-Ops-Sign",
HeaderValue::from_str("algorithm=sha256;version=1.3")?,
);
headers.insert("X-Ops-Timestamp", HeaderValue::from_str(&self.date)?);
headers.insert("X-Ops-Userid", HeaderValue::from_str(&self.userid)?);

let enc = self.signed_request()?;
let mut i = 1;
for h in enc.split('\n') {
for h in &enc.bytes().chunks(60) {
let key = format!("X-Ops-Authorization-{}", i);
headers.set_raw(key, vec![h.as_bytes().to_vec()]);
let value = h.collect::<Vec<_>>();
let value = HeaderValue::from_bytes(&value)?;
headers.insert(HeaderName::try_from(key)?, value);
i += 1;
}
Ok(())
Expand All @@ -116,10 +123,10 @@ impl Auth13 {
mod tests {
use super::Auth13;

use base64::{engine::general_purpose, Engine as _};
use openssl::hash::MessageDigest;
use openssl::pkey::PKey;
use openssl::sign::Verifier;
use rustc_serialize::base64::FromBase64;
use std::fs::File;
use std::io::Read;

Expand Down Expand Up @@ -172,7 +179,7 @@ mod tests {
let sig = &auth.signed_request().unwrap();
let req = &auth.canonical_request().unwrap();

let sig_raw = sig.clone().from_base64().unwrap();
let sig_raw = general_purpose::STANDARD.decode(&sig).unwrap();
let mut key: Vec<u8> = vec![];
let mut fh = File::open(PRIVATE_KEY).unwrap();
fh.read_to_end(&mut key).unwrap();
Expand All @@ -184,13 +191,12 @@ mod tests {

assert_eq!(
sig,
"FZOmXAyOBAZQV/uw188iBljBJXOm+m8xQ/8KTGLkgGwZNcRFxk1m953XjE3W\n\
VGy1dFT76KeaNWmPCNtDmprfH2na5UZFtfLIKrPv7xm80V+lzEzTd9WBwsfP\n\
42dZ9N+V9I5SVfcL/lWrrlpdybfceJC5jOcP5tzfJXWUITwb6Z3Erg3DU3Uh\n\
H9h9E0qWlYGqmiNCVrBnpe6Si1gU/Jl+rXlRSNbLJ4GlArAPuL976iTYJTzE\n\
MmbLUIm3JRYi00Yb01IUCCKdI90vUq1HHNtlTEu93YZfQaJwRxXlGkCNwIJe\n\
"FZOmXAyOBAZQV/uw188iBljBJXOm+m8xQ/8KTGLkgGwZNcRFxk1m953XjE3W\
VGy1dFT76KeaNWmPCNtDmprfH2na5UZFtfLIKrPv7xm80V+lzEzTd9WBwsfP\
42dZ9N+V9I5SVfcL/lWrrlpdybfceJC5jOcP5tzfJXWUITwb6Z3Erg3DU3Uh\
H9h9E0qWlYGqmiNCVrBnpe6Si1gU/Jl+rXlRSNbLJ4GlArAPuL976iTYJTzE\
MmbLUIm3JRYi00Yb01IUCCKdI90vUq1HHNtlTEu93YZfQaJwRxXlGkCNwIJe\
fy49QzaCIEu1XiOx5Jn+4GmkrZch/RrK9VzQWXgs+w=="
)
}

}
9 changes: 0 additions & 9 deletions chef_api/src/authentication/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,2 @@
use rustc_serialize::base64::{CharacterSet, Config, Newline};

pub mod auth11;
pub mod auth13;

pub static BASE64_AUTH: Config = Config {
char_set: CharacterSet::Standard,
newline: Newline::LF,
pad: true,
line_length: Some(60),
};
4 changes: 2 additions & 2 deletions chef_api/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ pub enum ChefError {
display = "An error occurred attempting to parse the Chef Server URL: {}",
_0
)]
UriError(#[cause] hyper::error::UriError),
UriError(#[cause] hyper::Error),
#[fail(display = "An error occurred communicating to the Chef Server: {}", _0)]
HTTPError(#[cause] hyper::error::Error),
HTTPError(#[cause] hyper::Error),
#[fail(display = "An error occurred when using the API client: {}", _0)]
BorrowError(#[cause] std::cell::BorrowMutError),
#[fail(display = "Failed to parse credentials file: {}", _0)]
Expand Down
21 changes: 0 additions & 21 deletions chef_api/src/http_headers.rs

This file was deleted.

5 changes: 1 addition & 4 deletions chef_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,13 @@ extern crate failure;

extern crate chrono;
extern crate openssl;
extern crate rustc_serialize;
extern crate url;

extern crate futures;

#[macro_use]
extern crate hyper;
extern crate hyper_openssl;
extern crate tokio_core;
extern crate tokio;

#[macro_use]
extern crate log;
Expand All @@ -58,7 +56,6 @@ extern crate dirs;
pub use crate::errors::*;
pub mod authentication;
pub mod errors;
mod http_headers;
#[macro_use]
mod macros;
pub mod credentials;
Expand Down
Loading