Skip to content

Instantly share code, notes, and snippets.

@dyens
Created May 1, 2021 12:19
Show Gist options
  • Save dyens/da9c5b088c6ea9a5b8ecd7da2ebfdcfe to your computer and use it in GitHub Desktop.
Save dyens/da9c5b088c6ea9a5b8ecd7da2ebfdcfe to your computer and use it in GitHub Desktop.
Encrypt some fields in log messages
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()
@dyens
Copy link
Author

dyens commented May 1, 2021

This code returns:

WARNING test a=1, sid=b'gAAAAABgjUbrVcO3nxGhQoa2dEYe3aZOrGIee7T3l8ST95fPX7UxNLR61TQKRBQvkBScZx7Y_nHROE8JsBlphY4fMnfOYMDU7g=='

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment