Source code for imednet.utils.secrets
"""Secret redaction utilities."""
import re
from typing import Any
SENSITIVE_KEYS = frozenset(
{
"password",
"token",
"secret",
"credential",
"api_key",
"apikey",
"auth_key",
"access_key",
"security_key",
"private_key",
"client_secret",
"authorization",
"x-api-key",
"x-imn-security-key",
}
)
_SENSITIVE_PATTERN_KEYS = (
"x-imn-security-key",
"x-api-key",
"api[_-]?key",
"security[_-]?key",
"authorization",
"token",
"password",
"secret",
)
_SENSITIVE_PATTERN = re.compile(
rf"(?i)\b({'|'.join(_SENSITIVE_PATTERN_KEYS)})\b(\s*[:=]\s*)([\"']?)([^,;\r\n]*?)\3(?=,|;|$)"
)
def _replace_sensitive_match(match: re.Match[str]) -> str:
return f"{match.group(1)}{match.group(2)}{match.group(3)}***{match.group(3)}"
[docs]def redact_sensitive_payload(data: Any) -> Any:
"""Return data with sensitive key values redacted."""
if isinstance(data, dict):
redacted: dict[str, Any] = {}
for key, value in data.items():
key_str = str(key)
key_lower = key_str.lower()
if any(pattern in key_lower for pattern in SENSITIVE_KEYS):
redacted[key_str] = "***"
else:
redacted[key_str] = redact_sensitive_payload(value)
return redacted
if isinstance(data, list):
return [redact_sensitive_payload(item) for item in data]
if isinstance(data, tuple):
return tuple(redact_sensitive_payload(item) for item in data)
if isinstance(data, str):
return _SENSITIVE_PATTERN.sub(_replace_sensitive_match, data)
return data