diff --git a/Cargo.toml b/Cargo.toml index d1c39726..808f1c85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,35 +24,35 @@ reqwest_request = ["dep:reqwest"] # services that reqsign supports services-all = [ - "services-aliyun", - "services-aws", - "services-azblob", - "services-google", - "services-huaweicloud", - "services-oracle", - "services-tencent", + "services-aliyun", + "services-aws", + "services-azblob", + "services-google", + "services-huaweicloud", + "services-oracle", + "services-tencent", ] services-aliyun = [ - "dep:reqwest", - "dep:serde", - "dep:serde_json", - "dep:once_cell", + "dep:reqwest", + "dep:serde", + "dep:serde_json", + "dep:once_cell", ] services-aws = [ - "dep:reqwest", - "dep:serde", - "dep:serde_json", - "dep:quick-xml", - "dep:rust-ini", + "dep:reqwest", + "dep:serde", + "dep:serde_json", + "dep:quick-xml", + "dep:rust-ini", ] services-azblob = ["dep:serde", "dep:serde_json", "dep:reqwest"] services-google = [ - "dep:reqwest", - "dep:serde", - "dep:serde_json", - "dep:jsonwebtoken", - "dep:rsa", + "dep:reqwest", + "dep:serde", + "dep:serde_json", + "dep:jsonwebtoken", + "dep:rsa", ] services-huaweicloud = ["dep:serde", "dep:serde_json", "dep:once_cell"] services-oracle = ["dep:reqwest", "dep:rsa", "dep:toml", "dep:serde"] @@ -66,20 +66,20 @@ name = "aws" anyhow = "1" async-trait = "0.1" base64 = "0.22" -chrono = "0.4.24" +chrono = "0.4.35" form_urlencoded = "1" hex = "0.4" hmac = "0.12" -http = "0.2" +http = "1.1" jsonwebtoken = { version = "9.2", optional = true } log = "0.4" once_cell = { version = "1", optional = true } percent-encoding = "2" quick-xml = { version = "0.31", features = ["serialize"], optional = true } rand = "0.8.5" -reqwest = { version = "0.11", default-features = false, optional = true } +reqwest = { version = "0.12", default-features = false, optional = true } rsa = { version = "0.9.2", features = ["pkcs5", "sha2"], optional = true } -rust-ini = { version = "0.20", optional = true } +rust-ini = { version = "0.21", optional = true } serde = { version = "1", features = ["derive"], optional = true } serde_json = { version = "1", optional = true } sha1 = "0.10" @@ -95,13 +95,16 @@ getrandom = { version = "0.2", features = ["js"] } tokio = { version = "1", optional = true } [dev-dependencies] -aws-sigv4 = "0.56" +aws-credential-types = "1.1.8" +aws-sigv4 = "1.2.0" criterion = { version = "0.5", features = ["async_tokio", "html_reports"] } dotenv = "0.15" env_logger = "0.11" +macro_rules_attribute = "0.2.0" once_cell = "1" pretty_assertions = "1.3" -reqwest = { version = "0.11", features = ["blocking", "json"] } +reqwest = { version = "0.12", features = ["blocking", "json"] } temp-env = "0.3" tempfile = "3.8" +test-case = "3.3.1" tokio = { version = "1", features = ["full"] } diff --git a/benches/aws.rs b/benches/aws.rs index f0536cc2..2262b9f1 100644 --- a/benches/aws.rs +++ b/benches/aws.rs @@ -5,7 +5,7 @@ use aws_sigv4::http_request::PercentEncodingMode; use aws_sigv4::http_request::SignableBody; use aws_sigv4::http_request::SignableRequest; use aws_sigv4::http_request::SigningSettings; -use aws_sigv4::SigningParams; +use aws_sigv4::sign::v4::SigningParams; use criterion::criterion_group; use criterion::criterion_main; use criterion::Criterion; @@ -43,30 +43,47 @@ pub fn bench(c: &mut Criterion) { ss.percent_encoding_mode = PercentEncodingMode::Single; ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; + let credentials = aws_credential_types::Credentials::new( + "access_key_id".to_string(), + "secret_access_key".to_string(), + None, + None, + "test", + ) + .into(); + let sp = SigningParams::builder() - .access_key("access_key_id") - .secret_key("secret_access_key") + .identity(&credentials) .region("test") - .service_name("s3") + .name("s3") .time(SystemTime::now()) .settings(ss) .build() - .expect("signing params must be valid"); + .expect("signing params must be valid") + .into(); - b.iter(|| { - let mut req = http::Request::new(""); - *req.method_mut() = http::Method::GET; - *req.uri_mut() = "http://127.0.0.1:9000/hello" - .parse() - .expect("url must be valid"); + let mut req = http::Request::new(""); + *req.method_mut() = http::Method::GET; + *req.uri_mut() = "http://127.0.0.1:9000/hello" + .parse() + .expect("url must be valid"); + let method = req.method().as_str(); + let uri = req.uri().to_string(); + let headers = req + .headers() + .iter() + .map(|(k, v)| (k.as_str(), std::str::from_utf8(v.as_bytes()).unwrap())) + .collect::>(); + b.iter(|| { let _ = aws_sigv4::http_request::sign( SignableRequest::new( - req.method(), - req.uri(), - req.headers(), + method, + uri.as_str(), + headers.clone().into_iter(), SignableBody::UnsignedPayload, - ), + ) + .unwrap(), &sp, ) .expect("signing must succeed"); diff --git a/src/aliyun/credential.rs b/src/aliyun/credential.rs index dc40e416..3efebbac 100644 --- a/src/aliyun/credential.rs +++ b/src/aliyun/credential.rs @@ -39,7 +39,7 @@ impl Credential { // Take 120s as buffer to avoid edge cases. if let Some(valid) = self .expires_in - .map(|v| v > now() + chrono::Duration::minutes(2)) + .map(|v| v > now() + chrono::TimeDelta::try_minutes(2).expect("in bounds")) { return valid; } @@ -115,7 +115,7 @@ impl Loader { security_token: self.config.security_token.clone(), // Set expires_in to 10 minutes to enforce re-read // from file. - expires_in: Some(now() + chrono::Duration::minutes(10)), + expires_in: Some(now() + chrono::TimeDelta::try_minutes(10).expect("in bounds")), })) } else { Ok(None) diff --git a/src/aliyun/oss.rs b/src/aliyun/oss.rs index dda898dd..1f92558b 100644 --- a/src/aliyun/oss.rs +++ b/src/aliyun/oss.rs @@ -67,7 +67,7 @@ impl Signer { ctx.query_push("OSSAccessKeyId", &cred.access_key_id); ctx.query_push( "Expires", - (now + chrono::Duration::from_std(expire).unwrap()) + (now + chrono::TimeDelta::from_std(expire).unwrap()) .timestamp() .to_string(), ); @@ -135,7 +135,7 @@ fn string_to_sign( writeln!( &mut s, "{}", - (now + chrono::Duration::from_std(expires).unwrap()).timestamp() + (now + chrono::TimeDelta::from_std(expires).unwrap()).timestamp() )?; } } diff --git a/src/aws/credential.rs b/src/aws/credential.rs index 2cf9f0a9..62c30572 100644 --- a/src/aws/credential.rs +++ b/src/aws/credential.rs @@ -48,7 +48,7 @@ impl Credential { // Take 120s as buffer to avoid edge cases. if let Some(valid) = self .expires_in - .map(|v| v > now() + chrono::Duration::minutes(2)) + .map(|v| v > now() + chrono::TimeDelta::try_minutes(2).expect("in bounds")) { return valid; } @@ -159,7 +159,7 @@ impl DefaultLoader { session_token: self.config.session_token.clone(), // Set expires_in to 10 minutes to enforce re-read // from file. - expires_in: Some(now() + chrono::Duration::minutes(10)), + expires_in: Some(now() + chrono::TimeDelta::try_minutes(10).expect("in bounds")), })) } else { Ok(None) @@ -356,7 +356,8 @@ impl IMDSv2Loader { } let ec2_token = resp.text().await?; // Set expires_in to 10 minutes to enforce re-read. - let expires_in = now() + chrono::Duration::seconds(21600) - chrono::Duration::seconds(600); + let expires_in = now() + chrono::TimeDelta::try_seconds(21600).expect("in bounds") + - chrono::TimeDelta::try_seconds(600).expect("in bounds"); { *self.token.lock().expect("lock poisoned") = (ec2_token.clone(), expires_in); diff --git a/src/aws/v4.rs b/src/aws/v4.rs index 9198f246..97c79289 100644 --- a/src/aws/v4.rs +++ b/src/aws/v4.rs @@ -381,14 +381,16 @@ mod tests { use std::time::SystemTime; use anyhow::Result; + use aws_credential_types::Credentials; use aws_sigv4::http_request::PayloadChecksumKind; use aws_sigv4::http_request::PercentEncodingMode; use aws_sigv4::http_request::SignableBody; use aws_sigv4::http_request::SignableRequest; use aws_sigv4::http_request::SignatureLocation; use aws_sigv4::http_request::SigningSettings; - use aws_sigv4::SigningParams; + use aws_sigv4::sign::v4; use http::header; + use macro_rules_attribute::apply; use reqwest::Client; use super::super::AwsDefaultLoader; @@ -519,17 +521,18 @@ mod tests { req } - fn test_cases() -> &'static [fn() -> http::Request<&'static str>] { - &[ - test_get_request, - test_get_request_with_sse, - test_get_request_with_query, - test_get_request_virtual_host, - test_get_request_with_query_virtual_host, - test_put_request, - test_put_request_virtual_host, - test_put_request_with_body_digest, - ] + macro_rules! test_cases { + ($($tt:tt)*) => { + #[test_case::test_case(test_get_request)] + #[test_case::test_case(test_get_request_with_sse)] + #[test_case::test_case(test_get_request_with_query)] + #[test_case::test_case(test_get_request_virtual_host)] + #[test_case::test_case(test_get_request_with_query_virtual_host)] + #[test_case::test_case(test_put_request)] + #[test_case::test_case(test_put_request_virtual_host)] + #[test_case::test_case(test_put_request_with_body_digest)] + $($tt)* + }; } fn compare_request(name: &str, l: &http::Request<&str>, r: &http::Request<&str>) { @@ -567,271 +570,324 @@ mod tests { assert_eq!(format_query(l), format_query(r), "{name} query mismatch"); } + #[apply(test_cases)] #[tokio::test] - async fn test_calculate() -> Result<()> { + async fn test_calculate(req_fn: fn() -> http::Request<&'static str>) -> Result<()> { let _ = env_logger::builder().is_test(true).try_init(); - for req_fn in test_cases() { - let mut req = req_fn(); - let name = format!( - "{} {} {:?}", - req.method(), - req.uri().path(), - req.uri().query(), - ); - let now = now(); - - let mut ss = SigningSettings::default(); - ss.percent_encoding_mode = PercentEncodingMode::Double; - ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; - - let sp = SigningParams::builder() - .access_key("access_key_id") - .secret_key("secret_access_key") - .region("test") - .service_name("s3") - .time(SystemTime::from(now)) - .settings(ss) - .build() - .expect("signing params must be valid"); - - let mut body = SignableBody::UnsignedPayload; - if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { - body = SignableBody::Bytes(req.body().as_bytes()); - } + let mut req = req_fn(); + let name = format!( + "{} {} {:?}", + req.method(), + req.uri().path(), + req.uri().query(), + ); + let now = now(); + + let mut ss = SigningSettings::default(); + ss.percent_encoding_mode = PercentEncodingMode::Double; + ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; + let id = Credentials::new( + "access_key_id", + "secret_access_key", + None, + None, + "hardcoded-credentials", + ) + .into(); + let sp = v4::SigningParams::builder() + .identity(&id) + .region("test") + .name("s3") + .time(SystemTime::from(now)) + .settings(ss) + .build() + .expect("signing params must be valid"); + + let mut body = SignableBody::UnsignedPayload; + if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { + body = SignableBody::Bytes(req.body().as_bytes()); + } - let output = aws_sigv4::http_request::sign( - SignableRequest::new(req.method(), req.uri(), req.headers(), body), - &sp, + let output = aws_sigv4::http_request::sign( + SignableRequest::new( + req.method().as_str(), + req.uri().to_string(), + req.headers() + .iter() + .map(|(k, v)| (k.as_str(), std::str::from_utf8(v.as_bytes()).unwrap())), + body, ) - .expect("signing must succeed"); - let (aws_sig, _) = output.into_parts(); - aws_sig.apply_to_request(&mut req); - let expected_req = req; - - let mut req = req_fn(); - - let loader = AwsDefaultLoader::new( - Client::new(), - AwsConfig { - access_key_id: Some("access_key_id".to_string()), - secret_access_key: Some("secret_access_key".to_string()), - ..Default::default() - }, - ); - let cred = loader.load().await?.unwrap(); + .unwrap(), + &sp.into(), + ) + .expect("signing must succeed"); + let (aws_sig, _) = output.into_parts(); + aws_sig.apply_to_request_http1x(&mut req); + let expected_req = req; + + let mut req = req_fn(); + + let loader = AwsDefaultLoader::new( + Client::new(), + AwsConfig { + access_key_id: Some("access_key_id".to_string()), + secret_access_key: Some("secret_access_key".to_string()), + ..Default::default() + }, + ); + let cred = loader.load().await?.unwrap(); - let signer = Signer::new("s3", "test").time(now); - signer.sign(&mut req, &cred).expect("must apply success"); + let signer = Signer::new("s3", "test").time(now); + signer.sign(&mut req, &cred).expect("must apply success"); - let actual_req = req; + let actual_req = req; - compare_request(&name, &expected_req, &actual_req); - } + compare_request(&name, &expected_req, &actual_req); Ok(()) } + #[apply(test_cases)] #[tokio::test] - async fn test_calculate_in_query() -> Result<()> { + async fn test_calculate_in_query(req_fn: fn() -> http::Request<&'static str>) -> Result<()> { let _ = env_logger::builder().is_test(true).try_init(); - for req_fn in test_cases() { - let mut req = req_fn(); - let name = format!( - "{} {} {:?}", - req.method(), - req.uri().path(), - req.uri().query(), - ); - let now = now(); - - let mut ss = SigningSettings::default(); - ss.percent_encoding_mode = PercentEncodingMode::Double; - ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; - ss.signature_location = SignatureLocation::QueryParams; - ss.expires_in = Some(std::time::Duration::from_secs(3600)); - - let sp = SigningParams::builder() - .access_key("access_key_id") - .secret_key("secret_access_key") - .region("test") - .service_name("s3") - .time(SystemTime::from(now)) - .settings(ss) - .build() - .expect("signing params must be valid"); - - let mut body = SignableBody::UnsignedPayload; - if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { - body = SignableBody::Bytes(req.body().as_bytes()); - } + let mut req = req_fn(); + let name = format!( + "{} {} {:?}", + req.method(), + req.uri().path(), + req.uri().query(), + ); + let now = now(); + + let mut ss = SigningSettings::default(); + ss.percent_encoding_mode = PercentEncodingMode::Double; + ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; + ss.signature_location = SignatureLocation::QueryParams; + ss.expires_in = Some(std::time::Duration::from_secs(3600)); + let id = Credentials::new( + "access_key_id", + "secret_access_key", + None, + None, + "hardcoded-credentials", + ) + .into(); + let sp = v4::SigningParams::builder() + .identity(&id) + .region("test") + .name("s3") + .time(SystemTime::from(now)) + .settings(ss) + .build() + .expect("signing params must be valid"); + + let mut body = SignableBody::UnsignedPayload; + if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { + body = SignableBody::Bytes(req.body().as_bytes()); + } - let output = aws_sigv4::http_request::sign( - SignableRequest::new(req.method(), req.uri(), req.headers(), body), - &sp, + let output = aws_sigv4::http_request::sign( + SignableRequest::new( + req.method().as_str(), + req.uri().to_string(), + req.headers() + .iter() + .map(|(k, v)| (k.as_str(), std::str::from_utf8(v.as_bytes()).unwrap())), + body, ) - .expect("signing must succeed"); - let (aws_sig, _) = output.into_parts(); - aws_sig.apply_to_request(&mut req); - let expected_req = req; - - let mut req = req_fn(); - - let loader = AwsDefaultLoader::new( - Client::new(), - AwsConfig { - access_key_id: Some("access_key_id".to_string()), - secret_access_key: Some("secret_access_key".to_string()), - ..Default::default() - }, - ); - let cred = loader.load().await?.unwrap(); + .unwrap(), + &sp.into(), + ) + .expect("signing must succeed"); + let (aws_sig, _) = output.into_parts(); + aws_sig.apply_to_request_http1x(&mut req); + let expected_req = req; + + let mut req = req_fn(); + + let loader = AwsDefaultLoader::new( + Client::new(), + AwsConfig { + access_key_id: Some("access_key_id".to_string()), + secret_access_key: Some("secret_access_key".to_string()), + ..Default::default() + }, + ); + let cred = loader.load().await?.unwrap(); - let signer = Signer::new("s3", "test").time(now); + let signer = Signer::new("s3", "test").time(now); - signer.sign_query(&mut req, Duration::from_secs(3600), &cred)?; - let actual_req = req; + signer.sign_query(&mut req, Duration::from_secs(3600), &cred)?; + let actual_req = req; - compare_request(&name, &expected_req, &actual_req); - } + compare_request(&name, &expected_req, &actual_req); Ok(()) } + #[apply(test_cases)] #[tokio::test] - async fn test_calculate_with_token() -> Result<()> { + async fn test_calculate_with_token(req_fn: fn() -> http::Request<&'static str>) -> Result<()> { let _ = env_logger::builder().is_test(true).try_init(); - for req_fn in test_cases() { - let mut req = req_fn(); - let name = format!( - "{} {} {:?}", - req.method(), - req.uri().path(), - req.uri().query(), - ); - let now = now(); - - let mut ss = SigningSettings::default(); - ss.percent_encoding_mode = PercentEncodingMode::Double; - ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; - - let sp = SigningParams::builder() - .access_key("access_key_id") - .secret_key("secret_access_key") - .region("test") - .security_token("security_token") - .service_name("s3") - .time(SystemTime::from(now)) - .settings(ss) - .build() - .expect("signing params must be valid"); - - let mut body = SignableBody::UnsignedPayload; - if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { - body = SignableBody::Bytes(req.body().as_bytes()); - } + let mut req = req_fn(); + let name = format!( + "{} {} {:?}", + req.method(), + req.uri().path(), + req.uri().query(), + ); + let now = now(); + + let mut ss = SigningSettings::default(); + ss.percent_encoding_mode = PercentEncodingMode::Double; + ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; + let id = Credentials::new( + "access_key_id", + "secret_access_key", + Some("security_token".to_string()), + None, + "hardcoded-credentials", + ) + .into(); + let sp = v4::SigningParams::builder() + .identity(&id) + .region("test") + .name("s3") + .time(SystemTime::from(now)) + .settings(ss) + .build() + .expect("signing params must be valid"); + + let mut body = SignableBody::UnsignedPayload; + if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { + body = SignableBody::Bytes(req.body().as_bytes()); + } - let output = aws_sigv4::http_request::sign( - SignableRequest::new(req.method(), req.uri(), req.headers(), body), - &sp, + let output = aws_sigv4::http_request::sign( + SignableRequest::new( + req.method().as_str(), + req.uri().to_string(), + req.headers() + .iter() + .map(|(k, v)| (k.as_str(), std::str::from_utf8(v.as_bytes()).unwrap())), + body, ) - .expect("signing must succeed"); - let (aws_sig, _) = output.into_parts(); - aws_sig.apply_to_request(&mut req); - let expected_req = req; - - let mut req = req_fn(); - - let loader = AwsDefaultLoader::new( - Client::new(), - AwsConfig { - access_key_id: Some("access_key_id".to_string()), - secret_access_key: Some("secret_access_key".to_string()), - session_token: Some("security_token".to_string()), - ..Default::default() - }, - ); - let cred = loader.load().await?.unwrap(); + .unwrap(), + &sp.into(), + ) + .expect("signing must succeed"); + let (aws_sig, _) = output.into_parts(); + aws_sig.apply_to_request_http1x(&mut req); + let expected_req = req; + + let mut req = req_fn(); + + let loader = AwsDefaultLoader::new( + Client::new(), + AwsConfig { + access_key_id: Some("access_key_id".to_string()), + secret_access_key: Some("secret_access_key".to_string()), + session_token: Some("security_token".to_string()), + ..Default::default() + }, + ); + let cred = loader.load().await?.unwrap(); - let signer = Signer::new("s3", "test").time(now); + let signer = Signer::new("s3", "test").time(now); - signer.sign(&mut req, &cred).expect("must apply success"); - let actual_req = req; + signer.sign(&mut req, &cred).expect("must apply success"); + let actual_req = req; - compare_request(&name, &expected_req, &actual_req); - } + compare_request(&name, &expected_req, &actual_req); Ok(()) } + #[apply(test_cases)] #[tokio::test] - async fn test_calculate_with_token_in_query() -> Result<()> { + async fn test_calculate_with_token_in_query( + req_fn: fn() -> http::Request<&'static str>, + ) -> Result<()> { let _ = env_logger::builder().is_test(true).try_init(); - for req_fn in test_cases() { - let mut req = req_fn(); - let name = format!( - "{} {} {:?}", - req.method(), - req.uri().path(), - req.uri().query(), - ); - let now = now(); - - let mut ss = SigningSettings::default(); - ss.percent_encoding_mode = PercentEncodingMode::Double; - ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; - ss.signature_location = SignatureLocation::QueryParams; - ss.expires_in = Some(std::time::Duration::from_secs(3600)); - - let sp = SigningParams::builder() - .access_key("access_key_id") - .secret_key("secret_access_key") - .region("test") - .security_token("security_token") - .service_name("s3") - .time(SystemTime::from(now)) - .settings(ss) - .build() - .expect("signing params must be valid"); - - let mut body = SignableBody::UnsignedPayload; - if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { - body = SignableBody::Bytes(req.body().as_bytes()); - } + let mut req = req_fn(); + let name = format!( + "{} {} {:?}", + req.method(), + req.uri().path(), + req.uri().query(), + ); + let now = now(); + + let mut ss = SigningSettings::default(); + ss.percent_encoding_mode = PercentEncodingMode::Double; + ss.payload_checksum_kind = PayloadChecksumKind::XAmzSha256; + ss.signature_location = SignatureLocation::QueryParams; + ss.expires_in = Some(std::time::Duration::from_secs(3600)); + let id = Credentials::new( + "access_key_id", + "secret_access_key", + Some("security_token".to_string()), + None, + "hardcoded-credentials", + ) + .into(); + let sp = v4::SigningParams::builder() + .identity(&id) + .region("test") + // .security_token("security_token") + .name("s3") + .time(SystemTime::from(now)) + .settings(ss) + .build() + .expect("signing params must be valid"); + + let mut body = SignableBody::UnsignedPayload; + if req.headers().get(X_AMZ_CONTENT_SHA_256).is_some() { + body = SignableBody::Bytes(req.body().as_bytes()); + } - let output = aws_sigv4::http_request::sign( - SignableRequest::new(req.method(), req.uri(), req.headers(), body), - &sp, + let output = aws_sigv4::http_request::sign( + SignableRequest::new( + req.method().as_str(), + req.uri().to_string(), + req.headers() + .iter() + .map(|(k, v)| (k.as_str(), std::str::from_utf8(v.as_bytes()).unwrap())), + body, ) - .expect("signing must succeed"); - let (aws_sig, _) = output.into_parts(); - aws_sig.apply_to_request(&mut req); - let expected_req = req; - - let mut req = req_fn(); - - let loader = AwsDefaultLoader::new( - Client::new(), - AwsConfig { - access_key_id: Some("access_key_id".to_string()), - secret_access_key: Some("secret_access_key".to_string()), - session_token: Some("security_token".to_string()), - ..Default::default() - }, - ); - let cred = loader.load().await?.unwrap(); + .unwrap(), + &sp.into(), + ) + .expect("signing must succeed"); + let (aws_sig, _) = output.into_parts(); + aws_sig.apply_to_request_http1x(&mut req); + let expected_req = req; + + let mut req = req_fn(); + + let loader = AwsDefaultLoader::new( + Client::new(), + AwsConfig { + access_key_id: Some("access_key_id".to_string()), + secret_access_key: Some("secret_access_key".to_string()), + session_token: Some("security_token".to_string()), + ..Default::default() + }, + ); + let cred = loader.load().await?.unwrap(); - let signer = Signer::new("s3", "test").time(now); - signer - .sign_query(&mut req, Duration::from_secs(3600), &cred) - .expect("must apply success"); - let actual_req = req; + let signer = Signer::new("s3", "test").time(now); + signer + .sign_query(&mut req, Duration::from_secs(3600), &cred) + .expect("must apply success"); + let actual_req = req; - compare_request(&name, &expected_req, &actual_req); - } + compare_request(&name, &expected_req, &actual_req); Ok(()) } diff --git a/src/azure/storage/sas/account_sas.rs b/src/azure/storage/sas/account_sas.rs index 0c05adcc..c1566d59 100644 --- a/src/azure/storage/sas/account_sas.rs +++ b/src/azure/storage/sas/account_sas.rs @@ -115,7 +115,7 @@ mod tests { #[test] fn test_can_generate_sas_token() { let key = hash::base64_encode("key".as_bytes()); - let expiry = test_time() + chrono::Duration::minutes(5); + let expiry = test_time() + chrono::TimeDelta::try_minutes(5).expect("in bounds"); let sign = AccountSharedAccessSignature::new("account".to_string(), key, expiry); let token_content = sign.token().expect("token decode failed"); let token = token_content diff --git a/src/azure/storage/signer.rs b/src/azure/storage/signer.rs index e8d2c1be..fbc2287c 100644 --- a/src/azure/storage/signer.rs +++ b/src/azure/storage/signer.rs @@ -81,7 +81,7 @@ impl Signer { let signer = account_sas::AccountSharedAccessSignature::new( ak.to_string(), sk.to_string(), - time::now() + chrono::Duration::from_std(d)?, + time::now() + chrono::TimeDelta::from_std(d)?, ); let signer_token = signer.token()?; signer_token.iter().for_each(|(k, v)| { diff --git a/src/google/token.rs b/src/google/token.rs index 52b285c6..151283b9 100644 --- a/src/google/token.rs +++ b/src/google/token.rs @@ -177,7 +177,10 @@ impl TokenLoader { /// Load token from different sources. pub async fn load(&self) -> Result> { match self.token.lock().expect("lock poisoned").clone() { - Some((token, expire_in)) if now() < expire_in - chrono::Duration::seconds(2 * 60) => { + Some((token, expire_in)) + if now() + < expire_in - chrono::TimeDelta::try_seconds(2 * 60).expect("in bounds") => + { return Ok(Some(token)) } _ => (), @@ -189,7 +192,8 @@ impl TokenLoader { return Ok(None); }; - let expire_in = now() + chrono::Duration::seconds(token.expires_in() as i64); + let expire_in = + now() + chrono::TimeDelta::try_seconds(token.expires_in() as i64).expect("in bounds"); let mut lock = self.token.lock().expect("lock poisoned"); *lock = Some((token.clone(), expire_in)); diff --git a/src/huaweicloud/obs/signer.rs b/src/huaweicloud/obs/signer.rs index 0663b0d2..bee71aa4 100644 --- a/src/huaweicloud/obs/signer.rs +++ b/src/huaweicloud/obs/signer.rs @@ -83,7 +83,7 @@ impl Signer { ctx.query_push("AccessKeyId", &cred.access_key_id); ctx.query_push( "Expires", - (now + chrono::Duration::from_std(expire).unwrap()) + (now + chrono::TimeDelta::from_std(expire).unwrap()) .timestamp() .to_string(), ); @@ -182,7 +182,7 @@ fn string_to_sign( writeln!( &mut s, "{}", - (now + chrono::Duration::from_std(expires).unwrap()).timestamp() + (now + chrono::TimeDelta::from_std(expires).unwrap()).timestamp() )?; } } diff --git a/src/oracle/credential.rs b/src/oracle/credential.rs index 08759cd3..0a035e01 100644 --- a/src/oracle/credential.rs +++ b/src/oracle/credential.rs @@ -84,7 +84,7 @@ impl Loader { fingerprint: config.fingerprint, // Set expires_in to 10 minutes to enforce re-read // from file. - expires_in: Some(now() + chrono::Duration::minutes(10)), + expires_in: Some(now() + chrono::TimeDelta::try_minutes(10).expect("in bounds")), })) } } diff --git a/src/tencent/cos.rs b/src/tencent/cos.rs index 4bffa766..20705ddc 100644 --- a/src/tencent/cos.rs +++ b/src/tencent/cos.rs @@ -124,7 +124,7 @@ fn build_signature( let key_time = format!( "{};{}", now.timestamp(), - (now + chrono::Duration::from_std(expires).unwrap()).timestamp() + (now + chrono::TimeDelta::from_std(expires).unwrap()).timestamp() ); let sign_key = hex_hmac_sha1(cred.secret_key.as_bytes(), key_time.as_bytes()); diff --git a/src/tencent/credential.rs b/src/tencent/credential.rs index edab9474..f98bb906 100644 --- a/src/tencent/credential.rs +++ b/src/tencent/credential.rs @@ -96,7 +96,7 @@ impl CredentialLoader { security_token: self.config.security_token.clone(), // Set expires_in to 10 minutes to enforce re-read // from file. - expires_in: Some(now() + chrono::Duration::minutes(10)), + expires_in: Some(now() + chrono::TimeDelta::try_minutes(10).expect("in bounds")), }; return Ok(Some(cred)); }