mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-17 04:34:25 +00:00
fix(proxy): store list-valued audit log changes as JSON text (#46555)
LiteLLM_AuditLogs parses before_value and updated_values as JSON but only re-serialized dicts, so a list change reached Prisma as a Python list and the row write failed. Every deployment warning ignore, snooze and restore hit this. Mask and re-serialize any JSON value instead
This commit is contained in:
parent
d6e6c6f26c
commit
9444f53300
2 changed files with 11 additions and 19 deletions
|
|
@ -3364,26 +3364,9 @@ class LiteLLM_AuditLogs(LiteLLMPydanticObjectBase):
|
|||
masker: Final = SensitiveDataMasker(sensitive_patterns={"key"})
|
||||
|
||||
if self.before_value is not None:
|
||||
json_before_value: dict | None = None
|
||||
if isinstance(self.before_value, str):
|
||||
json_before_value = json.loads(self.before_value)
|
||||
elif isinstance(self.before_value, dict):
|
||||
json_before_value = self.before_value
|
||||
|
||||
if json_before_value is not None:
|
||||
json_before_value = masker.mask_dict(json_before_value)
|
||||
self.before_value = json.dumps(json_before_value, default=str)
|
||||
|
||||
self.before_value = json.dumps(masker.mask(self.before_value), default=str)
|
||||
if self.updated_values is not None:
|
||||
json_updated_values: dict | None = None
|
||||
if isinstance(self.updated_values, str):
|
||||
json_updated_values = json.loads(self.updated_values)
|
||||
elif isinstance(self.updated_values, dict):
|
||||
json_updated_values = self.updated_values
|
||||
|
||||
if json_updated_values is not None:
|
||||
json_updated_values = masker.mask_dict(json_updated_values)
|
||||
self.updated_values = json.dumps(json_updated_values, default=str)
|
||||
self.updated_values = json.dumps(masker.mask(self.updated_values), default=str)
|
||||
|
||||
return self
|
||||
|
||||
|
|
|
|||
|
|
@ -260,6 +260,15 @@ def test_an_audit_log_keeps_the_non_secret_fields_it_recorded(field):
|
|||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("field", ("before_value", "updated_values"))
|
||||
def test_an_audit_log_stores_a_list_of_changes_as_json_text_with_keys_masked(field):
|
||||
sent = [{"id": "no_redis", "key": SECRET}, {"id": "detailed_debug"}]
|
||||
|
||||
log = _audit_log(**{field: json.dumps(sent)})
|
||||
|
||||
assert json.loads(getattr(log, field)) == [{"id": "no_redis", "key": SECRET_MASKED}, {"id": "detailed_debug"}]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("field", ("before_value", "updated_values"))
|
||||
def test_an_audit_log_leaves_a_change_it_has_no_record_of_alone(field):
|
||||
assert getattr(_audit_log(**{field: None}), field) is None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue