Skip to content

Commit 4d881a8

Browse files
authored
feat: prefer AWS-native auth naming (#5939)
# What does this PR do? Rename Bedrock provider config fields from generic names (`api_key`, `aws_bearer_token_bedrock`) to AWS-native names (`aws_bedrock_bearer_token`) so the OpenAI-compatible Bedrock path reads like an AWS credential-chain integration by default. Legacy field names are preserved through Pydantic `AliasChoices` for backward compatibility. Related: #4730, #5388 Files changed: - `config.py` -- rename `auth_credential` alias to `aws_bedrock_bearer_token` with `AliasChoices("aws_bedrock_bearer_token", "api_key")` for backward compat - `config.py` (BedrockProviderDataValidator) -- add `AliasChoices("aws_bedrock_bearer_token", "aws_bearer_token_bedrock")` for provider-data headers - `bedrock.py` -- update `provider_data_api_key_field` and `_should_use_sigv4()` to use the new field name - `registry/inference.py` -- update provider description text - `ci-tests/config.yaml`, `ci-tests/run-with-postgres-store.yaml`, `starter/config.yaml`, `starter/run-with-postgres-store.yaml` -- rename field and env var to `aws_bedrock_bearer_token` / `AWS_BEDROCK_BEARER_TOKEN` - `remote_bedrock.mdx` -- updated provider documentation - `test_sigv4_auth.py`, `test_bedrock_adapter.py`, `test_bedrock_config.py` -- updated to use new field names, added legacy alias tests ## Test Plan Unit tests covering new canonical names and legacy aliases (43 passed): ~~~bash uv run pytest tests/unit/providers/inference/bedrock/test_sigv4_auth.py \ tests/unit/providers/inference/test_bedrock_adapter.py \ tests/unit/providers/inference/test_bedrock_config.py -q ~~~ Live Bedrock smoke tests against a local OGX server in `us-east-2` with SigV4 fallback and tested below successfully: `/v1/models` discovery, OpenAI client non-streaming and streaming, empty/whitespace/null bearer override fallback to SigV4 (both `aws_bedrock_bearer_token` and legacy `aws_bearer_token_bedrock`), invalid bearer rejection with token-leak check, valid bearer override with a real short-lived token (both keys), concurrent request auth isolation mixing SigV4 and bearer paths, repeated request smoke. <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/ogx-ai/ogx/pull/5939" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open in Devin Review"> </picture> </a> <!-- devin-review-badge-end --> Signed-off-by: skamenan7 <skamenan@redhat.com>
1 parent a7099cd commit 4d881a8

11 files changed

Lines changed: 79 additions & 38 deletions

File tree

docs/docs/providers/inference/remote_bedrock.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: "AWS Bedrock inference provider using OpenAI compatible endpoint."
2+
description: "AWS Bedrock inference provider for the OpenAI-compatible runtime, with AWS credential-chain auth by default and an optional bearer-token override."
33
sidebar_label: Remote - Bedrock
44
title: remote::bedrock
55
---
@@ -8,15 +8,15 @@ title: remote::bedrock
88

99
## Description
1010

11-
AWS Bedrock inference provider using OpenAI compatible endpoint.
11+
AWS Bedrock inference provider for the OpenAI-compatible runtime, with AWS credential-chain auth by default and an optional bearer-token override.
1212

1313
## Configuration
1414

1515
| Field | Type | Required | Default | Description |
1616
|-------|------|----------|---------|-------------|
1717
| `allowed_models` | `list[str] \| None` | No | | List of models that should be registered with the model registry. If None, all models are allowed. |
1818
| `refresh_models` | `bool` | No | False | Whether to refresh models periodically from the provider |
19-
| `api_key` | `SecretStr \| None` | No | | Authentication credential for the provider |
19+
| `aws_bedrock_bearer_token` | `SecretStr \| None` | No | | Optional bearer token for Amazon Bedrock's OpenAI-compatible runtime. Leave unset to use the server's AWS credential chain (recommended). |
2020
| `network` | `NetworkConfig \| None` | No | | Network configuration including TLS, proxy, and timeout settings. |
2121
| `network.tls` | `TLSConfig \| None` | No | | TLS/SSL configuration for secure connections. |
2222
| `network.tls.verify` | `bool \| Path` | No | True | Whether to verify TLS certificates. Can be a boolean or a path to a CA certificate file. |
@@ -51,7 +51,7 @@ AWS Bedrock inference provider using OpenAI compatible endpoint.
5151
## Sample Configuration
5252

5353
```yaml
54-
api_key: ${env.AWS_BEARER_TOKEN_BEDROCK:=}
54+
aws_bedrock_bearer_token: ${env.AWS_BEDROCK_BEARER_TOKEN:=}
5555
region_name: ${env.AWS_DEFAULT_REGION:=us-east-2}
5656
aws_role_arn: ${env.AWS_ROLE_ARN:=}
5757
aws_web_identity_token_file: ${env.AWS_WEB_IDENTITY_TOKEN_FILE:=}

src/ogx/distributions/ci-tests/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ providers:
4343
- provider_id: bedrock
4444
provider_type: remote::bedrock
4545
config:
46-
api_key: ${env.AWS_BEARER_TOKEN_BEDROCK:=}
46+
aws_bedrock_bearer_token: ${env.AWS_BEDROCK_BEARER_TOKEN:=}
4747
region_name: ${env.AWS_DEFAULT_REGION:=us-east-2}
4848
aws_role_arn: ${env.AWS_ROLE_ARN:=}
4949
aws_web_identity_token_file: ${env.AWS_WEB_IDENTITY_TOKEN_FILE:=}

src/ogx/distributions/ci-tests/run-with-postgres-store.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ providers:
4343
- provider_id: bedrock
4444
provider_type: remote::bedrock
4545
config:
46-
api_key: ${env.AWS_BEARER_TOKEN_BEDROCK:=}
46+
aws_bedrock_bearer_token: ${env.AWS_BEDROCK_BEARER_TOKEN:=}
4747
region_name: ${env.AWS_DEFAULT_REGION:=us-east-2}
4848
aws_role_arn: ${env.AWS_ROLE_ARN:=}
4949
aws_web_identity_token_file: ${env.AWS_WEB_IDENTITY_TOKEN_FILE:=}

src/ogx/distributions/starter/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ providers:
4343
- provider_id: bedrock
4444
provider_type: remote::bedrock
4545
config:
46-
api_key: ${env.AWS_BEARER_TOKEN_BEDROCK:=}
46+
aws_bedrock_bearer_token: ${env.AWS_BEDROCK_BEARER_TOKEN:=}
4747
region_name: ${env.AWS_DEFAULT_REGION:=us-east-2}
4848
aws_role_arn: ${env.AWS_ROLE_ARN:=}
4949
aws_web_identity_token_file: ${env.AWS_WEB_IDENTITY_TOKEN_FILE:=}

src/ogx/distributions/starter/run-with-postgres-store.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ providers:
4343
- provider_id: bedrock
4444
provider_type: remote::bedrock
4545
config:
46-
api_key: ${env.AWS_BEARER_TOKEN_BEDROCK:=}
46+
aws_bedrock_bearer_token: ${env.AWS_BEDROCK_BEARER_TOKEN:=}
4747
region_name: ${env.AWS_DEFAULT_REGION:=us-east-2}
4848
aws_role_arn: ${env.AWS_ROLE_ARN:=}
4949
aws_web_identity_token_file: ${env.AWS_WEB_IDENTITY_TOKEN_FILE:=}

src/ogx/providers/registry/inference.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ def available_providers() -> list[ProviderSpec]:
125125
module="ogx.providers.remote.inference.bedrock",
126126
config_class="ogx.providers.remote.inference.bedrock.BedrockConfig",
127127
provider_data_validator="ogx.providers.remote.inference.bedrock.config.BedrockProviderDataValidator",
128-
description="AWS Bedrock inference provider using OpenAI compatible endpoint.",
128+
description=(
129+
"AWS Bedrock inference provider for the OpenAI-compatible runtime, "
130+
"with AWS credential-chain auth by default and an optional bearer-token override."
131+
),
129132
),
130133
RemoteProviderSpec(
131134
api=Api.inference,

src/ogx/providers/remote/inference/bedrock/bedrock.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ class BedrockInferenceAdapter(OpenAIMixin):
4848
Supports Llama models across regions and GPT-OSS models (us-west-2 only).
4949
5050
Authentication modes:
51-
1. Bearer token (legacy): Set AWS_BEARER_TOKEN_BEDROCK or api_key in config
52-
2. AWS credential chain (enterprise): Leave api_key unset, configure AWS creds
51+
1. AWS credential chain (recommended): Leave aws_bedrock_bearer_token unset
52+
and configure AWS credentials for the server environment
5353
- Web Identity Federation (IRSA, GitHub Actions OIDC)
5454
- IAM roles (EC2, ECS, Lambda)
5555
- AWS profiles
5656
- Static credentials
57+
2. Bearer token (optional compatibility mode): Set aws_bedrock_bearer_token in
58+
config or pass it per request in x-ogx-provider-data
5759
5860
When using AWS credential chain, requests are signed using SigV4 with the
5961
"bedrock" signing name (note: the endpoint hostname uses "bedrock-runtime",
@@ -88,7 +90,7 @@ class BedrockInferenceAdapter(OpenAIMixin):
8890
for dynamic model discovery. Models must be pre-registered in the config.
8991
"""
9092

91-
provider_data_api_key_field: str | None = "aws_bearer_token_bedrock"
93+
provider_data_api_key_field: str | None = "aws_bedrock_bearer_token"
9294

9395
# built once in initialize() so get_extra_client_params() can stay sync;
9496
# reusing one client also avoids opening a new socket per request
@@ -112,8 +114,8 @@ def _should_use_sigv4(self) -> bool:
112114
return False
113115

114116
provider_data = self.get_request_provider_data()
115-
if provider_data and provider_data.aws_bearer_token_bedrock is not None:
116-
val = provider_data.aws_bearer_token_bedrock.get_secret_value()
117+
if provider_data and provider_data.aws_bedrock_bearer_token is not None:
118+
val = provider_data.aws_bedrock_bearer_token.get_secret_value()
117119
if val and val.strip():
118120
return False
119121

src/ogx/providers/remote/inference/bedrock/config.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,22 @@
66

77
import os
88

9-
from pydantic import BaseModel, Field, SecretStr
9+
from pydantic import AliasChoices, BaseModel, Field, SecretStr
1010

1111
from ogx.providers.utils.bedrock.config import BedrockBaseConfig
1212

1313

1414
class BedrockProviderDataValidator(BaseModel):
1515
"""Validates provider-specific request data for AWS Bedrock inference."""
1616

17-
aws_bearer_token_bedrock: SecretStr | None = Field(
17+
aws_bedrock_bearer_token: SecretStr | None = Field(
1818
default=None,
19-
description="API Key (Bearer token) for Amazon Bedrock",
19+
alias="aws_bedrock_bearer_token",
20+
validation_alias=AliasChoices("aws_bedrock_bearer_token", "aws_bearer_token_bedrock"),
21+
description=(
22+
"Optional per-request bearer token for Amazon Bedrock's OpenAI-compatible runtime. "
23+
"Leave unset to use the server's AWS credential chain instead."
24+
),
2025
)
2126

2227

@@ -25,8 +30,12 @@ class BedrockConfig(BedrockBaseConfig):
2530

2631
auth_credential: SecretStr | None = Field(
2732
default=None,
28-
description="Authentication credential for the provider",
29-
alias="api_key",
33+
alias="aws_bedrock_bearer_token",
34+
validation_alias=AliasChoices("aws_bedrock_bearer_token", "api_key"),
35+
description=(
36+
"Optional bearer token for Amazon Bedrock's OpenAI-compatible runtime. "
37+
"Leave unset to use the server's AWS credential chain (recommended)."
38+
),
3039
)
3140
# Override region_name to default to us-east-2 when unset
3241
region_name: str | None = Field(
@@ -44,7 +53,7 @@ def has_bearer_token(self) -> bool:
4453
@classmethod
4554
def sample_run_config(cls, **kwargs):
4655
return {
47-
"api_key": "${env.AWS_BEARER_TOKEN_BEDROCK:=}",
56+
"aws_bedrock_bearer_token": "${env.AWS_BEDROCK_BEARER_TOKEN:=}",
4857
"region_name": "${env.AWS_DEFAULT_REGION:=us-east-2}",
4958
"aws_role_arn": "${env.AWS_ROLE_ARN:=}",
5059
"aws_web_identity_token_file": "${env.AWS_WEB_IDENTITY_TOKEN_FILE:=}",

tests/unit/providers/inference/bedrock/test_sigv4_auth.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,13 @@ def test_has_bearer_token_with_token(self):
174174
"""Config should detect when bearer token is present."""
175175
from ogx.providers.remote.inference.bedrock.config import BedrockConfig
176176

177-
# Use api_key as that's the alias for auth_credential
177+
config = BedrockConfig(aws_bedrock_bearer_token="my-bearer-token")
178+
assert config.has_bearer_token() is True
179+
180+
def test_has_bearer_token_with_legacy_api_key_alias(self):
181+
"""Config should keep accepting the legacy api_key alias."""
182+
from ogx.providers.remote.inference.bedrock.config import BedrockConfig
183+
178184
config = BedrockConfig(api_key="my-bearer-token")
179185
assert config.has_bearer_token() is True
180186

@@ -189,14 +195,14 @@ def test_has_bearer_token_with_empty_string(self):
189195
"""Empty string should be treated as no token."""
190196
from ogx.providers.remote.inference.bedrock.config import BedrockConfig
191197

192-
config = BedrockConfig(api_key="")
198+
config = BedrockConfig(aws_bedrock_bearer_token="")
193199
assert config.has_bearer_token() is False
194200

195201
def test_has_bearer_token_with_whitespace(self):
196202
"""Whitespace-only string should be treated as no token."""
197203
from ogx.providers.remote.inference.bedrock.config import BedrockConfig
198204

199-
config = BedrockConfig(api_key=" ")
205+
config = BedrockConfig(aws_bedrock_bearer_token=" ")
200206
assert config.has_bearer_token() is False
201207

202208

@@ -222,7 +228,7 @@ def test_should_not_use_sigv4_when_bearer_token_in_config(self):
222228

223229
config = BedrockConfig(
224230
region_name="us-east-1",
225-
api_key="my-bearer-token", # Use api_key alias
231+
aws_bedrock_bearer_token="my-bearer-token",
226232
)
227233
adapter = BedrockInferenceAdapter(config=config)
228234

@@ -240,6 +246,21 @@ def test_should_not_use_sigv4_when_bearer_token_in_provider_data(self):
240246
config = BedrockConfig(region_name="us-east-1")
241247
adapter = BedrockInferenceAdapter(config=config)
242248

249+
provider_data = BedrockProviderDataValidator(aws_bedrock_bearer_token="per-request-token")
250+
with patch.object(adapter, "get_request_provider_data", return_value=provider_data):
251+
assert adapter._should_use_sigv4() is False
252+
253+
def test_should_not_use_sigv4_when_legacy_provider_data_alias_is_used(self):
254+
"""Legacy provider-data key should still trigger bearer auth."""
255+
from ogx.providers.remote.inference.bedrock.bedrock import BedrockInferenceAdapter
256+
from ogx.providers.remote.inference.bedrock.config import (
257+
BedrockConfig,
258+
BedrockProviderDataValidator,
259+
)
260+
261+
config = BedrockConfig(region_name="us-east-1")
262+
adapter = BedrockInferenceAdapter(config=config)
263+
243264
provider_data = BedrockProviderDataValidator(aws_bearer_token_bedrock="per-request-token")
244265
with patch.object(adapter, "get_request_provider_data", return_value=provider_data):
245266
assert adapter._should_use_sigv4() is False
@@ -248,7 +269,7 @@ def test_get_extra_client_params_skips_sigv4_client_when_bearer_override(self):
248269
"""Per-request bearer token override must not be silently discarded by the SigV4 client.
249270
250271
When the server starts in SigV4 mode (_sigv4_http_client is not None) but a request
251-
arrives with aws_bearer_token_bedrock in provider data, get_extra_client_params()
272+
arrives with aws_bedrock_bearer_token in provider data, get_extra_client_params()
252273
must return {} so the OpenAI SDK uses the bearer token instead of SigV4 auth.
253274
"""
254275
from unittest.mock import MagicMock
@@ -266,7 +287,7 @@ def test_get_extra_client_params_skips_sigv4_client_when_bearer_override(self):
266287
adapter._sigv4_http_client = MagicMock()
267288

268289
# Per-request bearer token override in provider data
269-
provider_data = BedrockProviderDataValidator(aws_bearer_token_bedrock="per-request-token")
290+
provider_data = BedrockProviderDataValidator(aws_bedrock_bearer_token="per-request-token")
270291
with patch.object(adapter, "get_request_provider_data", return_value=provider_data):
271292
params = adapter.get_extra_client_params()
272293
# Must return {} — the bearer token path must not receive the SigV4 http_client,
@@ -301,7 +322,7 @@ def test_should_use_sigv4_when_provider_data_token_is_whitespace(self):
301322
adapter = BedrockInferenceAdapter(config=config)
302323

303324
# Whitespace-only token should be treated as no token (use SigV4)
304-
provider_data = BedrockProviderDataValidator(aws_bearer_token_bedrock=" ")
325+
provider_data = BedrockProviderDataValidator(aws_bedrock_bearer_token=" ")
305326
with patch.object(adapter, "get_request_provider_data", return_value=provider_data):
306327
assert adapter._should_use_sigv4() is True
307328

tests/unit/providers/inference/test_bedrock_adapter.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,33 @@
1717

1818

1919
def test_adapter_initialization():
20-
config = BedrockConfig(api_key="test-key", region_name="us-east-1")
20+
config = BedrockConfig(aws_bedrock_bearer_token="test-key", region_name="us-east-1")
2121
adapter = BedrockInferenceAdapter(config=config)
2222

2323
assert adapter.config.auth_credential.get_secret_value() == "test-key"
2424
assert adapter.config.region_name == "us-east-1"
2525

2626

2727
def test_client_url_construction():
28-
config = BedrockConfig(api_key="test-key", region_name="us-west-2")
28+
config = BedrockConfig(aws_bedrock_bearer_token="test-key", region_name="us-west-2")
2929
adapter = BedrockInferenceAdapter(config=config)
3030

3131
assert adapter.get_base_url() == "https://bedrock-runtime.us-west-2.amazonaws.com/openai/v1"
3232

3333

3434
def test_api_key_from_config():
35-
config = BedrockConfig(api_key="config-key", region_name="us-east-1")
35+
config = BedrockConfig(aws_bedrock_bearer_token="config-key", region_name="us-east-1")
3636
adapter = BedrockInferenceAdapter(config=config)
3737
assert adapter.config.auth_credential.get_secret_value() == "config-key"
3838

3939

4040
def test_api_key_from_header_overrides_config():
4141
"""Test API key from request header overrides config via client property"""
42-
config = BedrockConfig(api_key="config-key", region_name="us-east-1")
42+
config = BedrockConfig(aws_bedrock_bearer_token="config-key", region_name="us-east-1")
4343
adapter = BedrockInferenceAdapter(config=config)
44-
adapter.provider_data_api_key_field = "aws_bearer_token_bedrock"
44+
adapter.provider_data_api_key_field = "aws_bedrock_bearer_token"
4545
adapter.get_request_provider_data = MagicMock(
46-
return_value=SimpleNamespace(aws_bearer_token_bedrock=SecretStr("header-key"))
46+
return_value=SimpleNamespace(aws_bedrock_bearer_token=SecretStr("header-key"))
4747
)
4848

4949
# The client property is where header override happens (in OpenAIMixin)
@@ -52,7 +52,7 @@ def test_api_key_from_header_overrides_config():
5252

5353
async def test_authentication_error_handling():
5454
"""Authentication failures should surface as a sanitized InternalServerError."""
55-
config = BedrockConfig(api_key="invalid-key", region_name="us-east-1")
55+
config = BedrockConfig(aws_bedrock_bearer_token="invalid-key", region_name="us-east-1")
5656
adapter = BedrockInferenceAdapter(config=config)
5757

5858
# Mock the parent class method to raise AuthenticationError

0 commit comments

Comments
 (0)