fix(bedrock): resolve realtime AWS credentials from config, not just env - #32257
fix(bedrock): resolve realtime AWS credentials from config, not just env#32257devin-ai-integration[bot] wants to merge 2 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Greptile SummaryThis PR replaces the
Confidence Score: 4/5Safe to merge; the credential fix is correct and all aws_* config params are properly forwarded through the existing boto3 resolution chain. The core fix is sound: BotoCredentialsResolver correctly adapts the boto3 frozen credentials object to the smithy identity interface, and get_credentials() already handles every auth flow (static keys, session tokens, role assumption, web identity, profiles) with env-var fallback. The only concern is that get_frozen_credentials() inside the async get_identity() method is a synchronous botocore call that can block the event loop when refreshable credentials expire mid-session and a network round-trip to STS is needed. litellm/llms/bedrock/realtime/handler.py — specifically the get_identity method in BotoCredentialsResolver
|
| Filename | Overview |
|---|---|
| litellm/llms/bedrock/realtime/handler.py | Replaces EnvironmentCredentialsResolver with BotoCredentialsResolver; get_frozen_credentials() in get_identity() is a synchronous blocking call that could stall the event loop for refreshable credentials (role assumption, web identity) when mid-session token refresh occurs. |
| tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py | Adds two well-scoped regression tests: one for BotoCredentialsResolver mapping and one for end-to-end credential forwarding through async_realtime; all mocked, no real network calls. |
Reviews (1): Last reviewed commit: "fix(bedrock): resolve realtime AWS crede..." | Re-trigger Greptile
| async def get_identity(self, *, properties: Any) -> Any: | ||
| from smithy_aws_core.identity import AWSCredentialsIdentity | ||
|
|
||
| frozen = self._credentials.get_frozen_credentials() | ||
| return AWSCredentialsIdentity( | ||
| access_key_id=frozen.access_key, | ||
| secret_access_key=frozen.secret_key, | ||
| session_token=frozen.token, | ||
| ) |
There was a problem hiding this comment.
get_frozen_credentials() is a synchronous botocore call inside an async method. For RefreshableCredentials (produced by role assumption, web identity, or profile auth), an expired token triggers a synchronous STS HTTP request here, which will block the asyncio event loop for the duration of that network round-trip. Static key credentials are unaffected since get_frozen_credentials() is instant for them, but long-running WebSocket sessions with role-assumed credentials will hit this on every credential refresh cycle.
| async def get_identity(self, *, properties: Any) -> Any: | |
| from smithy_aws_core.identity import AWSCredentialsIdentity | |
| frozen = self._credentials.get_frozen_credentials() | |
| return AWSCredentialsIdentity( | |
| access_key_id=frozen.access_key, | |
| secret_access_key=frozen.secret_key, | |
| session_token=frozen.token, | |
| ) | |
| async def get_identity(self, *, properties: Any) -> Any: | |
| import asyncio | |
| from smithy_aws_core.identity import AWSCredentialsIdentity | |
| loop = asyncio.get_event_loop() | |
| frozen = await loop.run_in_executor(None, self._credentials.get_frozen_credentials) | |
| return AWSCredentialsIdentity( | |
| access_key_id=frozen.access_key, | |
| secret_access_key=frozen.secret_key, | |
| session_token=frozen.token, | |
| ) |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…realtime resolver Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
Closing: superseded by #32275, which landed the same config-credential fix |
Relevant issues
Follow-up to #31924. The Nova Sonic realtime handler built its smithy client with
EnvironmentCredentialsResolver, which only readsAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYfrom the process environment. Anyaws_access_key_id,aws_secret_access_key,aws_session_token,aws_role_name,aws_profile_name,aws_web_identity_token, etc. set in the proxy config'slitellm_paramswere silently ignored, so realtime sessions failed unless ambient env credentials happened to existThis change routes the params (already plumbed through
realtime_api/main.pyintoBedrockRealtime.async_realtime) throughBaseAWSLLM.get_credentials, the same boto3-based resolution every other Bedrock endpoint uses (static keys, session tokens, role assumption, profiles, web identity), and adapts the resulting boto3 credentials to the smithy client via a smallBotoCredentialsResolver. When no config params are set,get_credentialsfalls back to the standard boto3 chain, which still covers env vars, so existing env-based setups keep working. The resolver freezes credentials viarun_in_executorso a refreshable-credentials STS call never blocks the event loopLinear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewScreenshots / Proof of Fix
No AWS credentials were available in this session, so a live Bedrock run wasn't possible. To verify against the real API, put keys only in the config (none in env) and run the same qa_client.py flow from #31924:
Before this PR the session dies with
SmithyIdentityError: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are required; after it, the client receivesresponse.text.deltaevents and a finalresponse.doneRegression tests pin both halves:
BotoCredentialsResolvermaps frozen boto3 credentials to a smithyAWSCredentialsIdentity, andasync_realtimeforwards all config aws_* params intoget_credentialsand wires the resulting resolver into the client configType
🐛 Bug Fix
Changes
litellm/llms/bedrock/realtime/handler.py: replaceEnvironmentCredentialsResolverwithBotoCredentialsResolver(self.get_credentials(aws_access_key_id=..., aws_role_name=..., ...))tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py: regression tests for the credential pathLink to Devin session: https://app.devin.ai/sessions/9c6563e5a0834358aa1db302935bb36f
Requested by: @mateo-berri