屏蔽python日志中的敏感信息 [英] Mask out sensitive information in python log

查看:616
本文介绍了屏蔽python日志中的敏感信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码

try:
    r = requests.get('https://sensitive:passw0rd@what.ever/')
    r.raise_for_status()
except requests.HTTPError:
    logging.exception("Failed to what.ever")

在这里,如果端点返回不成功的http状态代码,则会记录以下内容

Here, if the endpoint returns non-successful http status code, the following will be logged

Traceback (most recent call last):
  File "a.py", line 5, in <module>
    r.raise_for_status()
  File "venv/lib/python3.5/site-packages/requests/models.py", line 928, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://sensitive:passw0rd@what.ever/

问题是记录了密码.我可以创建一个日志记录过滤器以完全过滤掉该行.但是,如果只是以某种方式屏蔽了密码,将会更加方便.由于没有字符串传递给logging.exception,因此在应用程序端进行过滤非常棘手.我可以在日志记录框架中的何处转换日志记录?

The problem is that the password is logged. I could create a logging filter to filter out this line completely. However, it would be more convenient if the password was just masked out somehow. As no string is passed to logging.exception filtering on the app side is tricky. Where in the logging framwork can I transform a log record?

推荐答案

显然,这是通过Formatter完成的.下面的例子

Apparently, this is done with a Formatter. Example below

import logging
import re


class SensitiveFormatter(logging.Formatter):
    """Formatter that removes sensitive information in urls."""
    @staticmethod
    def _filter(s):
        return re.sub(r':\/\/(.*?)\@', r'://', s)

    def format(self, record):
        original = logging.Formatter.format(self, record)
        return self._filter(original)

像这样使用

import logging
import requests

from sensitive_formatter import SensitiveFormatter

LOG_FORMAT = \
    '%(asctime)s [%(threadName)-16s] %(filename)27s:%(lineno)-4d %(levelname)7s| %(message)s'
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger(__name__)

# Don't actually configure your logging like this, just to showcase
# the above answer. :)
for handler in logging.root.handlers:
   handler.setFormatter(SensitiveFormatter(LOG_FORMAT))

log.warning('https://not:shown@httpbin.org/basic-auth/expected-user/expected-pass')
try:
    r = requests.get('https://not:shown@httpbin.org/basic-auth/expected-user/expected-pass')
    r.raise_for_status()
except requests.exceptions.RequestException as e:
    log.exception('boom!')

用户/密码将被屏蔽.请参阅下面的示例日志

The user/password will be masked out. See example log below

$ python log_example.py 
2018-05-18 11:59:22,703 [MainThread      ]                      log.py:14   WARNING| https://httpbin.org/basic-auth/user/secret
2018-05-18 11:59:22,747 [MainThread      ]           connectionpool.py:824    DEBUG| Starting new HTTPS connection (1): httpbin.org
2018-05-18 11:59:23,908 [MainThread      ]           connectionpool.py:396    DEBUG| https://httpbin.org:443 "DELETE /basic-auth/user/secret HTTP/1.1" 405 178
2018-05-18 11:59:23,913 [MainThread      ]                      log.py:19     ERROR| boom!
Traceback (most recent call last):
  File "log.py", line 17, in <module>
    r.raise_for_status()
  File "/Users/vidstige/src/so/venv/lib/python3.6/site-packages/requests/models.py", line 935, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 405 Client Error: METHOD NOT ALLOWED for url: https://httpbin.org/basic-auth/user/secret

这篇关于屏蔽python日志中的敏感信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆