Pass ownership of header map to get_headers_to_sign (#10)

This commit is contained in:
Daniel Valdivia 2021-02-08 10:48:59 -08:00 committed by GitHub
parent 8aa4d412ff
commit db45f6865f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -18,7 +18,7 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use hyper::header::{ use hyper::header::{
HeaderMap, HeaderName, HeaderValue, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, USER_AGENT,
}; };
use log::debug; use log::debug;
use ring::{digest, hmac}; use ring::{digest, hmac};
@ -40,18 +40,18 @@ fn mk_scope(t: &Tm, r: &minio::Region) -> String {
format!("{}/{}/s3/aws4_request", scope_time, r.to_string()) format!("{}/{}/s3/aws4_request", scope_time, r.to_string())
} }
// Returns list of SORTED headers that will be signed. TODO: verify // Returns list of SORTED headers that will be signed.
// that input headermap contains only ASCII valued headers // TODO: verify that input headermap contains only ASCII valued headers
fn get_headers_to_sign(h: &HeaderMap) -> Vec<(String, String)> { fn get_headers_to_sign(h: HeaderMap) -> Vec<(String, String)> {
let mut ignored_hdrs: HashSet<HeaderName> = HashSet::new(); let ignored_hdrs: HashSet<HeaderName> = vec![
ignored_hdrs.insert(AUTHORIZATION); AUTHORIZATION,
ignored_hdrs.insert(CONTENT_LENGTH); CONTENT_LENGTH,
ignored_hdrs.insert(CONTENT_TYPE); CONTENT_TYPE,
ignored_hdrs.insert(USER_AGENT); USER_AGENT].into_iter().collect();
let mut res: Vec<(String, String)> = h let mut res: Vec<(String, String)> = h
.iter() .iter()
.map(|(x, y)| (x.clone(), y.clone())) .filter(|(x, _)| !ignored_hdrs.contains(*x))
.filter(|(x, _)| !ignored_hdrs.contains(x))
.map(|(x, y)| { .map(|(x, y)| {
( (
x.as_str().to_string(), x.as_str().to_string(),
@ -59,8 +59,7 @@ fn get_headers_to_sign(h: &HeaderMap) -> Vec<(String, String)> {
.expect("Unexpected non-ASCII header value!") .expect("Unexpected non-ASCII header value!")
.to_string(), .to_string(),
) )
}) }).collect();
.collect();
res.sort(); res.sort();
res res
} }
@ -164,30 +163,30 @@ fn compute_sign(str_to_sign: &str, key: &Vec<u8>) -> String {
} }
pub fn sign_v4( pub fn sign_v4(
r: &minio::S3Req, request: &minio::S3Req,
creds: Option<minio::Credentials>, credentials: Option<minio::Credentials>,
region: Region, region: Region,
) -> Vec<(HeaderName, HeaderValue)> { ) -> Vec<(HeaderName, HeaderValue)> {
creds.map_or(Vec::new(), |creds| { credentials.map_or(Vec::new(), |creds| {
let scope = mk_scope(&r.ts, &region); let scope = mk_scope(&request.ts, &region);
let date_hdr = ( let date_hdr = (
HeaderName::from_static("x-amz-date"), HeaderName::from_static("x-amz-date"),
HeaderValue::from_str(&aws_format_time(&r.ts)).unwrap(), HeaderValue::from_str(&aws_format_time(&request.ts)).unwrap(),
); );
let mut hmap = r.headers.clone(); let mut hmap = request.headers.clone();
hmap.insert(date_hdr.0.clone(), date_hdr.1.clone()); hmap.insert(date_hdr.0.clone(), date_hdr.1.clone());
let hs = get_headers_to_sign(&hmap); let headers = get_headers_to_sign(hmap);
let signed_hdrs_str: String = hs let signed_hdrs_str: String = headers
.iter() .iter()
.map(|(x, _)| x.clone()) .map(|(x, _)| x.clone())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(";"); .join(";");
let cr = get_canonical_request(r, &hs, &signed_hdrs_str); let cr = get_canonical_request(request, &headers, &signed_hdrs_str);
debug!("canonicalreq: {}", cr); debug!("canonicalreq: {}", cr);
let s2s = string_to_sign(&r.ts, &scope, &cr); let s2s = string_to_sign(&request.ts, &scope, &cr);
debug!("s2s: {}", s2s); debug!("s2s: {}", s2s);
let skey = get_signing_key(&r.ts, &region.to_string(), &creds.secret_key); let skey = get_signing_key(&request.ts, &region.to_string(), &creds.secret_key);
debug!("skey: {:?}", skey); debug!("skey: {:?}", skey);
let signature = compute_sign(&s2s, &skey); let signature = compute_sign(&s2s, &skey);
debug!("sign: {}", signature); debug!("sign: {}", signature);
@ -221,4 +220,19 @@ mod sign_tests {
"key1=val1&key1=val2&key2=val3&key2=" "key1=val1&key1=val2&key2=val3&key2="
); );
} }
#[test]
fn headers_to_sign_remove_ignored_and_sort() {
let mut map = HeaderMap::new();
map.insert(AUTHORIZATION, "hello".parse().unwrap());
map.insert(CONTENT_LENGTH, "123".parse().unwrap());
map.insert("second", "123".parse().unwrap());
map.insert("first", "123".parse().unwrap());
assert_eq!(
get_headers_to_sign(map),
vec![("first".parse().unwrap(), "123".parse().unwrap()),
("second".parse().unwrap(), "123".parse().unwrap())]
);
}
} }