Skip to content

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

Open
LockedThread wants to merge 8 commits into
durch:masterfrom
LockedThread:master
Open

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

Conversation

@LockedThread
Copy link
Copy Markdown

@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

    • Support for an additional container credential source (EKS Pod Identity) and optional container authorization token usage.
  • Improvements

    • Clearer precedence between container metadata sources, conditional token attachment only for trusted agent endpoints, and improved credential request handling and error reporting.
  • Tests

    • Expanded tests for container credential flows, token-source precedence, host trust validation, and environment isolation during tests.
  • 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
Copy Markdown

coderabbitai Bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Adds support for two container metadata sources: ECS RELATIVE_URI and EKS FULL_URI; implements optional container authorization token loading (file or env) and allowlist validation for link-local agent hosts; refactors container metadata request construction to include conditional Authorization header; expands unit tests and test helpers.

Changes

Container credentials: FULL_URI, token loading, and request refactor

Layer / File(s) Summary
Data / Constants / Errors
aws-creds/src/credentials.rs, aws-creds/src/error.rs
Adds link-local EKS agent address constants and imports (Host), and a feature-gated error variant InvalidContainerCredentialsFullUri(String) for AWS_CONTAINER_CREDENTIALS_FULL_URI parsing/authorization issues.
Helpers: token load & allowlist
aws-creds/src/credentials.rs
Adds feature-gated get_container_authorization_token() (reads trimmed AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE or AWS_CONTAINER_AUTHORIZATION_TOKEN) and a validator ensuring FULL_URI targets only trusted link-local agent IPs before using a token.
Core provider refactor
aws-creds/src/credentials.rs
Refactors Credentials::from_container_credentials_provider() to prefer AWS_CONTAINER_CREDENTIALS_RELATIVE_URI (ECS) when set; otherwise use AWS_CONTAINER_CREDENTIALS_FULL_URI (EKS), optionally attach Authorization header when a token is present and host is trusted, build the HTTP request from chosen URL, and deserialize credentials from response.
Tests / Test utilities
aws-creds/src/credentials.rs
Adds tests for: absence of container env vars (NotContainer), RELATIVE_URI precedence, FULL_URI path behavior, token retrieval from file vs env (including file-read error/no-env-fallback and file precedence), rejecting token usage for untrusted hosts, and trusted allowlist validation. Introduces CONTAINER_CREDENTIALS_TEST_LOCK and EnvGuard to serialize and isolate env changes.

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 tokens from file or air,
I hop from RELATIVE to FULL_URI with care,
A header here if the agent is true,
Tests lock the env so messes are few,
🥕 Hops, trims, and creds — a rabbit's share.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: adding support for AWS_CONTAINER_CREDENTIALS_FULL_URI for EKS Pod Identity Agent, which aligns with the primary objective of extending the container credentials provider.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

@brownian-motion-v0
Copy link
Copy Markdown

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
Copy Markdown

@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

Comment thread aws-creds/src/credentials.rs
Comment thread aws-creds/src/credentials.rs
@brownian-motion-v0
Copy link
Copy Markdown

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
Copy Markdown

@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

typedrat added a commit to synapdeck/turbo-cache-server that referenced this pull request Mar 17, 2026
Patches rust-s3 to use LockedThread/rust-s3 fork which adds support for
AWS_CONTAINER_CREDENTIALS_FULL_URI (EKS Pod Identity Agent). Without
this, the S3 client falls through to IMDS and picks up the node group
role instead of the Pod Identity role.

See: durch/rust-s3#449
@LockedThread
Copy link
Copy Markdown
Author

Hey @durch, can you please review this? It's a complete blocker for anyone wanting to use the recommended approach to granting AWS resources to EKS Pods. I'm glad someone is getting use out of my fork so far, and I wasn't the only one running into this issue. --- @typedrat


See the comparison table for more info.

@durch
Copy link
Copy Markdown
Owner

durch commented May 4, 2026

Thanks for this PR. The EKS Pod Identity use case is important, and I agree this is a gap in the current container credentials provider.

Before I can merge it, I need a few safety and documentation issues addressed because this is credential-resolution code:

  1. Validate AWS_CONTAINER_CREDENTIALS_FULL_URI before attaching an authorization token. In particular, avoid forwarding AWS_CONTAINER_AUTHORIZATION_TOKEN[_FILE] to an arbitrary untrusted URI.
  2. If AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE is set but unreadable, return an explicit error rather than silently falling back to AWS_CONTAINER_AUTHORIZATION_TOKEN.
  3. Add a short rustdoc example for from_container_credentials_provider() showing the ECS RELATIVE_URI path and EKS FULL_URI + optional auth token path.
  4. Please include the exact local verification command/result, especially:
    • cargo test -p aws-creds --features http-credentials

I’m interested in merging EKS Pod Identity support, but credential-provider changes need conservative failure behavior and clear token-handling semantics.

@brownian-motion-v0
Copy link
Copy Markdown

Brownian Motion (Brass)

Recommendation: Stop

Summary: PR adds support for EKS Pod Identity but introduces unnecessary complexity.
Risk: High · Confidence: 80%

Highlights

  • Good test coverage
  • Clear commit history

Unknowns

  • No performance benchmarks
  • Impact on existing credential flows

Next actions

  • Keep: existing credential handling logic
  • Drop: unnecessary complexity in handling full URI
  • Add: documentation for existing credential mechanisms

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?

@LockedThread
Copy link
Copy Markdown
Author

Thanks for this PR. The EKS Pod Identity use case is important, and I agree this is a gap in the current container credentials provider.

Before I can merge it, I need a few safety and documentation issues addressed because this is credential-resolution code:

1. Validate `AWS_CONTAINER_CREDENTIALS_FULL_URI` before attaching an authorization token. In particular, avoid forwarding `AWS_CONTAINER_AUTHORIZATION_TOKEN[_FILE]` to an arbitrary untrusted URI.

2. If `AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE` is set but unreadable, return an explicit error rather than silently falling back to `AWS_CONTAINER_AUTHORIZATION_TOKEN`.

3. Add a short rustdoc example for `from_container_credentials_provider()` showing the ECS `RELATIVE_URI` path and EKS `FULL_URI` + optional auth token path.

4. Please include the exact local verification command/result, especially:
   
   * `cargo test -p aws-creds --features http-credentials`

I’m interested in merging EKS Pod Identity support, but credential-provider changes need conservative failure behavior and clear token-handling semantics.

Thanks for the reply.

$ cargo fmt --check
$ cargo test -p aws-creds --features http-credentials
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.08s
     Running unittests src/lib.rs (target/debug/deps/awscreds-b18214caec79feac)

running 14 tests
test credentials::test_credentials_refresh ... ignored
test credentials::test_instance_metadata_creds_deserialization ... ok
test credentials::tests::test_container_credentials_auth_token_full_uri_allowlist ... ok
test credentials::tests::test_from_credentials_file_errors ... ok
test credentials::tests::test_from_profile_respects_env_var ... ok
test credentials::tests::test_from_credentials_file_custom_location ... ok
test credentials::tests::test_container_credentials_full_uri_used_when_no_relative ... ok
test credentials::tests::test_container_credentials_not_container_when_no_env ... ok
test credentials::tests::test_container_credentials_rejects_auth_token_for_untrusted_full_uri has been running for over 60 seconds
test credentials::tests::test_container_credentials_relative_uri_precedence has been running for over 60 seconds
test credentials::tests::test_get_container_authorization_token_file_error_does_not_fallback_to_env has been running for over 60 seconds
test credentials::tests::test_get_container_authorization_token_file_precedence has been running for over 60 seconds
test credentials::tests::test_get_container_authorization_token_from_env has been running for over 60 seconds
test credentials::tests::test_get_container_authorization_token_from_file has been running for over 60 seconds
test credentials::tests::test_container_credentials_relative_uri_precedence ... ok
test credentials::tests::test_container_credentials_rejects_auth_token_for_untrusted_full_uri ... ok
test credentials::tests::test_get_container_authorization_token_file_error_does_not_fallback_to_env ... ok
test credentials::tests::test_get_container_authorization_token_file_precedence ... ok
test credentials::tests::test_get_container_authorization_token_from_env ... ok
test credentials::tests::test_get_container_authorization_token_from_file ... ok

test result: ok. 13 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 60.06s

   Doc-tests awscreds

running 4 tests
test aws-creds/src/credentials.rs - credentials::Credentials (line 24) - compile ... ok
test aws-creds/src/credentials.rs - credentials::Credentials::from_credentials_file (line 509) - compile ... ok
test aws-creds/src/credentials.rs - credentials::Credentials::from_container_credentials_provider (line 381) - compile ... ok
test aws-creds/src/credentials.rs - credentials::Credentials (line 51) ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.11s```

@LockedThread
Copy link
Copy Markdown
Author

Brownian Motion (Brass)

Recommendation: Stop

Summary: PR adds support for EKS Pod Identity but introduces unnecessary complexity. Risk: High · Confidence: 80%

Highlights

* Good test coverage

* Clear commit history

Unknowns

* No performance benchmarks

* Impact on existing credential flows

Next actions

* Keep: existing credential handling logic

* Drop: unnecessary complexity in handling full URI

* Add: documentation for existing credential mechanisms

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?

@durch This bot is ridiculous.

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@aws-creds/src/credentials.rs`:
- Around line 202-208: In get_container_authorization_token(), ensure you fully
trim whitespace for both the file path and the token value: call .trim() on the
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE string before using it to read the file
(so stray whitespace in the path is removed) and call .trim() on the contents
returned from std::fs::read_to_string to remove both leading and trailing
whitespace; likewise, when returning AWS_CONTAINER_AUTHORIZATION_TOKEN from
env::var, return its .trim()ed value (if present) instead of the raw string to
keep behavior consistent with the file-path branch.
- Around line 210-230: The
validate_container_credentials_full_uri_for_auth_token function currently only
allows specific EKS/ECS addresses; update its logic so that for HTTPS
(parsed.scheme() == "https") it accepts any host, and for HTTP (parsed.scheme()
== "http") it only allows loopback and known link-local/EKS addresses: accept
Host::Ipv4 where ip.octets() equals EKS_POD_IDENTITY_AGENT_IPV4 or equals
127.0.0.1, accept Host::Ipv6 where ip.segments() equals
EKS_POD_IDENTITY_AGENT_IPV6 or equals the ::1 segments, and accept Host::Domain
where the domain equals "localhost"; otherwise return
CredentialsError::InvalidContainerCredentialsFullUri(url.to_string()) as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b5a4d93-f4b5-4762-b4f1-a89dc9e3265c

📥 Commits

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

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

Comment on lines +202 to +208
fn get_container_authorization_token() -> Result<Option<String>, CredentialsError> {
if let Ok(path) = env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE") {
let token = std::fs::read_to_string(path)?;
return Ok(Some(token.trim_end().to_string()));
}
Ok(env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN").ok())
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

trim_end() leaves potential leading whitespace in file-sourced tokens; the env-var path is untrimmed entirely.

token.trim_end().to_string() on line 205 strips trailing whitespace (the common trailing newline) but does not strip leading whitespace. AWS CLI's equivalent reads the file and does a full strip(). If a token file has leading whitespace due to a template or editor artefact, the value passed in the Authorization header will be silently corrupted.

Additionally, the env-var path at line 207 applies no trimming at all, while the file path applies partial trimming—an inconsistency that can lead to subtle header-value mismatches.

✏️ Proposed fix
-        let token = std::fs::read_to_string(path)?;
-        return Ok(Some(token.trim_end().to_string()));
+        let token = std::fs::read_to_string(path)?;
+        return Ok(Some(token.trim().to_string()));
 ...
-    Ok(env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN").ok())
+    Ok(env::var("AWS_CONTAINER_AUTHORIZATION_TOKEN").ok().map(|t| t.trim().to_string()))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@aws-creds/src/credentials.rs` around lines 202 - 208, In
get_container_authorization_token(), ensure you fully trim whitespace for both
the file path and the token value: call .trim() on the
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE string before using it to read the file
(so stray whitespace in the path is removed) and call .trim() on the contents
returned from std::fs::read_to_string to remove both leading and trailing
whitespace; likewise, when returning AWS_CONTAINER_AUTHORIZATION_TOKEN from
env::var, return its .trim()ed value (if present) instead of the raw string to
keep behavior consistent with the file-path branch.

Comment on lines +210 to +230
/// Returns whether it is safe to send a container authorization token to `url`.
#[cfg(feature = "http-credentials")]
fn validate_container_credentials_full_uri_for_auth_token(
url: &str,
) -> Result<(), CredentialsError> {
let parsed = Url::parse(url)?;

if parsed.scheme() != "http" && parsed.scheme() != "https" {
return Err(CredentialsError::InvalidContainerCredentialsFullUri(
url.to_string(),
));
}

match parsed.host() {
Some(Host::Ipv4(ip)) if ip.octets() == EKS_POD_IDENTITY_AGENT_IPV4 => Ok(()),
Some(Host::Ipv6(ip)) if ip.segments() == EKS_POD_IDENTITY_AGENT_IPV6 => Ok(()),
_ => Err(CredentialsError::InvalidContainerCredentialsFullUri(
url.to_string(),
)),
}
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 4, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

AWS container credential provider FULL_URI allowed hosts loopback HTTPS policy Java SDK Go SDK botocore

💡 Result:

The AWS Container Credential Provider uses the AWS_CONTAINER_CREDENTIALS_FULL_URI environment variable to specify a full HTTP/HTTPS endpoint for fetching credentials in container environments like ECS and EKS. Due to security policies across AWS SDKs, this URI is restricted: For HTTP URIs: Only loopback hosts (localhost, 127.0.0.1, ::1) and specific AWS service endpoints (e.g., ECS 169.254.170.2, EKS IPv6 like fd00:ec2::23) are allowed. Non-loopback HTTP URIs are rejected. For HTTPS URIs: All hosts are permitted. This policy is enforced consistently: - Java SDK v1 (1.x): Only loopback hosts for HTTP; all HTTPS allowed. Docs explicitly state: "For absolute paths, only loopback hosts are allowed when using HTTP... All HTTPS endpoints are allowed." {1,5} - Java SDK v2 (2.x): Validates host resolves to loopback addresses for HTTP (via InetAddress check); HTTPS unrestricted. Source code confirms: if not HTTPS and not allowed host (loopback rules), throws error. {20} - Go SDK (v1 and v2): Follows same standard; supports FULL_URI with loopback/known endpoints for HTTP. {14,15} - Botocore (Python/CLI): ContainerMetadataFetcher._ALLOWED_HOSTS limits to ['169.254.170.2', 'localhost', '127.0.0.1'] for FULL_URI; cannot extend due to org-wide security policy. {2,16} This is a deliberate cross-SDK security measure to prevent arbitrary remote credential fetches, as confirmed in GitHub issues. {2,4} No configuration to override allowed hosts; use relative URI (AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) with default ECS host or ensure HTTPS/loopback compliance. IPv6 loopback supported in recent versions. {13,23}

Citations:


validate_container_credentials_full_uri_for_auth_token allowlist is narrower than AWS SDK standard.

The current implementation only permits 169.254.170.23 (IPv4) and fd00:ec2::23 (IPv6), rejecting https://any-host, http://localhost, and http://127.0.0.1 when a token is present. This deviates from AWS SDK behavior across Java, Go, and Python:

  • Java SDK v1/v2: "For absolute paths, only loopback hosts are allowed when using HTTP... All HTTPS endpoints are allowed."
  • Go SDK: Supports loopback and known endpoints for HTTP; all hosts for HTTPS
  • Botocore: Allows ['169.254.170.2', 'localhost', '127.0.0.1'] for FULL_URI

This breaks:

  1. Custom HTTPS credential providers (IoT Greengrass, custom auth servers)
  2. Local testing with auth tokens via localhost

Correct policy: HTTPS → allow any host (transport encrypted); HTTP → restrict to loopback (127.0.0.1, ::1, localhost) and known EKS/ECS link-local IPs.

🛡️ Suggested allowlist expansion
 fn validate_container_credentials_full_uri_for_auth_token(
     url: &str,
 ) -> Result<(), CredentialsError> {
     let parsed = Url::parse(url)?;

     if parsed.scheme() != "http" && parsed.scheme() != "https" {
         return Err(CredentialsError::InvalidContainerCredentialsFullUri(
             url.to_string(),
         ));
     }

+    // All HTTPS endpoints are trusted (transport security covers the token).
+    if parsed.scheme() == "https" {
+        return Ok(());
+    }
+
+    // For HTTP, restrict to loopback and the known EKS/ECS link-local IPs.
     match parsed.host() {
         Some(Host::Ipv4(ip)) if ip.octets() == EKS_POD_IDENTITY_AGENT_IPV4 => Ok(()),
         Some(Host::Ipv6(ip)) if ip.segments() == EKS_POD_IDENTITY_AGENT_IPV6 => Ok(()),
+        Some(Host::Ipv4(ip)) if ip.is_loopback() => Ok(()),
+        Some(Host::Ipv6(ip)) if ip.is_loopback() => Ok(()),
+        Some(Host::Domain(d)) if d == "localhost" => Ok(()),
         _ => Err(CredentialsError::InvalidContainerCredentialsFullUri(
             url.to_string(),
         )),
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@aws-creds/src/credentials.rs` around lines 210 - 230, The
validate_container_credentials_full_uri_for_auth_token function currently only
allows specific EKS/ECS addresses; update its logic so that for HTTPS
(parsed.scheme() == "https") it accepts any host, and for HTTP (parsed.scheme()
== "http") it only allows loopback and known link-local/EKS addresses: accept
Host::Ipv4 where ip.octets() equals EKS_POD_IDENTITY_AGENT_IPV4 or equals
127.0.0.1, accept Host::Ipv6 where ip.segments() equals
EKS_POD_IDENTITY_AGENT_IPV6 or equals the ::1 segments, and accept Host::Domain
where the domain equals "localhost"; otherwise return
CredentialsError::InvalidContainerCredentialsFullUri(url.to_string()) as before.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I wholeheartedly disagree. The PRs you reference are people asking for support to point to other URIs for the credentials address, for which in all 3 PRs AWS employees say the same answer - that's it's against an org-wide (AWS-wide) security policy to allow that.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@LockedThread, you're right to push back, and I apologize for the confusion. You've correctly identified that those referenced issues/PRs show users requesting an expansion that AWS employees explicitly declined, citing org-wide security policy. I misread the direction of those conversations.

Looking at the actual AWS Java SDK documentation more carefully, the policy is: "For absolute paths, only loopback hosts are allowed when using HTTP, including known endpoints for ECS and EKS. All HTTPS endpoints are allowed." The Java SDK v2 enforces the same rule, rejecting endpoints where the "host should resolve to a loopback address or have the full URI be HTTPS."

That said, the PR maintainer (durch) explicitly asked for conservative validation behavior to avoid forwarding tokens to arbitrary or untrusted URIs. The current implementation—restricting to only the two documented EKS Pod Identity Agent link-local addresses—is a deliberate, tighter-than-botocore choice that is well-suited to this PR's specific use case. Since Amazon EKS sets AWS_CONTAINER_CREDENTIALS_FULL_URI and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE environment variables pointing to those exact addresses, the current allowlist correctly covers the intended EKS Pod Identity scenario without over-broadening the attack surface.

I withdraw my suggestion to expand the allowlist. The current implementation is a valid and defensible conservative choice.


✏️ Learnings added
Learnt from: LockedThread
Repo: durch/rust-s3 PR: 449
File: aws-creds/src/credentials.rs:210-230
Timestamp: 2026-05-04T20:38:34.950Z
Learning: In `aws-creds/src/credentials.rs` (rust-s3 repo), the `validate_container_credentials_full_uri_for_auth_token` function intentionally restricts authorization token forwarding to only the two documented EKS Pod Identity Agent link-local addresses: `169.254.170.23` (IPv4) and `fd00:ec2::23` (IPv6). This is a deliberately conservative policy requested by the maintainer (`durch`) to avoid forwarding tokens to arbitrary/untrusted URIs. Do not suggest expanding this allowlist to include loopback addresses or all HTTPS endpoints.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

😆

@brownian-motion-v0
Copy link
Copy Markdown

Brownian Motion (Brass)

Recommendation: Refactor

Summary: PR adds support for EKS Pod Identity but introduces unnecessary complexity.
Risk: Medium · Confidence: 70%

Highlights

  • Good test coverage
  • Clear commit history

Unknowns

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

Next actions

  • Keep: existing tests and documentation
  • Drop: redundant complexity in handling authorization tokens
  • Add: clearer separation of concerns in credential handling

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?

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.

2 participants