Skip to content

fix(bedrock): honor AWS auth params in realtime handler - #32275

Merged
mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_fix_bedrock_realtime_aws_auth
Jul 6, 2026
Merged

fix(bedrock): honor AWS auth params in realtime handler#32275
mateo-berri merged 2 commits into
litellm_internal_stagingfrom
litellm_fix_bedrock_realtime_aws_auth

Conversation

@mateo-berri

@mateo-berri mateo-berri commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

Linear ticket

Resolves LIT-3923

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Both runs below hit a live proxy on localhost against the real Bedrock Nova Sonic model in us-east-1, with AWS credentials supplied only through litellm_params under non-standard env var names; every standard AWS_* credential variable was scrubbed from the proxy environment before launch. Before is the merge-base commit b4a10fb, after is this branch at 489e94b. The config, launcher, and client are byte-identical across the two arms; only the checkout changes

Config (qa_config.yaml):

model_list:
  - model_name: bedrock-sonic
    litellm_params:
      model: bedrock/amazon.nova-sonic-v1:0
      aws_region_name: us-east-1
      aws_access_key_id: os.environ/LIT3923_QA_KEY_ID
      aws_secret_access_key: os.environ/LIT3923_QA_SECRET
      aws_session_token: os.environ/LIT3923_QA_SESSION
    model_info:
      mode: realtime

general_settings:
  master_key: sk-qa-lit3923

Proxy launcher (run_proxy_qa.sh), which loads session credentials produced by aws configure export-credentials --format env, re-exports them under the non-standard names the config reads, and unsets every standard AWS variable before starting the proxy:

. ./qa_creds.env
export LIT3923_QA_KEY_ID="$AWS_ACCESS_KEY_ID"
export LIT3923_QA_SECRET="$AWS_SECRET_ACCESS_KEY"
export LIT3923_QA_SESSION="$AWS_SESSION_TOKEN"
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \
    AWS_CREDENTIAL_EXPIRATION AWS_PROFILE AWS_DEFAULT_PROFILE \
    AWS_BEARER_TOKEN_BEDROCK AWS_REGION AWS_DEFAULT_REGION
env | grep -oE '^(AWS|LIT3923)[A-Z0-9_]*' | sort
exec .venv/bin/python litellm/proxy/proxy_cli.py --config qa_config.yaml --port 56759 --detailed_debug

Env check printed at proxy start, identical in both arms, confirming no standard AWS_* credential vars remain in the proxy environment:

LIT3923_QA_KEY_ID
LIT3923_QA_SECRET
LIT3923_QA_SESSION

The client (qa_realtime_client.py) opens ws://localhost:56759/v1/realtime?model=bedrock-sonic authenticated with the master key, sends session.update (text modalities), one conversation.item.create user message "Say hello in one sentence.", then response.create, and prints every received event type with a 60 second overall timeout

Before, at merge-base b4a10fb: the session connects and then hangs silently, zero events in 60 seconds

$ git checkout b4a10fb134
$ ./run_proxy_qa.sh 56759 > proxy_before.log 2>&1 &
$ .venv/bin/python qa_realtime_client.py 56759
CONNECTED
VERDICT: TIMED OUT after 60s partial_text=''

The before proxy log confirms the hang; this is the last Bedrock realtime line, the stream is never established and no error is surfaced:

14:19:04 - LiteLLM Proxy:DEBUG: handler.py:83 - Bedrock Realtime: Connecting to https://bedrock-runtime.us-east-1.amazonaws.com with model amazon.nova-sonic-v1:0

After, on this branch at 489e94b, same config, same launcher, same client:

$ git checkout 489e94b92d
$ ./run_proxy_qa.sh 56759 > proxy_after.log 2>&1 &
$ .venv/bin/python qa_realtime_client.py 56759
CONNECTED
EVENT: response.created
EVENT: response.output_item.added
EVENT: response.content_part.added
EVENT: response.text.delta
EVENT: response.text.done
EVENT: response.content_part.done
EVENT: response.output_item.done
EVENT: response.created
EVENT: response.output_item.added
EVENT: response.content_part.added
EVENT: response.audio.delta
[EVENT: response.audio.delta repeated 59 times total, trimmed]
EVENT: response.audio.done
EVENT: response.content_part.done
EVENT: response.output_item.done
EVENT: response.done
VERDICT: RESPONSE RECEIVED: "Hello there! I'm ready to chat. What's on your mind today?"

The after proxy log shows the stream opening with the litellm_params credentials:

14:21:15 - LiteLLM Proxy:DEBUG: handler.py:81 - Bedrock Realtime: Connecting to https://bedrock-runtime.us-east-1.amazonaws.com with model amazon.nova-sonic-v1:0
14:21:15 - LiteLLM Proxy:DEBUG: handler.py:115 - Bedrock Realtime: Bidirectional stream established

Type

🐛 Bug Fix

Changes

The Bedrock Nova Sonic realtime handler (litellm/llms/bedrock/realtime/handler.py, backing /v1/realtime) accepted every standard AWS auth param in async_realtime (aws_access_key_id, aws_secret_access_key, aws_session_token, aws_role_name, aws_session_name, aws_profile_name, aws_web_identity_token, aws_sts_endpoint, aws_external_id) but ignored all of them: the Smithy client config was built with a hardcoded aws_credentials_identity_resolver=EnvironmentCredentialsResolver(), which only ever reads the ambient AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY environment variables. Credentials supplied via litellm_params were silently dropped and the session hung at stream open with zero events and no error

The fix resolves credentials with the same machinery every other Bedrock path uses: BaseAWSLLM.get_credentials(...), which handles static keys, session tokens, role assumption via STS, web identity tokens (IRSA), named profiles, and falls back to the boto3 default chain when nothing is configured. The resolved credentials are frozen and fed to the Smithy Config as aws_access_key_id/aws_secret_access_key/aws_session_token alongside the SDK's own StaticCredentialsResolver; this is the smithy_aws_core static-credentials flow, where the SigV4 auth scheme builds identity properties from those config fields and the resolver returns them as the AWSCredentialsIdentity used for signing

This makes static keys stored under non-standard env names, role assumption (aws_role_name/aws_session_name/aws_external_id), web identity auth, profile auth, and STS endpoint overrides work for the realtime endpoint. When no aws params are given, behavior is now the boto3 default credential chain, consistent with bedrock chat/converse and strictly more capable than the previous env-only behavior. The optional-import error message for aws_sdk_bedrock_runtime is unchanged

Regression tests in tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py stub the optional aws_sdk_bedrock_runtime/smithy_aws_core modules in sys.modules and assert that static credentials passed to async_realtime reach the captured Smithy config through the real get_credentials path, and that role-assumption params are forwarded to get_credentials with the resolved credentials landing on the config; both tests fail on the base branch and pass with the fix

Follow-up commit c89bffc: when get_credentials resolves nothing anywhere (returns None), the handler now raises a BedrockError with a clear message ("No AWS credentials found for Bedrock realtime") instead of an obscure AttributeError on get_frozen_credentials; covered by a regression test that fails on the previous commit

@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

@greptile-apps

greptile-apps Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the Bedrock Nova Sonic realtime handler so that AWS credentials supplied via litellm_params are actually used when signing requests, replacing a hardcoded EnvironmentCredentialsResolver() that silently dropped all configured auth params and caused sessions to hang.

  • Handler fix: async_realtime now calls BaseAWSLLM.get_credentials() with all provided auth params (static keys, role assumption, web identity, profile, STS endpoint), freezes the result, and passes it into the Smithy Config along with StaticCredentialsResolver(). A None guard raises a descriptive BedrockError(401) instead of an obscure AttributeError.
  • Tests: Three new regression tests in TestBedrockRealtimeAwsAuth stub the Smithy/bedrock-runtime SDK modules, clear all ambient AWS env vars, and assert that credentials flow end-to-end to the Config kwargs, that role-assumption params are forwarded correctly, and that unresolvable credentials surface a clear error.

Confidence Score: 5/5

Safe to merge — the change is confined to the realtime handler's credential-resolution step, is consistent with every other Bedrock code path in the repo, and is backed by live QA evidence plus three targeted regression tests.

The replacement of EnvironmentCredentialsResolver with the shared get_credentials() + StaticCredentialsResolver pattern is a straightforward, well-scoped fix. The None guard prevents the AttributeError regression. Tests are new (not modifications of existing assertions) and exercise the real code path with the AWS SDK modules stubbed out. No pre-existing functionality is altered.

No files require special attention.

Important Files Changed

Filename Overview
litellm/llms/bedrock/realtime/handler.py Replaces hardcoded EnvironmentCredentialsResolver with the shared BaseAWSLLM.get_credentials() path, adds a None guard that raises a clear BedrockError(401) instead of an AttributeError, and wires the frozen credentials into the Smithy Config alongside StaticCredentialsResolver().
tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py Adds a stub_aws_sdk_client fixture and three regression tests covering static credentials, role-assumption param forwarding, and unresolvable-credential error handling; all use mocked AWS SDK modules with no real network calls.

Reviews (3): Last reviewed commit: "fix(bedrock): raise clear auth error whe..." | Re-trigger Greptile

Comment thread litellm/llms/bedrock/realtime/handler.py Outdated
@greptile-apps

greptile-apps Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the Bedrock Nova Sonic realtime handler to honour AWS auth params (static keys, role assumption, web identity, profiles) supplied via litellm_params, replacing the hardcoded EnvironmentCredentialsResolver with BaseAWSLLM.get_credentials(...) — the same credential machinery used by every other Bedrock path. The resolved boto3 credentials are then fed into the Smithy Config alongside a StaticCredentialsResolver.

  • Core logic change (handler.py): get_credentials(...) is now called with all auth params before constructing the Smithy Config; EnvironmentCredentialsResolver is removed and StaticCredentialsResolver is substituted.
  • New tests (test_bedrock_realtime_handler.py): Two new async tests stub the optional SDK modules in sys.modules and verify that credentials reach the captured Config kwargs and that role-assumption params are forwarded to get_credentials.

Confidence Score: 3/5

The handler change solves the right problem but the Smithy credential resolver wiring needs verification before merging — if StaticCredentialsResolver requires a credentials argument, the fix will fail at runtime for every realtime request.

The intent and the get_credentials delegation are correct, but StaticCredentialsResolver() is instantiated with no arguments while research on the smithy_aws_core SDK indicates it expects an AWSCredentialsIdentity (or equivalent) at construction time. The test suite stubs the resolver with FakeStaticCredentialsResolver that accepts no args, so the production path is not exercised and would raise TypeError on every request. The raw Config fields (aws_access_key_id etc.) may also be unrecognised by the Smithy Config constructor and silently ignored.

litellm/llms/bedrock/realtime/handler.py lines 97–104 — the StaticCredentialsResolver constructor call and how credentials are passed to the Smithy Config need to be validated against the actual smithy_aws_core API (and confirmed with a live end-to-end test).

Important Files Changed

Filename Overview
litellm/llms/bedrock/realtime/handler.py Replaces hardcoded EnvironmentCredentialsResolver with boto3-resolved credentials via get_credentials(), but uses StaticCredentialsResolver() with no constructor arguments — likely incorrect per smithy_aws_core API, which requires credentials to be passed to the resolver's constructor.
tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py New tests stub aws_sdk_bedrock_runtime and smithy_aws_core correctly; however FakeStaticCredentialsResolver takes no constructor arguments, which masks the fact that the real StaticCredentialsResolver likely requires an AWSCredentialsIdentity argument.

Reviews (2): Last reviewed commit: "fix(bedrock): honor AWS auth params in r..." | Re-trigger Greptile

Comment thread litellm/llms/bedrock/realtime/handler.py
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

@mateo-berri
mateo-berri merged commit c5454af into litellm_internal_staging Jul 6, 2026
123 of 124 checks passed
@mateo-berri
mateo-berri deleted the litellm_fix_bedrock_realtime_aws_auth branch July 6, 2026 23:16
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