From 79d784c70040abcbc7e1d8e173fd98e6ae12abf9 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Fri, 29 Sep 2023 17:17:17 +0800 Subject: [PATCH] feat: updates --- Cargo.toml | 1 + src/lib.rs | 2 ++ src/main.rs | 28 +++++++++++++++-- src/util/mod.rs | 2 +- src/util/sign_algorithm.rs | 2 +- src/v4/aliyun_util.rs | 63 +++++++++++++++++++++++++------------- src/v4/mod.rs | 6 ++-- 7 files changed, 75 insertions(+), 29 deletions(-) create mode 100644 src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index b934c58..f3ec15a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,6 @@ hmac-sm3 = "0.1.0" rand = "0.8.5" sha1 = "0.10.5" sha256 = "1.4.0" +simpledateformat = "0.1.4" sm3 = "0.4.2" zeroize = "1.6.0" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a57c2dd --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +pub mod util; +pub mod v4; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f822d30..4625be0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,28 @@ -mod util; -mod v4; +use alibabacloud_openapi_signature::util::sign_algorithm::SignAlgorithm; +use alibabacloud_openapi_signature::v4::access_key::AccessKey; +use alibabacloud_openapi_signature::v4::aliyun_util::{add_common_headers, Request}; fn main() { - println!("Hello, world!"); + let mut request = Request { + version: "2012-12-31".to_string(), + region: Some("cn-hangzhou".to_string()), + product: "test".to_string(), + action: "DoAction".to_string(), + method: "POST".to_string(), + endpoint: "ecs.cn-hangzhou.aliyuncs.com".to_string(), + pathname: "/do-action".to_string(), + access_key: Some(AccessKey { + access_key_id: "AccessKeyId".to_string(), + security_token: None, + access_key_secret: "AccessKeySecret".to_string(), + }), + user_agent: "TetUa/1.0".to_string(), + sign_algorithm: SignAlgorithm::Sha256, + query: Default::default(), + headers: Default::default(), + stream: None, + }; + add_common_headers(&mut request); + + println!("{:#?}", request); } diff --git a/src/util/mod.rs b/src/util/mod.rs index f3c5bd9..99f7fa7 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,3 @@ pub(crate) mod common_util; pub(crate) mod map_util; -pub(crate) mod sign_algorithm; \ No newline at end of file +pub mod sign_algorithm; \ No newline at end of file diff --git a/src/util/sign_algorithm.rs b/src/util/sign_algorithm.rs index 3f496ef..6a90ce2 100644 --- a/src/util/sign_algorithm.rs +++ b/src/util/sign_algorithm.rs @@ -5,7 +5,7 @@ const ACS4_HMAC_SHA256: &str = "ACS4-HMAC-SHA256"; const ACS4_HMAC_SM3: &str = "ACS4-HMAC-SM3"; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub enum SignAlgorithm { /// SHA1 is used for Signatures before V4 Sha1, diff --git a/src/v4/aliyun_util.rs b/src/v4/aliyun_util.rs index b01c772..f408308 100644 --- a/src/v4/aliyun_util.rs +++ b/src/v4/aliyun_util.rs @@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicU64, Ordering}; use std::time::SystemTime; use rand::random; +use simpledateformat::fmt; use crate::util::common_util::{join_slices, percent_encode}; use crate::util::map_util::BTreeMapAddKv; @@ -12,9 +13,10 @@ use crate::v4::constant::{ALIYUN_V4, ALIYUN_V4_REQUEST, CONTENT_TYPE_APPLICATION const SEQ: AtomicU64 = AtomicU64::new(0); -struct Request { +#[derive(Debug)] +pub struct Request { pub version: String, - pub region: String, + pub region: Option, pub product: String, pub action: String, pub method: String, @@ -28,42 +30,48 @@ struct Request { pub stream: Option>, } -fn add_common_headers(header: &mut BTreeMap, request: &Request) { +pub fn add_common_headers(request: &mut Request) { let (ymd, date) = get_timestamp(); + let headers = &mut request.headers; let host = get_host(&request.endpoint); - header.insert_kv(HEADER_HOST, host); - header.insert_kv(HEADER_X_ASC_VERSION, &request.version); - header.insert_kv(HEADER_X_ASC_ACTION, &request.action); - header.insert_kv(HEADER_USER_AGENT, &request.user_agent); - header.insert_kv(HEADER_X_ASC_DATE, date); - header.insert_kv(HEADER_X_ASC_SIGNATURE_NONCE, get_nonce()); - header.insert_kv(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON); + headers.insert_kv(HEADER_HOST, host); + headers.insert_kv(HEADER_X_ASC_VERSION, &request.version); + headers.insert_kv(HEADER_X_ASC_ACTION, &request.action); + headers.insert_kv(HEADER_USER_AGENT, &request.user_agent); + headers.insert_kv(HEADER_X_ASC_DATE, date); + headers.insert_kv(HEADER_X_ASC_SIGNATURE_NONCE, get_nonce()); + headers.insert_kv(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON); let digest_request_payload = digest_request_body(&request.sign_algorithm, &request.stream); match &request.sign_algorithm { SignAlgorithm::Sha1 => panic!("SHA1 in V4 is NOT supported!"), SignAlgorithm::Sha256 => { - header.insert_kv(HEADER_X_ASC_CONTENT_SHA256, &digest_request_payload); + headers.insert_kv(HEADER_X_ASC_CONTENT_SHA256, &digest_request_payload); } SignAlgorithm::Sm3 => { - header.insert_kv(HEADER_X_ASC_CONTENT_SM3, &digest_request_payload); + headers.insert_kv(HEADER_X_ASC_CONTENT_SM3, &digest_request_payload); } } let query = BTreeMap::new(); if let Some(access_key) = &request.access_key { + headers.insert_kv(HEADER_X_ASC_ACCESS_KEY_ID, &access_key.access_key_id); if let Some(security_token) = &access_key.security_token { - header.insert_kv(HEADER_X_ASC_ACCESS_KEY_ID, &access_key.access_key_id); - header.insert_kv(HEADER_X_ASC_SECURITY_TOKEN, security_token); + headers.insert_kv(HEADER_X_ASC_SECURITY_TOKEN, security_token); } + let region = match &request.region { + None => get_region(&request.product, &request.endpoint), + Some(region) => region.to_string(), + }; + let signing_key = get_signing_key( &request.sign_algorithm, &access_key.access_key_secret, &ymd, - &request.region, + ®ion, &request.product, ); let derived_access_key = DerivedAccessKey { @@ -74,22 +82,25 @@ fn add_common_headers(header: &mut BTreeMap, request: &Request) &request.sign_algorithm, &derived_access_key, &ymd, - &request.region, + ®ion, &request.product, &request.pathname, &request.method, &query, - header, + headers, &digest_request_payload, ); - header.insert_kv(HEADER_AUTHORIZATION, authorization); + headers.insert_kv(HEADER_AUTHORIZATION, authorization); } } - fn get_timestamp() -> (String, String) { - // TODO ... - ("yyyymmdd".into(), "yyyy-mm-dd".into()) + let ymd_format = "yyyyMMdd"; + let ymd_hms_format = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + let now = simpledateformat::get_utc_now(); + let ymd = fmt(ymd_format).unwrap().format(&now); + let ymd_hms = fmt(ymd_hms_format).unwrap().format(&now); + (ymd, ymd_hms) } fn digest_request_body(sign_algorithm: &SignAlgorithm, body: &Option>) -> String { @@ -248,6 +259,16 @@ fn test_get_nonce() { assert!(nonce.starts_with("nonce-")); } +#[test] +fn test_get_timestamp() { + let (ymd, ymd_hms) = get_timestamp(); + let ymd_hms_take: String = ymd_hms.chars() + .filter(|c| *c != '-') + .take_while(|c| *c != 'T') + .collect(); + assert_eq!(ymd, ymd_hms_take); +} + #[test] fn test_digest_request_body() { assert_eq!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", diff --git a/src/v4/mod.rs b/src/v4/mod.rs index 6422cfa..3963977 100644 --- a/src/v4/mod.rs +++ b/src/v4/mod.rs @@ -1,3 +1,3 @@ -mod constant; -mod access_key; -mod aliyun_util; +pub mod constant; +pub mod access_key; +pub mod aliyun_util;