Created
May 1, 2021 12:19
-
-
Save dyens/da9c5b088c6ea9a5b8ecd7da2ebfdcfe to your computer and use it in GitHub Desktop.
Encrypt some fields in log messages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import logging.config | |
# pip install cryptography | |
from cryptography.fernet import Fernet | |
# FROM https://github.com/madzak/python-json-logger/blob/master/src/pythonjsonlogger/jsonlogger.py#L18 | |
RESERVED_ATTRS = ('args', 'asctime', 'created', 'exc_info', 'exc_text', | |
'filename', 'funcName', 'levelname', 'levelno', 'lineno', | |
'module', 'msecs', 'message', 'msg', 'name', 'pathname', | |
'process', 'processName', 'relativeCreated', 'stack_info', | |
'thread', 'threadName') | |
SECRET_KEYS = {'sid', 'password', 'username'} | |
def merge_record_extra(record, target, reserved): | |
""" | |
Merges extra attributes from LogRecord object into target dictionary | |
:param record: logging.LogRecord | |
:param target: dict to update | |
:param reserved: dict or list with reserved keys to skip | |
""" | |
for key, value in record.__dict__.items(): | |
# this allows to have numeric keys | |
if (key not in reserved | |
and not (hasattr(key, "startswith") and key.startswith('_'))): | |
target[key] = value | |
return target | |
key = b'7Kpw9lLjN3BEBqz-hMPURwKIKX-aP-Q2VZUVnD8PyDw=' | |
fernet = Fernet(key) | |
token = fernet.encrypt(b"A really secret message. Not for prying eyes.") | |
class FormatterWithExtra(logging.Formatter): | |
def format(self, record): | |
extras = merge_record_extra( | |
record=record, | |
target=dict(), | |
reserved=RESERVED_ATTRS, | |
) | |
record.extras = ', '.join('{}={}'.format( | |
k, | |
fernet.encrypt(v.encode()) if k in SECRET_KEYS else v) | |
for k, v in extras.items()) | |
return super().format(record) | |
config = { | |
'version': 1, | |
'disable_existing_loggers': False, | |
'formatters': { | |
'standard': { | |
'class': '__main__.FormatterWithExtra', | |
'format': '%(levelname)s %(message)s %(extras)s', | |
}, | |
}, | |
'handlers': { | |
'standard': { | |
'class': 'logging.StreamHandler', | |
'formatter': 'standard', | |
}, | |
}, | |
'loggers': { | |
'': { | |
'handlers': ['standard'], | |
'level': logging.INFO, | |
}, | |
}, | |
} | |
logging.config.dictConfig(config) | |
logger = logging.getLogger(__name__) | |
logger.warning('test', extra={'a': 1, 'sid': 'this is secret'}) | |
# For generating a new KEY | |
# KEY = Fernet.generate_key() | |
# print(KEY) | |
# For decrypting | |
# key = b'7Kpw9lLjN3BEBqz-hMPURwKIKX-aP-Q2VZUVnD8PyDw=' | |
# fernet = Fernet(key) | |
# string = fernet.decrypt(token).decode() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code returns: