aboutsummaryrefslogtreecommitdiff
path: root/src/garage/tests
diff options
context:
space:
mode:
authorAlex <alex@adnab.me>2024-03-01 12:49:43 +0000
committerAlex <alex@adnab.me>2024-03-01 12:49:43 +0000
commit34086531a842199d6d998bd85d8f65429c4a351d (patch)
tree7bb4a770514e683db047434c0b6908f91b981f19 /src/garage/tests
parentf01883794e475f5dae3d2d4f621b020e1134fa47 (diff)
parent430d0be48c2c4bc789d0f1fd8ef35a34c88a300a (diff)
downloadgarage-34086531a842199d6d998bd85d8f65429c4a351d.tar.gz
garage-34086531a842199d6d998bd85d8f65429c4a351d.zip
Merge pull request 'Backport AWS signature verification refactoring and fixes to v0.8.x' (#744) from backport-735-v0.8.x into main-0.8.x
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/744
Diffstat (limited to 'src/garage/tests')
-rw-r--r--src/garage/tests/common/custom_requester.rs81
-rw-r--r--src/garage/tests/s3/streaming_signature.rs2
2 files changed, 59 insertions, 24 deletions
diff --git a/src/garage/tests/common/custom_requester.rs b/src/garage/tests/common/custom_requester.rs
index 4133bb8b..c931f6ef 100644
--- a/src/garage/tests/common/custom_requester.rs
+++ b/src/garage/tests/common/custom_requester.rs
@@ -1,11 +1,14 @@
#![allow(dead_code)]
use std::collections::HashMap;
-use std::convert::TryFrom;
+use std::convert::{TryFrom, TryInto};
use chrono::{offset::Utc, DateTime};
use hmac::{Hmac, Mac};
use hyper::client::HttpConnector;
+use hyper::header::{
+ HeaderMap, HeaderName, HeaderValue, AUTHORIZATION, CONTENT_ENCODING, CONTENT_LENGTH, HOST,
+};
use hyper::{Body, Client, Method, Request, Response, Uri};
use super::garage::{Instance, Key};
@@ -168,54 +171,85 @@ impl<'a> RequestBuilder<'a> {
.unwrap();
let streaming_signer = signer.clone();
- let mut all_headers = self.signed_headers.clone();
+ let mut all_headers = self
+ .signed_headers
+ .iter()
+ .map(|(k, v)| {
+ (
+ HeaderName::try_from(k).expect("invalid header name"),
+ HeaderValue::try_from(v).expect("invalid header value"),
+ )
+ })
+ .collect::<HeaderMap>();
let date = now.format(signature::LONG_DATETIME).to_string();
- all_headers.insert("x-amz-date".to_owned(), date);
- all_headers.insert("host".to_owned(), host);
+ all_headers.insert(
+ signature::payload::X_AMZ_DATE,
+ HeaderValue::from_str(&date).unwrap(),
+ );
+ all_headers.insert(HOST, HeaderValue::from_str(&host).unwrap());
let body_sha = match self.body_signature {
BodySignature::Unsigned => "UNSIGNED-PAYLOAD".to_owned(),
BodySignature::Classic => hex::encode(garage_util::data::sha256sum(&self.body)),
BodySignature::Streaming(size) => {
- all_headers.insert("content-encoding".to_owned(), "aws-chunked".to_owned());
all_headers.insert(
- "x-amz-decoded-content-length".to_owned(),
- self.body.len().to_string(),
+ CONTENT_ENCODING,
+ HeaderValue::from_str("aws-chunked").unwrap(),
+ );
+ all_headers.insert(
+ HeaderName::from_static("x-amz-decoded-content-length"),
+ HeaderValue::from_str(&self.body.len().to_string()).unwrap(),
);
// Get lenght of body by doing the conversion to a streaming body with an
// invalid signature (we don't know the seed) just to get its length. This
// is a pretty lazy and inefficient way to do it, but it's enought for test
// code.
all_headers.insert(
- "content-length".to_owned(),
+ CONTENT_LENGTH,
to_streaming_body(&self.body, size, String::new(), signer.clone(), now, "")
.len()
- .to_string(),
+ .to_string()
+ .try_into()
+ .unwrap(),
);
"STREAMING-AWS4-HMAC-SHA256-PAYLOAD".to_owned()
}
};
- all_headers.insert("x-amz-content-sha256".to_owned(), body_sha.clone());
+ all_headers.insert(
+ signature::payload::X_AMZ_CONTENT_SH256,
+ HeaderValue::from_str(&body_sha).unwrap(),
+ );
- let mut signed_headers = all_headers
+ let mut signed_headers = all_headers.keys().cloned().collect::<Vec<_>>();
+ signed_headers.sort_by(|h1, h2| h1.as_str().cmp(h2.as_str()));
+ let signed_headers_str = signed_headers
.iter()
- .map(|(k, _)| k.as_ref())
- .collect::<Vec<&str>>();
- signed_headers.sort();
- let signed_headers = signed_headers.join(";");
+ .map(ToString::to_string)
+ .collect::<Vec<_>>()
+ .join(";");
- all_headers.extend(self.unsigned_headers.clone());
+ all_headers.extend(self.unsigned_headers.iter().map(|(k, v)| {
+ (
+ HeaderName::try_from(k).expect("invalid header name"),
+ HeaderValue::try_from(v).expect("invalid header value"),
+ )
+ }));
+
+ let uri = Uri::try_from(&uri).unwrap();
+ let query = signature::payload::parse_query_map(&uri).unwrap();
let canonical_request = signature::payload::canonical_request(
self.service,
&self.method,
- &Uri::try_from(&uri).unwrap(),
+ uri.path(),
+ &query,
&all_headers,
&signed_headers,
&body_sha,
- );
+ )
+ .unwrap();
let string_to_sign = signature::payload::string_to_sign(&now, &scope, &canonical_request);
@@ -223,14 +257,15 @@ impl<'a> RequestBuilder<'a> {
let signature = hex::encode(signer.finalize().into_bytes());
let authorization = format!(
"AWS4-HMAC-SHA256 Credential={}/{},SignedHeaders={},Signature={}",
- self.requester.key.id, scope, signed_headers, signature
+ self.requester.key.id, scope, signed_headers_str, signature
+ );
+ all_headers.insert(
+ AUTHORIZATION,
+ HeaderValue::from_str(&authorization).unwrap(),
);
- all_headers.insert("authorization".to_owned(), authorization);
let mut request = Request::builder();
- for (k, v) in all_headers {
- request = request.header(k, v);
- }
+ *request.headers_mut().unwrap() = all_headers;
let body = if let BodySignature::Streaming(size) = self.body_signature {
to_streaming_body(&self.body, size, signature, streaming_signer, now, &scope)
diff --git a/src/garage/tests/s3/streaming_signature.rs b/src/garage/tests/s3/streaming_signature.rs
index b7a1acae..968f7189 100644
--- a/src/garage/tests/s3/streaming_signature.rs
+++ b/src/garage/tests/s3/streaming_signature.rs
@@ -26,7 +26,7 @@ async fn test_putobject_streaming() {
.builder(bucket.clone())
.method(Method::PUT)
.path(STD_KEY.to_owned())
- .unsigned_headers(headers)
+ .signed_headers(headers)
.vhost_style(true)
.body(vec![])
.body_signature(BodySignature::Streaming(10))