Skip to content

Add support for AWS_CONTAINER_CREDENTIALS_FULL_URI (EKS Pod Identity Agent)#449

Open
LockedThread wants to merge 5 commits intodurch:masterfrom
LockedThread:master
Open

Add support for AWS_CONTAINER_CREDENTIALS_FULL_URI (EKS Pod Identity Agent)#449
LockedThread wants to merge 5 commits intodurch:masterfrom
LockedThread:master

Conversation

@LockedThread
Copy link

@LockedThread LockedThread commented Mar 3, 2026

Summary

Extends the container credentials provider to support AWS_CONTAINER_CREDENTIALS_FULL_URI and the optional authorization token environment variables (AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE). This allows applications to obtain credentials when running with AWS EKS Pod Identity Agent or other credential endpoints that use a full URI and bearer token (e.g. AWS Greengrass Token Exchange, custom sidecars).

Why this is important

  • EKS Pod Identity is the recommended way to give pods on Amazon EKS access to AWS APIs without IRSA or instance roles. The EKS Pod Identity Agent runs as a DaemonSet and exposes credentials at a fixed endpoint (http://169.254.170.23/v1/credentials). The agent expects the client to set:
    • AWS_CONTAINER_CREDENTIALS_FULL_URI to that URL
    • AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE (or AWS_CONTAINER_AUTHORIZATION_TOKEN) with the pod identity token
  • Without FULL_URI support, Credentials::default() (and the rest of the chain) never considers the container provider when only these env vars are set, so pods using EKS Pod Identity get NoCredentials and cannot call S3 or other AWS services with this crate.

Prior work

This builds on the container credentials support added in Priorize ECS/EKS credentials over EC2's when available (PR #441). That PR introduced from_container_credentials_provider() and prioritized it over EC2 instance metadata, but only for AWS_CONTAINER_CREDENTIALS_RELATIVE_URI (used by ECS task IAM roles). This change adds the FULL_URI path and authorization token handling so both ECS-style and EKS Pod Identity–style container credentials are supported by the same provider.

Changes

  • aws-creds/src/credentials.rs
    • from_container_credentials_provider() now:
      1. Uses AWS_CONTAINER_CREDENTIALS_RELATIVE_URI if set (unchanged; builds http://169.254.170.2{path}).
      2. Otherwise uses AWS_CONTAINER_CREDENTIALS_FULL_URI if set.
    • When using FULL_URI, the request optionally includes an Authorization header:
      • Token is read from AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE (file path) if set.
      • Otherwise from AWS_CONTAINER_AUTHORIZATION_TOKEN.
    • New helper get_container_authorization_token() implements the token lookup (file precedence over env).
  • Tests (same file, #[cfg(feature = "http-credentials")]):
    • test_container_credentials_not_container_when_no_env – neither URI set → NotContainer.
    • test_container_credentials_relative_uri_precedence – both set → RELATIVE_URI is used.
    • test_container_credentials_full_uri_used_when_no_relative – only FULL_URI set → that URL is used.
    • test_get_container_authorization_token_from_file – token read from file.
    • test_get_container_authorization_token_from_env – token from env var.
    • test_get_container_authorization_token_file_precedence – file overrides env.

Environment variables (after this PR)

Variable When used Purpose
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI Checked first Path only; host is 169.254.170.2 (ECS task role).
AWS_CONTAINER_CREDENTIALS_FULL_URI If RELATIVE_URI unset Full URL (e.g. EKS Pod Identity Agent).
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE When using FULL_URI Path to file containing token for Authorization header.
AWS_CONTAINER_AUTHORIZATION_TOKEN When using FULL_URI, if _FILE unset Token value for Authorization header.

Behavior matches the AWS SDK / container credential provider (RELATIVE_URI precedence, FULL_URI, optional auth token).

Testing

  • cargo test -p aws-creds --features http-credentials – all new and existing tests pass.
  • No change to the default credential chain order; container provider remains after env/profile/STS and before instance metadata.

This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Added container authorization token support and EKS Pod Identity credential source.
  • Improvements

    • Flexible container metadata source selection with clearer precedence and improved credential handling for containerized deployments.
  • Tests

    • Added tests covering container credential flows and token-source precedence (file vs environment).
  • Temp Usage
    • If you want to use this in the interim you must add the following:
    [dependencies]
    rust-s3 = { git = 'https://github.com/LockedThread/rust-s3', branch = 'master', features = ['http-credentials'] }
    
    [patch.crates-io]
    # To force rust-s3 to use aws-creds from the fork, since rust-s3 does independent versioning.
    aws-creds = { git = "https://github.com/LockedThread/rust-s3", branch = "master" }

@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Adds feature-gated container authorization token retrieval and extends Credentials::from_container_credentials_provider to support ECS RELATIVE_URI and EKS FULL_URI metadata endpoints, optionally sending an Authorization header. Includes tests and test utilities to validate token sourcing and precedence.

Changes

Cohort / File(s) Summary
Container token helper & provider logic
aws-creds/src/credentials.rs
Added get_container_authorization_token() (feature-gated http-credentials) and refactored Credentials::from_container_credentials_provider() to handle AWS_CONTAINER_CREDENTIALS_RELATIVE_URI (ECS) and AWS_CONTAINER_CREDENTIALS_FULL_URI (EKS Pod Identity), attaching Authorization header when token present.
Tests & test utilities
aws-creds/src/credentials.rs
Added tests covering RELATIVE_URI vs FULL_URI precedence, absence of container envs, token retrieval from file vs env (with file precedence), plus EnvGuard and a static test lock to serialize environment changes during tests.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant CP as CredentialsProvider
    participant TS as TokenSource\n(File / Env)
    participant MS as MetadataServer\n(ECS RELATIVE_URI / EKS FULL_URI)

    App->>CP: from_container_credentials_provider()
    alt FULL_URI path
        CP->>TS: get_container_authorization_token()
        TS-->>CP: token (optional)
        CP->>MS: GET FULL_URI with Authorization header
    else RELATIVE_URI path
        CP->>MS: GET RELATIVE_URI (no auth)
    end
    MS-->>CP: credential JSON
    CP-->>App: Credentials
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇 I nibble at tokens found in file or air,
I hop between RELATIVE and FULL_URI with care,
A header here, a file there, precedence set right,
Credentials fetched, snug in the night—
🥕 bytes and hops, a rabbit's delight.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for AWS_CONTAINER_CREDENTIALS_FULL_URI (EKS Pod Identity Agent), which aligns with the primary objective and the significant code additions (196 lines) to handle this new credential provider.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@brownian-motion-v0
Copy link

Brownian Motion (Brass)

Recommendation: Refactor

Summary: PR adds support for EKS Pod Identity, but complexity may outweigh benefits.
Risk: Medium · Confidence: 70%

Highlights

  • Good test coverage
  • Clear commit history

Unknowns

  • Impact on existing credential handling
  • Performance implications of added complexity

Next actions

  • Keep: existing tests and structure
  • Drop: unnecessary complexity in authorization handling
  • Add: documentation on the new functionality

Reflection questions

  • What core assumption underpins this PR's approach?
  • How does this change align with the project's longer-term goals?
  • Could there be a simpler way to achieve the primary objective here?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
aws-creds/src/credentials.rs (2)

344-350: Add a rustdoc example for from_container_credentials_provider.

The updated public API docs explain precedence and auth behavior, but they still lack a concrete usage example.

As per coding guidelines, "Provide documentation examples for all public APIs".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aws-creds/src/credentials.rs` around lines 344 - 350, Add a rustdoc example
for the public function from_container_credentials_provider that shows how to
construct and use the provider: demonstrate calling
from_container_credentials_provider(), await-ing/getting credentials, and
illustrate the precedence order (AWS_CONTAINER_CREDENTIALS_RELATIVE_URI checked
before AWS_CONTAINER_CREDENTIALS_FULL_URI) and how an Authorization header is
supplied from AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE or
AWS_CONTAINER_AUTHORIZATION_TOKEN; mark the example with the #[cfg(feature =
"http-credentials")] note in the docs and include a short snippet that sets the
relevant env vars (or token file) and retrieves credentials so users can
copy/paste to verify behavior.

196-201: Avoid silently masking token-file misconfiguration.

If AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE is set but unreadable at Line 197, the code silently falls back. For explicit file configuration, returning an error is usually safer and easier to debug.

Proposed refactor
- fn get_container_authorization_token() -> Option<String> {
+ fn get_container_authorization_token() -> Result<Option<String>, CredentialsError> {
     if let Ok(path) = env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE") {
-        if let Ok(token) = std::fs::read_to_string(path) {
-            return Some(token.trim_end().to_string());
-        }
+        let token = std::fs::read_to_string(path)?;
+        return Ok(Some(token.trim_end().to_string()));
     }
-    env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN").ok()
+    Ok(env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN").ok())
 }
- let token = get_container_authorization_token();
+ let token = get_container_authorization_token()?;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aws-creds/src/credentials.rs` around lines 196 - 201, The code silently falls
back to AWS_CONTAINER_AUTHORIZATION_TOKEN when
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE is set but std::fs::read_to_string fails;
change the logic so that if AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE is present
but unreadable you return/propagate an explicit error (rather than silently
falling back) — detect env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE") being
Ok and, on read_to_string error, return a Result::Err (or otherwise propagate a
io::Error with context) referencing the failing std::fs::read_to_string call and
the AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE variable instead of proceeding to
env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN").ok().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@aws-creds/src/credentials.rs`:
- Around line 669-709: The three tests
(test_get_container_authorization_token_from_file,
test_get_container_authorization_token_from_env,
test_get_container_authorization_token_file_precedence) mutate process-global
env vars without synchronizing on CONTAINER_CREDENTIALS_TEST_LOCK; update each
test to acquire the same lock at the start (e.g. let _guard_lock =
CONTAINER_CREDENTIALS_TEST_LOCK.lock().unwrap();) so they use the shared mutex
while setting/removing env vars via EnvGuard and calling
get_container_authorization_token(), preventing races in parallel test runs.
- Around line 352-365: The code currently accepts any env-provided URL in the
url variable and may forward auth_token to it; parse and validate the URL before
making the request by calling Url::parse(&full_uri) (or equivalent) and ensure
the scheme is http or https and the host is in a trusted allowlist (reject
otherwise, e.g. return Err(CredentialsError::NotContainer)). Only call
get_container_authorization_token() and attach the Authorization header to the
request created by apply_timeout(attohttpc::get(&url)) if the parsed URL passes
validation; do not attach the token for untrusted or invalid URIs.

---

Nitpick comments:
In `@aws-creds/src/credentials.rs`:
- Around line 344-350: Add a rustdoc example for the public function
from_container_credentials_provider that shows how to construct and use the
provider: demonstrate calling from_container_credentials_provider(),
await-ing/getting credentials, and illustrate the precedence order
(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI checked before
AWS_CONTAINER_CREDENTIALS_FULL_URI) and how an Authorization header is supplied
from AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE or
AWS_CONTAINER_AUTHORIZATION_TOKEN; mark the example with the #[cfg(feature =
"http-credentials")] note in the docs and include a short snippet that sets the
relevant env vars (or token file) and retrieves credentials so users can
copy/paste to verify behavior.
- Around line 196-201: The code silently falls back to
AWS_CONTAINER_AUTHORIZATION_TOKEN when AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE is
set but std::fs::read_to_string fails; change the logic so that if
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE is present but unreadable you
return/propagate an explicit error (rather than silently falling back) — detect
env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE") being Ok and, on
read_to_string error, return a Result::Err (or otherwise propagate a io::Error
with context) referencing the failing std::fs::read_to_string call and the
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE variable instead of proceeding to
env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN").ok().

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a9314f and 4462583.

📒 Files selected for processing (1)
  • aws-creds/src/credentials.rs

@brownian-motion-v0
Copy link

Brownian Motion (Brass)

Recommendation: Refactor

Summary: PR adds support for EKS Pod Identity, but complexity may outweigh benefits.
Risk: Medium · Confidence: 70%

Highlights

  • Good test coverage
  • Clear documentation on changes

Unknowns

  • Impact on existing credential retrieval logic
  • Performance implications of added complexity

Next actions

  • Keep: Existing tests and documentation
  • Drop: Unused environment variable checks
  • Add: Simplified error handling for credential retrieval

Reflection questions

  • What core assumption underpins this PR's approach?
  • How does this change align with the project's longer-term goals?
  • Could there be a simpler way to achieve the primary objective here?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
aws-creds/src/credentials.rs (1)

344-350: Add a rustdoc example for this public API.

The method-level docs explain behavior well, but this public API still lacks an example snippet. Adding a short no_run example for RELATIVE_URI/FULL_URI usage would satisfy the project doc standard.

Suggested doc addition
     /// Load credentials from container metadata (ECS task role or EKS Pod Identity).
     ///
     /// Checks `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` first (ECS), then
     /// `AWS_CONTAINER_CREDENTIALS_FULL_URI` (EKS Pod Identity Agent, etc.).
     /// When using `FULL_URI`, optionally sends an `Authorization` header from
     /// `AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE` or `AWS_CONTAINER_AUTHORIZATION_TOKEN`.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// use awscreds::Credentials;
+    ///
+    /// // In ECS, set AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.
+    /// // In EKS Pod Identity, set AWS_CONTAINER_CREDENTIALS_FULL_URI
+    /// // (optionally with AWS_CONTAINER_AUTHORIZATION_TOKEN[_FILE]).
+    /// let creds = Credentials::from_container_credentials_provider().unwrap();
+    /// ```

As per coding guidelines, "Provide documentation examples for all public APIs".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aws-creds/src/credentials.rs` around lines 344 - 350, Add a rustdoc example
(annotated with no_run) to the public method
Credentials::from_container_credentials_provider() demonstrating typical usage
for ECS (set AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) and EKS Pod Identity (set
AWS_CONTAINER_CREDENTIALS_FULL_URI and optional
AWS_CONTAINER_AUTHORIZATION_TOKEN or AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE),
returning a Credentials instance; place the example in the doc comment for the
same function (keeping the existing #[cfg(feature = "http-credentials")] guard)
and ensure it follows the project's doc style (short, shows environment
variables and a call to Credentials::from_container_credentials_provider() and
unwrap()).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@aws-creds/src/credentials.rs`:
- Around line 344-350: Add a rustdoc example (annotated with no_run) to the
public method Credentials::from_container_credentials_provider() demonstrating
typical usage for ECS (set AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) and EKS Pod
Identity (set AWS_CONTAINER_CREDENTIALS_FULL_URI and optional
AWS_CONTAINER_AUTHORIZATION_TOKEN or AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE),
returning a Credentials instance; place the example in the doc comment for the
same function (keeping the existing #[cfg(feature = "http-credentials")] guard)
and ensure it follows the project's doc style (short, shows environment
variables and a call to Credentials::from_container_credentials_provider() and
unwrap()).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4462583 and 550f2c8.

📒 Files selected for processing (1)
  • aws-creds/src/credentials.rs

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.

1 participant