1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-11 04:36:48 +00:00

feat(operations): admit claims atomically; redact secrets

This commit is contained in:
catborise 2026-10-13 17:25:39 +03:00
parent 99b9aa2a3c
commit fca4a5d91c
4 changed files with 227 additions and 0 deletions

32
operations/utils.py Normal file
View file

@ -0,0 +1,32 @@
"""Secrets never reach a job record, a response or a log line."""
import re
_NAMES = r"(?:pass|secret|token|key)\w*"
_PATTERNS = [
(re.compile(r"(://[^:/@\s]+:)[^@\s]+@"), r"\1***@"),
# quoted values, also XML attributes: passwd='x', password="x"
(re.compile(rf"""({_NAMES}['"]?\s*[:=]\s*)(['"])(?:\\.|(?!\2)[^\\])*\\?(?:\2|\Z)""", re.I | re.S), r"\1\2***\2"),
(re.compile(rf"""({_NAMES}['"]?\s*[:=]\s*)[^\s'",;<>]+""", re.I), r"\1***"),
# <secret ...>value</secret>-like elements
(re.compile(r"(<(secret|passphrase)\b[^>]*>).*?(</\2>)", re.I | re.S), r"\1***\3"),
]
_SECRET_KEY = re.compile(r"pass|secret|token|private|key$", re.I)
def safe_text(text):
text = str(text)
for pattern, replacement in _PATTERNS:
text = pattern.sub(replacement, text)
return text
def check_params(params):
if isinstance(params, dict):
for key, value in params.items():
if _SECRET_KEY.search(str(key)):
raise ValueError(f"A job cannot store the field {key}")
check_params(value)
elif isinstance(params, (list, tuple)):
for value in params:
check_params(value)