use http::{header::InvalidHeaderValue, HeaderValue};
use crate::{auth::AuthBuilder, client::Client, BucketName, EndPoint, KeyId, KeySecret};
pub trait STS
where
Self: Sized,
{
fn new_with_sts<ST>(
access_key_id: KeyId,
access_key_secret: KeySecret,
endpoint: EndPoint,
bucket: BucketName,
security_token: ST,
) -> Result<Self, InvalidHeaderValue>
where
ST: TryInto<HeaderValue>,
ST::Error: Into<InvalidHeaderValue>;
}
const SECURITY_TOKEN: &str = "x-oss-security-token";
impl<M: Default + Clone> STS for Client<M> {
fn new_with_sts<ST>(
access_key_id: KeyId,
access_key_secret: KeySecret,
endpoint: EndPoint,
bucket: BucketName,
security_token: ST,
) -> Result<Self, InvalidHeaderValue>
where
ST: TryInto<HeaderValue>,
ST::Error: Into<InvalidHeaderValue>,
{
let mut auth_builder = AuthBuilder::default();
auth_builder.key(access_key_id);
auth_builder.secret(access_key_secret);
auth_builder.header_insert(SECURITY_TOKEN, {
let mut token = security_token.try_into().map_err(|e| e.into())?;
token.set_sensitive(true);
token
});
Ok(Self::from_builder(auth_builder, endpoint, bucket))
}
}
#[cfg(test)]
mod tests {
use http::{HeaderValue, Method};
use crate::{file::AlignBuilder, types::CanonicalizedResource, BucketName, Client, EndPoint};
use super::STS;
#[tokio::test]
async fn test_sts() {
let client = Client::new_with_sts(
"foo1".into(),
"foo2".into(),
EndPoint::CN_SHANGHAI,
BucketName::new("abc").unwrap(),
"bar",
)
.unwrap();
let builder = client
.builder(
Method::GET,
"https://abc.oss-cn-shanghai.aliyuncs.com/"
.try_into()
.unwrap(),
CanonicalizedResource::default(),
)
.unwrap();
let request = builder.build().unwrap();
let headers = request.headers();
let sts_token = headers.get("x-oss-security-token");
assert_eq!(sts_token, Some(&HeaderValue::from_static("bar")));
}
}