feat: updates

This commit is contained in:
2023-09-29 17:17:17 +08:00
parent 36755d3e99
commit 79d784c700
7 changed files with 75 additions and 29 deletions

View File

@@ -13,5 +13,6 @@ hmac-sm3 = "0.1.0"
rand = "0.8.5" rand = "0.8.5"
sha1 = "0.10.5" sha1 = "0.10.5"
sha256 = "1.4.0" sha256 = "1.4.0"
simpledateformat = "0.1.4"
sm3 = "0.4.2" sm3 = "0.4.2"
zeroize = "1.6.0" zeroize = "1.6.0"

2
src/lib.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod util;
pub mod v4;

View File

@@ -1,6 +1,28 @@
mod util; use alibabacloud_openapi_signature::util::sign_algorithm::SignAlgorithm;
mod v4; use alibabacloud_openapi_signature::v4::access_key::AccessKey;
use alibabacloud_openapi_signature::v4::aliyun_util::{add_common_headers, Request};
fn main() { 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);
} }

View File

@@ -1,3 +1,3 @@
pub(crate) mod common_util; pub(crate) mod common_util;
pub(crate) mod map_util; pub(crate) mod map_util;
pub(crate) mod sign_algorithm; pub mod sign_algorithm;

View File

@@ -5,7 +5,7 @@ const ACS4_HMAC_SHA256: &str = "ACS4-HMAC-SHA256";
const ACS4_HMAC_SM3: &str = "ACS4-HMAC-SM3"; const ACS4_HMAC_SM3: &str = "ACS4-HMAC-SM3";
#[derive(Clone, Copy)] #[derive(Clone, Copy, Debug)]
pub enum SignAlgorithm { pub enum SignAlgorithm {
/// SHA1 is used for Signatures before V4 /// SHA1 is used for Signatures before V4
Sha1, Sha1,

View File

@@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
use std::time::SystemTime; use std::time::SystemTime;
use rand::random; use rand::random;
use simpledateformat::fmt;
use crate::util::common_util::{join_slices, percent_encode}; use crate::util::common_util::{join_slices, percent_encode};
use crate::util::map_util::BTreeMapAddKv; 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); const SEQ: AtomicU64 = AtomicU64::new(0);
struct Request { #[derive(Debug)]
pub struct Request {
pub version: String, pub version: String,
pub region: String, pub region: Option<String>,
pub product: String, pub product: String,
pub action: String, pub action: String,
pub method: String, pub method: String,
@@ -28,42 +30,48 @@ struct Request {
pub stream: Option<Vec<u8>>, pub stream: Option<Vec<u8>>,
} }
fn add_common_headers(header: &mut BTreeMap<String, String>, request: &Request) { pub fn add_common_headers(request: &mut Request) {
let (ymd, date) = get_timestamp(); let (ymd, date) = get_timestamp();
let headers = &mut request.headers;
let host = get_host(&request.endpoint); let host = get_host(&request.endpoint);
header.insert_kv(HEADER_HOST, host); headers.insert_kv(HEADER_HOST, host);
header.insert_kv(HEADER_X_ASC_VERSION, &request.version); headers.insert_kv(HEADER_X_ASC_VERSION, &request.version);
header.insert_kv(HEADER_X_ASC_ACTION, &request.action); headers.insert_kv(HEADER_X_ASC_ACTION, &request.action);
header.insert_kv(HEADER_USER_AGENT, &request.user_agent); headers.insert_kv(HEADER_USER_AGENT, &request.user_agent);
header.insert_kv(HEADER_X_ASC_DATE, date); headers.insert_kv(HEADER_X_ASC_DATE, date);
header.insert_kv(HEADER_X_ASC_SIGNATURE_NONCE, get_nonce()); headers.insert_kv(HEADER_X_ASC_SIGNATURE_NONCE, get_nonce());
header.insert_kv(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON); headers.insert_kv(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON);
let digest_request_payload = digest_request_body(&request.sign_algorithm, &request.stream); let digest_request_payload = digest_request_body(&request.sign_algorithm, &request.stream);
match &request.sign_algorithm { match &request.sign_algorithm {
SignAlgorithm::Sha1 => panic!("SHA1 in V4 is NOT supported!"), SignAlgorithm::Sha1 => panic!("SHA1 in V4 is NOT supported!"),
SignAlgorithm::Sha256 => { 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 => { 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(); let query = BTreeMap::new();
if let Some(access_key) = &request.access_key { 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 { if let Some(security_token) = &access_key.security_token {
header.insert_kv(HEADER_X_ASC_ACCESS_KEY_ID, &access_key.access_key_id); headers.insert_kv(HEADER_X_ASC_SECURITY_TOKEN, security_token);
header.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( let signing_key = get_signing_key(
&request.sign_algorithm, &request.sign_algorithm,
&access_key.access_key_secret, &access_key.access_key_secret,
&ymd, &ymd,
&request.region, &region,
&request.product, &request.product,
); );
let derived_access_key = DerivedAccessKey { let derived_access_key = DerivedAccessKey {
@@ -74,22 +82,25 @@ fn add_common_headers(header: &mut BTreeMap<String, String>, request: &Request)
&request.sign_algorithm, &request.sign_algorithm,
&derived_access_key, &derived_access_key,
&ymd, &ymd,
&request.region, &region,
&request.product, &request.product,
&request.pathname, &request.pathname,
&request.method, &request.method,
&query, &query,
header, headers,
&digest_request_payload, &digest_request_payload,
); );
header.insert_kv(HEADER_AUTHORIZATION, authorization); headers.insert_kv(HEADER_AUTHORIZATION, authorization);
} }
} }
fn get_timestamp() -> (String, String) { fn get_timestamp() -> (String, String) {
// TODO ... let ymd_format = "yyyyMMdd";
("yyyymmdd".into(), "yyyy-mm-dd".into()) 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<Vec<u8>>) -> String { fn digest_request_body(sign_algorithm: &SignAlgorithm, body: &Option<Vec<u8>>) -> String {
@@ -248,6 +259,16 @@ fn test_get_nonce() {
assert!(nonce.starts_with("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] #[test]
fn test_digest_request_body() { fn test_digest_request_body() {
assert_eq!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", assert_eq!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",

View File

@@ -1,3 +1,3 @@
mod constant; pub mod constant;
mod access_key; pub mod access_key;
mod aliyun_util; pub mod aliyun_util;