errors: hide credentials in urls in error messages (#34793)

This commit is contained in:
Lauréline Guérin 2019-10-11 09:42:33 +02:00
parent 47c5ef7ee7
commit 8ac5660f25
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 54 additions and 0 deletions

View File

@ -19,6 +19,7 @@ from django.db.models import Q
from django.test import override_settings
from django.utils.text import slugify
from django.utils import timezone, six
from django.utils.six.moves.urllib.parse import urlparse
from django.utils.translation import ugettext_lazy as _
from django.utils.timezone import now
from django.core.files.base import ContentFile
@ -750,6 +751,18 @@ class ProxyLogger(object):
if self.connector.down() and not force:
# don't log if the connector is known to be down
return
# hide credentials in urls
for url in re.findall(r'(https?://\S+)', message):
try:
parsed = urlparse(url)
except Exception:
continue
if not parsed.username and not parsed.password:
continue
replaced = parsed._replace(netloc="{}:{}@{}".format('***', '***', parsed.hostname))
message = message.replace(url, replaced.geturl())
levelno = getattr(logging, levelname)
if self._logger.level <= levelno:

View File

@ -8,6 +8,7 @@ import pytest
from httmock import HTTMock
from django.core.exceptions import ValidationError
from django.utils.log import AdminEmailHandler
from passerelle.base.models import ProxyLogger, ResourceLog
from passerelle.apps.feeds.models import Feed
@ -24,6 +25,18 @@ def connector():
return connector
@pytest.fixture
def email_handler():
root = logging.getLogger()
handler = AdminEmailHandler(include_html=True)
handler.level = logging.ERROR
root.handlers.append(handler)
try:
yield
finally:
root.handlers.remove(handler)
def test_proxy_logger_basic(db, connector):
pr = ProxyLogger(connector)
pr.debug(u'some message')
@ -61,6 +74,7 @@ def test_proxy_logger_ignore(db, connector):
pr.debug(u'some message')
assert len(ResourceLog.objects.all()) == 0
def test_proxy_logger_ignore_when_down(db, connector):
with HTTMock(down_mock): # set connector as down
connector.availability()
@ -71,6 +85,33 @@ def test_proxy_logger_ignore_when_down(db, connector):
assert len(ResourceLog.objects.all()) == 0
@pytest.mark.parametrize('error_msg, expected', [
('Foo Bar', 'Foo Bar'),
('http://badurl', 'http://badurl'),
('GET http://tcl.example.net/tclpassagearret (=> 502)',
'GET http://tcl.example.net/tclpassagearret (=> 502)'),
('GET https://tcl.example.net/tclpassagearret (=> 502)',
'GET https://tcl.example.net/tclpassagearret (=> 502)'),
('GET http://username:password@tcl.example.net/tclpassagearret (=> 502)',
'GET http://***:***@tcl.example.net/tclpassagearret (=> 502)'),
('GET https://username:password@tcl.example.net/tclpassagearret (=> 502)',
'GET https://***:***@tcl.example.net/tclpassagearret (=> 502)'),
])
def test_proxy_logger_hide_url_credentials(db, settings, email_handler, mailoutbox,
connector, error_msg, expected):
settings.ADMINS = [('admin', 'admin@example.net')]
pr = ProxyLogger(connector)
pr.error(error_msg)
assert len(mailoutbox) == 1
msg = mailoutbox[0]
assert msg.to == ['admin@example.net']
assert msg.subject == '[Django] ERROR: %s' % expected
assert expected in msg.body
rl = ResourceLog.objects.latest('pk')
assert rl.message == expected
def test_validate_notification_delays(db, connector):
def take(iterator, count):
return list(itertools.compress(iterator, range(1, count + 1)))