feat: enable AWS login credentials for Bedrock auth (#21623)

## Summary

Codex's Amazon Bedrock provider signs Mantle requests with SigV4 using
credentials resolved by the AWS SDK. That worked for standard AWS
profiles and environment credentials, but AWS CLI console-login profiles
created by `aws login` require the SDK's `credentials-login` feature to
resolve `login_session` credentials.

This change enables that credential provider so Bedrock can use AWS
console-login credentials through the existing provider-owned AWS auth
path.

While testing the console-login path, we also hit a Mantle-specific
SigV4 regression from the new split between `session_id` and
`thread_id`. Mantle does not preserve legacy OpenAI compatibility
headers that use `snake_case` before SigV4 verification, so signing
those headers can make the server reconstruct a different canonical
request. The Bedrock auth path now removes that header class before
signing, keeping preserved hyphenated Codex/AWS headers such as
`x-codex-turn-metadata` signed normally.

## Changes

- Enable `aws-config`'s `credentials-login` feature in
`codex-rs/aws-auth`.
- Add a compile-time regression test for
`aws_config::login::LoginCredentialsProvider`.
- Strip `snake_case` compatibility headers from Bedrock Mantle SigV4
requests before signing.
- Expand the Bedrock auth regression test to cover `session_id`,
`thread_id`, and future headers of the same shape.
- Refresh Cargo and Bazel lockfiles for the added `aws-sdk-signin`
dependency.

## Tests
- tested with `aws login` locally and verified that it works as
intended.
This commit is contained in:
Celia Chen authored and GitHub committed 2026-05-08 04:07:59 +00:00
1 parent 314229fd72
commit 9cbd4c0371
4 files changed
+183 -9

No files matched your search

@@ -20,7 +20,6 @@ use super::mantle::aws_auth_config;
use super::mantle::region_from_config;
const AWS_BEARER_TOKEN_BEDROCK_ENV_VAR: &str = "AWS_BEARER_TOKEN_BEDROCK";
const LEGACY_SESSION_ID_HEADER: &str = "session_id";
pub(super) enum BedrockAuthMethod {
EnvBearerToken { token: String, region: String },
@@ -87,10 +86,18 @@ fn aws_auth_error_to_auth_error(error: AwsAuthError) -> AuthError {
}
fn remove_headers_not_preserved_by_bedrock_mantle(headers: &mut HeaderMap) {
// The Bedrock Mantle front door does not preserve this legacy OpenAI header
// for SigV4 verification. Signing it makes the richer Codex agent request
// fail even though raw Responses requests work.
headers.remove(LEGACY_SESSION_ID_HEADER);
// The Bedrock Mantle front door does not preserve legacy OpenAI
// compatibility headers that use snake_case, such as `session_id` and
// `thread_id`, before SigV4 verification. Signing that header class makes
// richer Codex agent requests fail even though raw Responses requests work.
let headers_to_remove = headers
.keys()
.filter(|name| name.as_str().contains('_'))
.cloned()
.collect::<Vec<_>>();
for name in headers_to_remove {
headers.remove(name);
}
}
/// AWS SigV4 auth provider for Bedrock Mantle OpenAI-compatible requests.
@@ -182,10 +189,18 @@ mod tests {
}
#[test]
fn bedrock_mantle_sigv4_strips_legacy_session_id_header() {
fn bedrock_mantle_sigv4_strips_headers_not_preserved_by_mantle() {
let mut headers = HeaderMap::new();
headers.insert(
LEGACY_SESSION_ID_HEADER,
"session_id",
HeaderValue::from_static("019dae79-15c3-70c3-8736-3219b8602b37"),
);
headers.insert(
"thread_id",
HeaderValue::from_static("019dae79-15c3-70c3-8736-3219b8602b37"),
);
headers.insert(
"future_identity_header",
HeaderValue::from_static("019dae79-15c3-70c3-8736-3219b8602b37"),
);
headers.insert(
@@ -195,7 +210,9 @@ mod tests {
remove_headers_not_preserved_by_bedrock_mantle(&mut headers);
assert!(!headers.contains_key(LEGACY_SESSION_ID_HEADER));
assert!(!headers.contains_key("session_id"));
assert!(!headers.contains_key("thread_id"));
assert!(!headers.contains_key("future_identity_header"));
assert_eq!(
headers
.get("x-client-request-id")