mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-06 08:16:43 +00:00
Merge pull request #39361 from BerriAI/litellm_fix_mantle_host_re_anchor
fix(bedrock_mantle): anchor MANTLE_HOST_RE so custom Mantle hosts are honored
This commit is contained in:
commit
300d335255
4 changed files with 85 additions and 1 deletions
|
|
@ -29,7 +29,7 @@ from litellm.secret_managers.main import get_secret_str
|
|||
BEDROCK_MANTLE_DEFAULT_REGION: Final = "us-east-1"
|
||||
|
||||
# Standard Mantle host: https://bedrock-mantle.<region>.api.aws (group 1 = region).
|
||||
MANTLE_HOST_RE: Final = re.compile(r"^https?://bedrock-mantle\.([^/.]+)\.api\.aws", re.IGNORECASE)
|
||||
MANTLE_HOST_RE: Final = re.compile(r"^https?://bedrock-mantle\.([^/.]+)\.api\.aws(?=/|$)", re.IGNORECASE)
|
||||
|
||||
|
||||
def resolve_mantle_bearer_token(api_key: str | None) -> str | None:
|
||||
|
|
|
|||
|
|
@ -68,6 +68,27 @@ def test_explicit_region_and_non_mantle_api_base_are_kept(no_ambient_aws):
|
|||
assert base_url == vpc_endpoint
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"lookalike_host",
|
||||
[
|
||||
"https://bedrock-mantle.us-east-1.api.aws.internal.example.com",
|
||||
"https://bedrock-mantle.us-gov-west-1.api.aws-int.example.com",
|
||||
"https://bedrock-mantle.us-east-1.api.aws:8443",
|
||||
],
|
||||
)
|
||||
def test_lookalike_mantle_host_api_base_is_kept(no_ambient_aws, lookalike_host):
|
||||
url, base_url = BedrockMantlePassthroughConfig().get_complete_url(
|
||||
api_base=lookalike_host,
|
||||
api_key=None,
|
||||
model="us.openai.gpt-5.6-sol",
|
||||
endpoint=INVOKE_ENDPOINT,
|
||||
request_query_params=None,
|
||||
litellm_params={"api_base": lookalike_host},
|
||||
)
|
||||
assert str(url) == f"{lookalike_host}/{INVOKE_ENDPOINT}"
|
||||
assert base_url == lookalike_host
|
||||
|
||||
|
||||
def test_region_falls_back_to_the_mantle_default_without_any_hint(no_ambient_aws):
|
||||
url, _ = BedrockMantlePassthroughConfig().get_complete_url(
|
||||
api_base=None,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,12 @@ from litellm.llms.bedrock_mantle.responses.transformation import (
|
|||
from litellm.types.router import GenericLiteLLMParams
|
||||
from litellm.types.utils import LlmProviders
|
||||
|
||||
LOOKALIKE_MANTLE_HOSTS = (
|
||||
"https://bedrock-mantle.us-east-1.api.aws.internal.example.com",
|
||||
"https://bedrock-mantle.us-gov-west-1.api.aws-int.example.com",
|
||||
"https://bedrock-mantle.us-east-1.api.aws:8443",
|
||||
)
|
||||
|
||||
|
||||
class TestBedrockMantleResponsesURL:
|
||||
def test_url_uses_region_from_env(self, monkeypatch):
|
||||
|
|
@ -1642,6 +1648,23 @@ class TestBedrockMantleResponsesSigV4:
|
|||
)
|
||||
assert url == "https://mantle-proxy.internal.example/openai/v1/responses"
|
||||
|
||||
@pytest.mark.parametrize("lookalike_host", LOOKALIKE_MANTLE_HOSTS)
|
||||
def test_lookalike_mantle_host_from_api_base_is_preserved(self, monkeypatch, lookalike_host):
|
||||
monkeypatch.delenv("BEDROCK_MANTLE_API_BASE", raising=False)
|
||||
cfg = BedrockMantleResponsesAPIConfig()
|
||||
url = cfg.get_complete_url(
|
||||
api_base=f"{lookalike_host}/openai/v1",
|
||||
litellm_params={"aws_region_name": "us-east-2"},
|
||||
)
|
||||
assert url == f"{lookalike_host}/openai/v1/responses"
|
||||
|
||||
@pytest.mark.parametrize("lookalike_host", LOOKALIKE_MANTLE_HOSTS)
|
||||
def test_lookalike_mantle_host_from_env_is_preserved(self, monkeypatch, lookalike_host):
|
||||
monkeypatch.setenv("BEDROCK_MANTLE_API_BASE", lookalike_host)
|
||||
cfg = BedrockMantleResponsesAPIConfig()
|
||||
url = cfg.get_complete_url(api_base=None, litellm_params={})
|
||||
assert url == f"{lookalike_host}/openai/v1/responses"
|
||||
|
||||
def test_caller_authorization_does_not_override_sigv4(self, monkeypatch):
|
||||
"""Adversarial-review regression: a caller-supplied Authorization header (e.g.
|
||||
from extra_headers, surviving the relaxed validate_environment) must not clobber
|
||||
|
|
|
|||
|
|
@ -399,6 +399,46 @@ class TestBedrockMantleChatAuth:
|
|||
assert "/eu-west-1/bedrock/aws4_request" in headers["Authorization"]
|
||||
assert "/us-west-2/bedrock/aws4_request" not in headers["Authorization"]
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("region_params", "env", "expected_region"),
|
||||
[
|
||||
({"aws_region_name": "us-west-2"}, {}, "us-west-2"),
|
||||
({}, {"BEDROCK_MANTLE_REGION": "ap-southeast-2"}, "ap-southeast-2"),
|
||||
],
|
||||
)
|
||||
def test_sigv4_scope_ignores_the_region_segment_of_a_lookalike_host(
|
||||
self, monkeypatch, region_params, env, expected_region
|
||||
):
|
||||
from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM
|
||||
|
||||
for var in (
|
||||
"BEDROCK_MANTLE_API_KEY",
|
||||
"AWS_BEARER_TOKEN_BEDROCK",
|
||||
"BEDROCK_MANTLE_REGION",
|
||||
"BEDROCK_MANTLE_API_BASE",
|
||||
"AWS_REGION",
|
||||
"AWS_REGION_NAME",
|
||||
):
|
||||
monkeypatch.delenv(var, raising=False)
|
||||
for var, value in env.items():
|
||||
monkeypatch.setenv(var, value)
|
||||
|
||||
cfg = BedrockMantleChatConfig(aws_signer=BaseAWSLLM())
|
||||
headers, _ = cfg.sign_request(
|
||||
headers={},
|
||||
optional_params={
|
||||
"aws_access_key_id": "AKIAEXAMPLE",
|
||||
"aws_secret_access_key": "c2VjcmV0LXRlc3Qtc2VjcmV0LXRlc3Qtc2VjcmV0",
|
||||
**region_params,
|
||||
},
|
||||
request_data={"input": "hi"},
|
||||
api_base="https://bedrock-mantle.eu-west-1.api.aws.internal.example.com/openai/v1/chat/completions",
|
||||
api_key=None,
|
||||
)
|
||||
|
||||
assert f"/{expected_region}/bedrock/aws4_request" in headers["Authorization"]
|
||||
assert "/eu-west-1/bedrock/aws4_request" not in headers["Authorization"]
|
||||
|
||||
def test_no_bearer_and_no_credentials_raises_value_error(self, monkeypatch):
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue