mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
Merge pull request #39044 from BerriAI/litellm_fix_bedrock_guardrail_token_log
fix(bedrock): mask signed request headers in guardrail debug log
This commit is contained in:
commit
9f6024bf97
3 changed files with 57 additions and 2 deletions
|
|
@ -32,6 +32,9 @@ from litellm.constants import BEDROCK_APPLY_GUARDRAIL_CHUNK_BUDGET_CHARS
|
|||
from litellm.exceptions import ModifyResponseException
|
||||
from litellm.integrations.custom_guardrail import CustomGuardrail
|
||||
from litellm.litellm_core_utils.core_helpers import redact_nested_match_and_regex_keys
|
||||
from litellm.litellm_core_utils.litellm_logging import (
|
||||
_get_masked_values, # pyright: ignore[reportPrivateUsage] # the shared header-masking helper has no public name
|
||||
)
|
||||
from litellm.litellm_core_utils.llm_cost_calc.guardrail_cost import bedrock_guardrail_cost
|
||||
from litellm.llms.anthropic.chat.guardrail_translation.handler import AnthropicMessagesHandler
|
||||
from litellm.llms.base_llm.guardrail_translation.utils import (
|
||||
|
|
@ -1170,11 +1173,12 @@ class BedrockGuardrail(CustomGuardrail, BaseAWSLLM):
|
|||
aws_region_name=aws_region_name,
|
||||
api_key=api_key,
|
||||
)
|
||||
headers_dict: Final = dict(prepared_request.headers) # mutable-ok: the masking helper requires a dict
|
||||
verbose_proxy_logger.debug(
|
||||
"Bedrock AI request body: %s, url %s, headers: %s",
|
||||
bedrock_request_data,
|
||||
prepared_request.url,
|
||||
prepared_request.headers,
|
||||
_get_masked_values(headers_dict),
|
||||
)
|
||||
|
||||
httpx_response: Final = await self._sign_and_post(
|
||||
|
|
|
|||
|
|
@ -5590,3 +5590,52 @@ async def test_streaming_end_of_stream_block_emits_error_frame_instead_of_trunca
|
|||
assert payload["error"]["message"] == "Violated guardrail policy"
|
||||
assert payload["error"]["code"] == "400"
|
||||
assert payload["error"]["provider_specific_fields"]["guardrailIdentifier"] == "test-guardrail"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_apply_guardrail_debug_log_masks_signed_request_headers():
|
||||
import logging
|
||||
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
|
||||
session_token = "FakeSessionTokenValueThatMustNeverAppearInLogs1234567890"
|
||||
guardrail = BedrockGuardrail(
|
||||
guardrailIdentifier="test-guardrail",
|
||||
guardrailVersion="DRAFT",
|
||||
aws_access_key_id="ASIAFAKEACCESSKEYID1",
|
||||
aws_secret_access_key="fakeSecretAccessKeyForSigning",
|
||||
aws_session_token=session_token,
|
||||
aws_region_name="us-east-1",
|
||||
)
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {"action": "NONE", "outputs": []}
|
||||
|
||||
captured_records: list[logging.LogRecord] = []
|
||||
|
||||
class _RecordingHandler(logging.Handler):
|
||||
def emit(self, record: logging.LogRecord) -> None:
|
||||
captured_records.append(record)
|
||||
|
||||
handler = _RecordingHandler(level=logging.DEBUG)
|
||||
previous_level = verbose_proxy_logger.level
|
||||
verbose_proxy_logger.addHandler(handler)
|
||||
verbose_proxy_logger.setLevel(logging.DEBUG)
|
||||
try:
|
||||
with patch.object(guardrail.async_handler, "post", new_callable=AsyncMock) as mock_post:
|
||||
mock_post.return_value = mock_response
|
||||
await guardrail.make_bedrock_api_request(
|
||||
source="INPUT",
|
||||
messages=[{"role": "user", "content": "hello"}],
|
||||
request_data={},
|
||||
)
|
||||
finally:
|
||||
verbose_proxy_logger.removeHandler(handler)
|
||||
verbose_proxy_logger.setLevel(previous_level)
|
||||
|
||||
rendered_messages = [record.getMessage() for record in captured_records]
|
||||
header_lines = [message for message in rendered_messages if "headers:" in message]
|
||||
assert header_lines, "expected the signed-request debug line to be logged"
|
||||
assert any("X-Amz-Security-Token" in message for message in header_lines)
|
||||
assert all(session_token not in message for message in rendered_messages)
|
||||
|
|
|
|||
|
|
@ -917,7 +917,9 @@ async def test_bedrock_guardrail_make_api_request_passes_api_key():
|
|||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer test-api-key-789",
|
||||
}
|
||||
mock_request_instance.prepare.return_value = Mock()
|
||||
mock_request_instance.prepare.return_value = Mock(
|
||||
headers=mock_request_instance.headers
|
||||
)
|
||||
mock_aws_request.return_value = mock_request_instance
|
||||
|
||||
await guardrail_hook.make_bedrock_api_request(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue