feat: add Bedrock Role ARN field in UI - #26578
Conversation
bb0b5d5 to
153d419
Compare
# Support IAM role assumption for AWS Bedrock in AI Bridge ## Summary Implements https://linear.app/codercom/issue/AIGOV-371/support-dynamic-bedrock-assumerole-across-aws-accounts-for-ai-gateway A Bedrock provider can now be configured with an IAM role to assume. Before calling Bedrock, the gateway assumes that role via STS and signs requests with the resulting temporary credentials. Whether the role lives in the same account or another one is entirely a matter of the role's trust policy. ## Problem Many organizations prohibit long-lived AWS access keys and expect workloads to authenticate through assumed IAM roles instead. A common case is an organization that runs Bedrock across several AWS accounts, one per business unit, and needs each unit's usage billed to its own account by assuming a role there. AI Bridge previously authenticated a Bedrock provider only with static keys or the gateway's own ambient AWS identity, which is shared by every provider, with no way to assume a role. These deployments had no clean path. ## How it works When a provider is configured with a role ARN, the gateway uses its base identity to assume that role via STS and signs Bedrock requests with the temporary credentials it returns. The base identity is whatever the AWS default credential chain resolves, IRSA, EKS Pod Identity, EC2 Instance Profile, or static keys. Credentials are resolved once when the provider is set up and are then cached and rotated, so individual requests are served from the cache rather than triggering a new STS call. A deployment that needs several roles configures several providers, each pointing at its own role. ## Configuration The role ARN is part of the Bedrock provider settings and is set through the AI provider API. It is optional: a provider with no role ARN behaves exactly as before. ## Scope and trade-offs - This PR is backend only. The settings UI for the role ARN ships in a follow-up. - Configuration is not exposed through environment variables. Environment-based provider configuration is being phased out in favor of database-managed providers, so the role ARN is intentionally database and API only. Follow-up PR: #26578
# Support IAM role assumption for AWS Bedrock in AI Bridge ## Summary Implements https://linear.app/codercom/issue/AIGOV-371/support-dynamic-bedrock-assumerole-across-aws-accounts-for-ai-gateway A Bedrock provider can now be configured with an IAM role to assume. Before calling Bedrock, the gateway assumes that role via STS and signs requests with the resulting temporary credentials. Whether the role lives in the same account or another one is entirely a matter of the role's trust policy. ## Problem Many organizations prohibit long-lived AWS access keys and expect workloads to authenticate through assumed IAM roles instead. A common case is an organization that runs Bedrock across several AWS accounts, one per business unit, and needs each unit's usage billed to its own account by assuming a role there. AI Bridge previously authenticated a Bedrock provider only with static keys or the gateway's own ambient AWS identity, which is shared by every provider, with no way to assume a role. These deployments had no clean path. ## How it works When a provider is configured with a role ARN, the gateway uses its base identity to assume that role via STS and signs Bedrock requests with the temporary credentials it returns. The base identity is whatever the AWS default credential chain resolves, IRSA, EKS Pod Identity, EC2 Instance Profile, or static keys. Credentials are resolved once when the provider is set up and are then cached and rotated, so individual requests are served from the cache rather than triggering a new STS call. A deployment that needs several roles configures several providers, each pointing at its own role. ## Configuration The role ARN is part of the Bedrock provider settings and is set through the AI provider API. It is optional: a provider with no role ARN behaves exactly as before. ## Scope and trade-offs - This PR is backend only. The settings UI for the role ARN ships in a follow-up. - Configuration is not exposed through environment variables. Environment-based provider configuration is being phased out in favor of database-managed providers, so the role ARN is intentionally database and API only. Follow-up PR: #26578
153d419 to
af1de6b
Compare
af1de6b to
537c24c
Compare
510937e to
afe0834
Compare
|
/coder-agents-review |
|
Chat: Review posted | View chat Review history
deep-review v0.9.0 | Round 1 | Last posted: Round 1, 2 findings (1 P3, 1 Nit), COMMENT. Review Finding inventoryFindings
Round logRound 1Panel. 1 P3, 2 P4, 1 Nit. Reviewed against c08b04a..afe0834. 13 reviewers (Bisky, Hisoka, Mafu-san, Mafuuu, Pariston, Gon, Leorio, Ging-ts, Ging-react, Nami, Komugi, Melody, Zoro). 9 of 13 returned no findings. Netero clean. About deep-reviewCRF = Coder Review Finding (P0-P4, Nit, Note)
|
Documentation CheckUpdates Needed
Automated review via Coder Agents |
There was a problem hiding this comment.
Clean, well-scoped addition. The mapping logic is correctly threaded through create, update, and read-back paths. The field follows the existing access-key pattern (conditional spread, .trim(), ?? "" fallback). Test coverage is strong: 7 new cases covering all three paths plus edge cases. Melody traced the full wire-format chain from Go struct through JSON to TypeScript and confirmed every pairing. Pariston verified each PR description claim against the code. 9 of 13 reviewers found nothing.
1 P3, 2 P4, 1 Nit.
P4 [CRF-2] ProviderForm.stories.tsx No Storybook play function asserts that the Role ARN field renders or accepts input. The existing AddBedrock and EditBedrockKeepCredentials stories implicitly render the field (it lives inside the Bedrock conditional block), but no play function queries it, checks its value, or types into it. The unit tests cover the mapping logic thoroughly; this is about the rendering-to-submit pipeline. The project convention says to use Storybook stories for component and page testing, including user interactions. A play function that fills in the Role ARN and verifies it reaches onSubmit would close the loop. (Bisky)
P4 [CRF-3] providerFormApiMap.test.ts No whitespace-trim test for roleArn on the update path. The create path has "trims whitespace around the role ARN" (line 429), but the update describe block has no symmetric test. Both paths call values.roleArn.trim() into the same buildBedrockSettings, so the risk is near zero. The gap breaks the symmetry the rest of the suite maintains between the create and update blocks. (Bisky)
Process note: the feature commit is feat: add Bedrock role ARN field while the test commit uses test(site): cover role_arn form mapping. Since all changed files are under site/, feat(site): add Bedrock role ARN field would match the project convention and the sibling commit.
"I tried to build a case against this and couldn't." (Pariston)
site/src/pages/AISettingsPage/ProvidersPage/components/ProviderForm.tsx:191
Nit [CRF-4] roleArn is the only ProviderFormValues field absent from makeBedrockSchema. Every other field has an entry, including apiKey: Yup.string() which Bedrock does not use. Adding roleArn: Yup.string() between accessKeySecret and enabled maintains the convention and provides a hook for future client-side ARN format validation (the backend already validates via validateAIProviderRoleARN).
(Zoro)
🤖
🤖 This review was automatically generated with Coder Agents.
| className="w-full" | ||
| placeholder="arn:aws:iam::123456789012:role/BedrockRole" | ||
| /> | ||
| <p className="text-xs text-content-secondary m-0"> |
There was a problem hiding this comment.
P3 [CRF-1] The Bedrock provider docs (docs/ai-coder/ai-gateway/providers.md, linked via "View docs" in the credentials section above) list SDK default credentials and static access keys but never mention role assumption, STS, or cross-account access. The backend already validates role ARNs (validateAIProviderRoleARN in codersdk/aiproviders.go:326), but none of the mechanism or required permissions reach the admin.
The inline help text here is functional but minimal. An admin configuring cross-account Bedrock access for the first time will click "View docs," find nothing about roles, and have to guess what permissions the assumed role needs (bedrock:InvokeModel, bedrock:InvokeModelWithResponseStream).
Consider adding a section under the Bedrock provider docs covering: what the Role ARN field does, when to use it (cross-account access), and what permissions the assumed role requires. This can be a separate docs PR.
(Leorio)
🤖
jakehwll
left a comment
There was a problem hiding this comment.
I think I agree with the coder-agent about how we describe this feature, but functionality-wise this is fine for frontend 🙂
|
@jakehwll I'll update docs in a separate PR. |
Adds a Role ARN field for the Bedrock provider in the UI. When set, the gateway assumes that IAM role (using the base identity) before calling Bedrock. The field is optional and non-secret, so it round-trips back into the form on edit and clears when left blank.
Related PR: #26527
Related issue: https://linear.app/codercom/issue/AIGOV-371/support-dynamic-bedrock-assumerole-across-aws-accounts-for-ai-gateway