Skip to content

Commit 924ad34

Browse files
committed
Avoid extending IMDS credentials expiry unconditionally
This commit fixes a bug reported in #2258 (comment)
1 parent a78ac59 commit 924ad34

File tree

1 file changed

+57
-11
lines changed

1 file changed

+57
-11
lines changed

aws/rust-runtime/aws-config/src/imds/credentials.rs

+57-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::fmt;
2323
use std::sync::{Arc, RwLock};
2424
use std::time::{Duration, SystemTime};
2525

26-
const CREDENTIAL_EXPIRATION_INTERVAL: Duration = Duration::from_secs(15 * 60);
26+
const CREDENTIAL_EXPIRATION_INTERVAL: Duration = Duration::from_secs(10 * 60);
2727

2828
#[derive(Debug)]
2929
struct ImdsCommunicationError {
@@ -192,21 +192,20 @@ impl ImdsCredentialsProvider {
192192
//
193193
// This allows continued use of the credentials even when IMDS returns expired ones.
194194
fn maybe_extend_expiration(&self, expiration: SystemTime) -> SystemTime {
195+
let now = self.time_source.now();
196+
// If credentials from IMDS are not stale, use them as they are.
197+
if now < expiration {
198+
return expiration;
199+
}
200+
195201
let rng = fastrand::Rng::with_seed(
196-
self.time_source
197-
.now()
198-
.duration_since(SystemTime::UNIX_EPOCH)
202+
now.duration_since(SystemTime::UNIX_EPOCH)
199203
.expect("now should be after UNIX EPOCH")
200204
.as_secs(),
201205
);
202206
// calculate credentials' refresh offset with jitter
203-
let refresh_offset =
204-
CREDENTIAL_EXPIRATION_INTERVAL + Duration::from_secs(rng.u64(120..=600));
205-
let new_expiry = self.time_source.now() + refresh_offset;
206-
207-
if new_expiry < expiration {
208-
return expiration;
209-
}
207+
let refresh_offset = CREDENTIAL_EXPIRATION_INTERVAL + Duration::from_secs(rng.u64(0..=300));
208+
let new_expiry = now + refresh_offset;
210209

211210
tracing::warn!(
212211
"Attempting credential expiration extension due to a credential service availability issue. \
@@ -342,6 +341,53 @@ mod test {
342341
connection.assert_requests_match(&[]);
343342
}
344343

344+
#[tokio::test]
345+
#[traced_test]
346+
async fn credentials_not_stale_should_be_used_as_they_are() {
347+
let connection = TestConnection::new(vec![
348+
(
349+
token_request("http://169.254.169.254", 21600),
350+
token_response(21600, TOKEN_A),
351+
),
352+
(
353+
imds_request("http://169.254.169.254/latest/meta-data/iam/security-credentials/", TOKEN_A),
354+
imds_response(r#"profile-name"#),
355+
),
356+
(
357+
imds_request("http://169.254.169.254/latest/meta-data/iam/security-credentials/profile-name", TOKEN_A),
358+
imds_response("{\n \"Code\" : \"Success\",\n \"LastUpdated\" : \"2021-09-20T21:42:26Z\",\n \"Type\" : \"AWS-HMAC\",\n \"AccessKeyId\" : \"ASIARTEST\",\n \"SecretAccessKey\" : \"testsecret\",\n \"Token\" : \"testtoken\",\n \"Expiration\" : \"2021-09-21T04:16:53Z\"\n}"),
359+
),
360+
]);
361+
362+
// set to 2021-09-21T04:16:50Z that makes returned credentials' expiry (2021-09-21T04:16:53Z)
363+
// not stale
364+
let time_of_request_to_fetch_credentials = UNIX_EPOCH + Duration::from_secs(1632197810);
365+
let time_source = TimeSource::testing(&TestingTimeSource::new(
366+
time_of_request_to_fetch_credentials,
367+
));
368+
369+
tokio::time::pause();
370+
371+
let provider_config = ProviderConfig::no_configuration()
372+
.with_http_connector(DynConnector::new(connection.clone()))
373+
.with_time_source(time_source)
374+
.with_sleep(TokioSleep::new());
375+
let client = crate::imds::Client::builder()
376+
.configure(&provider_config)
377+
.build()
378+
.await
379+
.expect("valid client");
380+
let provider = ImdsCredentialsProvider::builder()
381+
.configure(&provider_config)
382+
.imds_client(client)
383+
.build();
384+
let creds = provider.provide_credentials().await.expect("valid creds");
385+
assert!(creds.expiry().unwrap() > time_of_request_to_fetch_credentials);
386+
connection.assert_requests_match(&[]);
387+
388+
// There should not be logs indicating credentials are extended for stability.
389+
assert!(!logs_contain("Attempting credential expiration extension"));
390+
}
345391
#[tokio::test]
346392
#[traced_test]
347393
async fn expired_credentials_should_be_extended() {

0 commit comments

Comments
 (0)