rusty_oss/credentials/
serde.rsuse std::fmt::{self, Debug, Formatter};
use std::mem;
use serde::{Deserialize, Deserializer};
use time::PrimitiveDateTime;
use zeroize::Zeroize as _;
use crate::time_::ISO8601_EXT;
use super::{Credentials, RotatingCredentials};
#[derive(Clone, Deserialize)]
pub struct EcsSecurityCredentialsMetadataResponse {
#[serde(rename = "AccessKeyId")]
key: String,
#[serde(rename = "AccessKeySecret")]
secret: String,
#[serde(rename = "SecurityToken")]
token: String,
#[serde(rename = "Expiration", deserialize_with = "expiration_deserializer")]
expiration: PrimitiveDateTime,
}
fn expiration_deserializer<'de, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(deserializer)?;
PrimitiveDateTime::parse(s, &ISO8601_EXT).map_err(serde::de::Error::custom)
}
impl EcsSecurityCredentialsMetadataResponse {
pub fn deserialize(s: &str) -> Result<Self, serde_json::Error> {
serde_json::from_str(s)
}
#[inline]
#[must_use]
pub fn key(&self) -> &str {
&self.key
}
#[inline]
#[must_use]
pub fn secret(&self) -> &str {
&self.secret
}
#[inline]
#[must_use]
pub fn token(&self) -> &str {
&self.token
}
#[inline]
#[must_use]
pub const fn expiration(&self) -> PrimitiveDateTime {
self.expiration
}
#[inline]
#[must_use]
pub fn into_credentials(mut self) -> Credentials {
let key = mem::take(&mut self.key);
let secret = mem::take(&mut self.secret);
let token = mem::take(&mut self.token);
Credentials::new_with_token(key, secret, token)
}
#[inline]
pub fn rotate_credentials(mut self, rotating: &RotatingCredentials) {
let key = mem::take(&mut self.key);
let secret = mem::take(&mut self.secret);
let token = mem::take(&mut self.token);
rotating.update(key, secret, Some(token));
}
}
impl Debug for EcsSecurityCredentialsMetadataResponse {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("EcsSecurityCredentialsMetadataResponse")
.field("key", &self.key)
.finish_non_exhaustive()
}
}
impl Drop for EcsSecurityCredentialsMetadataResponse {
fn drop(&mut self) {
self.secret.zeroize();
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn deserialize() {
let json = r#"{
"Code" : "Success",
"LastUpdated" : "2020-12-28T16:47:50Z",
"Type" : "OSS-HMAC",
"AccessKeyId" : "some_access_key",
"AccessKeySecret" : "some_secret_key",
"SecurityToken" : "some_token",
"Expiration" : "2020-12-28T23:10:09Z"
}"#;
let deserialized = EcsSecurityCredentialsMetadataResponse::deserialize(json).unwrap();
assert_eq!(deserialized.key(), "some_access_key");
assert_eq!(deserialized.secret(), "some_secret_key");
assert_eq!(deserialized.token(), "some_token");
assert_eq!(
deserialized.expiration().assume_utc().unix_timestamp(),
1609197009
);
let debug_output = format!("{deserialized:?}");
assert_eq!(
debug_output,
"EcsSecurityCredentialsMetadataResponse { key: \"some_access_key\", .. }"
);
}
}