use chrono::{Duration, Utc};
use futures::future::{FutureResult, ok};
use {AwsCredentials, CredentialsError, ProvideAwsCredentials};
#[derive(Clone, Debug)]
pub struct StaticProvider {
credentials: AwsCredentials,
valid_for: Option<i64>,
}
impl StaticProvider {
pub fn new(
access_key: String,
secret_access_key: String,
token: Option<String>,
valid_for: Option<i64>,
) -> StaticProvider {
StaticProvider {
credentials: AwsCredentials::new(
access_key,
secret_access_key,
token,
None
),
valid_for: valid_for,
}
}
pub fn new_minimal(access_key: String, secret_access_key: String) -> StaticProvider {
StaticProvider {
credentials: AwsCredentials::new(
access_key,
secret_access_key,
None,
None
),
valid_for: None,
}
}
pub fn get_aws_access_key_id(&self) -> &str {
&self.credentials.key
}
pub fn get_aws_secret_access_key(&self) -> &str {
&self.credentials.secret
}
pub fn has_token(&self) -> bool {
self.credentials.token.is_some()
}
pub fn get_token(&self) -> &Option<String> {
&self.credentials.token
}
pub fn is_valid_for(&self) -> &Option<i64> {
&self.valid_for
}
}
impl ProvideAwsCredentials for StaticProvider {
type Future = FutureResult<AwsCredentials, CredentialsError>;
fn credentials(&self) -> Self::Future {
let mut creds = self.credentials.clone();
creds.expires_at = self.valid_for.map(|v| Utc::now() + Duration::seconds(v));
ok(creds)
}
}
#[cfg(test)]
mod tests {
use futures::Future;
use std::thread;
use std::time;
use test_utils::{is_secret_hidden_behind_asterisks, SECRET};
use ProvideAwsCredentials;
use super::*;
#[test]
fn test_static_provider_creation() {
let result = StaticProvider::new(
"fake-key".to_owned(),
"fake-secret".to_owned(),
Some("token".to_owned()),
Some(300),
).credentials().wait();
assert!(result.is_ok());
}
#[test]
fn test_static_provider_minimal_creation() {
let result =
StaticProvider::new_minimal("fake-key-2".to_owned(), "fake-secret-2".to_owned())
.credentials().wait();
assert!(result.is_ok());
}
#[test]
fn test_static_provider_custom_time_expiration() {
let start_time = Utc::now();
let result = StaticProvider::new(
"fake-key".to_owned(),
"fake-secret".to_owned(),
None,
Some(10000),
).credentials().wait();
assert!(result.is_ok());
let finalized = result.unwrap();
let expires_at = finalized.expires_at().unwrap().clone();
assert!(start_time + Duration::minutes(100) < expires_at);
assert!(expires_at < start_time + Duration::minutes(200));
}
#[test]
fn test_static_provider_expiration_time_is_recalculated() {
let provider = StaticProvider::new(
"fake-key".to_owned(),
"fake-secret".to_owned(),
None,
Some(10000),
);
let creds1 = provider.credentials().wait().unwrap();
thread::sleep(time::Duration::from_secs(1));
let creds2 = provider.credentials().wait().unwrap();
assert!(creds1.expires_at() < creds2.expires_at());
}
#[test]
quickcheck! {
fn test_static_provider_secrets_not_in_debug(
access_key: String,
token: Option<()>,
valid_for: Option<i64>
) -> bool {
let provider = StaticProvider::new(
access_key,
SECRET.to_owned(),
token.map(|_| SECRET.to_owned()),
valid_for
);
is_secret_hidden_behind_asterisks(&provider)
}
}
}