Skip to content

fix: cache CLI AWS credentials until expiry#23325

Open
ametel01 wants to merge 9 commits into
apache:mainfrom
ametel01:fix-cli-aws-credential-cache
Open

fix: cache CLI AWS credentials until expiry#23325
ametel01 wants to merge 9 commits into
apache:mainfrom
ametel01:fix-cli-aws-credential-cache

Conversation

@ametel01

@ametel01 ametel01 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

The CLI's S3 credential provider wrapped AWS SDK credentials but called SharedCredentialsProvider::provide_credentials() for every object-store credential request. That bypasses the AWS SDK request pipeline identity cache and can repeatedly invoke expensive providers such as credential_process or SSO-backed providers even when the returned credentials have not expired.

What changes are included in this PR?

  • Cache the converted object_store::aws::AwsCredential inside S3CredentialProvider.
  • Seed that cache from the initial credential fetch already performed while building the S3 object store.
  • Reuse cached credentials until they are expired or within a small refresh buffer.
  • Add regression coverage for seeded credentials, non-expiring credentials, expired and near-expiry credentials, and an end-to-end credential_process flow that fails on main without this fix.

Are these changes tested?

Yes:

  • cargo test -p datafusion-cli s3_object_store_reuses_fetched_credentials_until_expiry -- --nocapture
  • cargo test -p datafusion-cli object_storage
  • cargo test -p datafusion-cli
  • cargo clippy --all-targets --all-features -- -D warnings

I also verified the new public-flow regression test against detached main; it fails there because the credential process runs multiple times instead of once.

Are there any user-facing changes?

No API or configuration changes. The CLI should make fewer redundant AWS credential-provider calls for S3 object stores while still refreshing expiring credentials.

@ametel01 ametel01 marked this pull request as ready for review July 5, 2026 06:33

@kosiew kosiew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ametel01
Thanks for the fix. The credential cache behavior looks good to me. I left one small test cleanup suggestion.

Comment thread datafusion-cli/src/object_storage.rs Outdated

@kosiew kosiew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks 👍 to me

@kosiew kosiew added this pull request to the merge queue Jul 11, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 11, 2026
@kosiew kosiew added this pull request to the merge queue Jul 11, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 11, 2026
@kosiew kosiew enabled auto-merge July 14, 2026 07:40
@kosiew kosiew disabled auto-merge July 14, 2026 07:41
@kosiew kosiew enabled auto-merge July 14, 2026 07:44
@kosiew kosiew added this pull request to the merge queue Jul 14, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 14, 2026

@alamb alamb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ametel01 and @kosiew

credentials: Option<CredentialsFromConfigProvider>,
}

struct CredentialsFromConfigProvider {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add some comments expalining this?

let credentials = match credentials.provide_credentials().await {
Ok(_) => Some(credentials),
Ok(initial_credentials) => Some(CredentialsFromConfigProvider {
provider: credentials,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we can't use the same field name (provider)?

("AWS_REGION", None),
]);

let listener = TcpListener::bind("127.0.0.1:0").await?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do? Mimic a AWS endpoint with a shell script? I am not sure that is any better than a rust mock, and it won't work on windows , will it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI utility does not check expiration of AWS credentials

3 participants