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
2026-05-07 21:07:59 -07:00
committed by GitHub
Unverified
parent 314229fd72
commit 9cbd4c0371
4 changed files with 183 additions and 9 deletions
+11
View File
File diff suppressed because one or more lines are too long
+146
View File
@@ -757,6 +757,7 @@ checksum = "96571e6996817bf3d58f6b569e4b9fd2e9d2fcf9f7424eed07b2ce9bb87535e5"
dependencies = [
"aws-credential-types",
"aws-runtime",
"aws-sdk-signin",
"aws-sdk-sso",
"aws-sdk-ssooidc",
"aws-sdk-sts",
@@ -767,15 +768,20 @@ dependencies = [
"aws-smithy-runtime-api",
"aws-smithy-types",
"aws-types",
"base64-simd",
"bytes",
"fastrand",
"hex",
"http 1.4.0",
"p256",
"rand 0.8.5",
"ring",
"sha2",
"time",
"tokio",
"tracing",
"url",
"uuid",
"zeroize",
]
@@ -838,6 +844,28 @@ dependencies = [
"uuid",
]
[[package]]
name = "aws-sdk-signin"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c084bd63941916e1348cb8d9e05ac2e49bdd40a380e9167702683184c6c6be53"
dependencies = [
"aws-credential-types",
"aws-runtime",
"aws-smithy-async",
"aws-smithy-http",
"aws-smithy-json",
"aws-smithy-runtime",
"aws-smithy-runtime-api",
"aws-smithy-types",
"aws-types",
"bytes",
"fastrand",
"http 0.2.12",
"regex-lite",
"tracing",
]
[[package]]
name = "aws-sdk-sso"
version = "1.91.0"
@@ -1180,6 +1208,12 @@ dependencies = [
"windows-link",
]
[[package]]
name = "base16ct"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64"
version = "0.21.7"
@@ -4415,6 +4449,18 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]]
name = "crypto-bigint"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
dependencies = [
"generic-array",
"rand_core 0.6.4",
"subtle",
"zeroize",
]
[[package]]
name = "crypto-common"
version = "0.1.7"
@@ -5128,6 +5174,20 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "ecdsa"
version = "0.16.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
dependencies = [
"der",
"digest",
"elliptic-curve",
"rfc6979",
"signature",
"spki",
]
[[package]]
name = "ed25519"
version = "2.2.3"
@@ -5161,6 +5221,26 @@ dependencies = [
"serde",
]
[[package]]
name = "elliptic-curve"
version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
dependencies = [
"base16ct",
"crypto-bigint",
"digest",
"ff",
"generic-array",
"group",
"pem-rfc7468",
"pkcs8",
"rand_core 0.6.4",
"sec1",
"subtle",
"zeroize",
]
[[package]]
name = "ena"
version = "0.14.3"
@@ -5414,6 +5494,16 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "ff"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
dependencies = [
"rand_core 0.6.4",
"subtle",
]
[[package]]
name = "fiat-crypto"
version = "0.2.9"
@@ -6808,6 +6898,17 @@ dependencies = [
"system-deps",
]
[[package]]
name = "group"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
dependencies = [
"ff",
"rand_core 0.6.4",
"subtle",
]
[[package]]
name = "gzip-header"
version = "1.0.0"
@@ -9307,6 +9408,18 @@ dependencies = [
"supports-color 3.0.2",
]
[[package]]
name = "p256"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
dependencies = [
"ecdsa",
"elliptic-curve",
"primeorder",
"sha2",
]
[[package]]
name = "parking"
version = "2.2.1"
@@ -9736,6 +9849,15 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "primeorder"
version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
dependencies = [
"elliptic-curve",
]
[[package]]
name = "proc-macro-crate"
version = "3.4.0"
@@ -10686,6 +10808,16 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7"
[[package]]
name = "rfc6979"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
dependencies = [
"hmac",
"subtle",
]
[[package]]
name = "ring"
version = "0.17.14"
@@ -11145,6 +11277,20 @@ version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
[[package]]
name = "sec1"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
dependencies = [
"base16ct",
"der",
"generic-array",
"pkcs8",
"subtle",
"zeroize",
]
[[package]]
name = "seccompiler"
version = "0.5.0"
+1 -1
View File
@@ -13,7 +13,7 @@ path = "src/lib.rs"
workspace = true
[dependencies]
aws-config = { workspace = true }
aws-config = { workspace = true, features = ["credentials-login"] }
aws-credential-types = { workspace = true }
aws-sigv4 = { workspace = true }
aws-types = { workspace = true }
@@ -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")