Merge pull request #5265 from anasyusef/censor_db_pwd_logs

Censor DB password when outputting to logs
This commit is contained in:
Matthias 2021-07-12 20:48:41 +02:00 committed by GitHub
commit a261b188da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 5 deletions

View File

@ -14,7 +14,7 @@ from freqtrade.constants import USERPATH_HYPEROPTS, USERPATH_STRATEGIES
from freqtrade.enums import RunMode from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.exchange import market_is_active, validate_exchanges from freqtrade.exchange import market_is_active, validate_exchanges
from freqtrade.misc import plural from freqtrade.misc import parse_db_uri_for_logging, plural
from freqtrade.resolvers import ExchangeResolver, StrategyResolver from freqtrade.resolvers import ExchangeResolver, StrategyResolver
@ -225,7 +225,7 @@ def start_show_trades(args: Dict[str, Any]) -> None:
if 'db_url' not in config: if 'db_url' not in config:
raise OperationalException("--db-url is required for this command.") raise OperationalException("--db-url is required for this command.")
logger.info(f'Using DB: "{config["db_url"]}"') logger.info(f'Using DB: "{parse_db_uri_for_logging(config["db_url"])}"')
init_db(config['db_url'], clean_open_orders=False) init_db(config['db_url'], clean_open_orders=False)
tfilter = [] tfilter = []

View File

@ -15,7 +15,7 @@ from freqtrade.configuration.load_config import load_config_file, load_file
from freqtrade.enums import NON_UTIL_MODES, TRADING_MODES, RunMode from freqtrade.enums import NON_UTIL_MODES, TRADING_MODES, RunMode
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.loggers import setup_logging from freqtrade.loggers import setup_logging
from freqtrade.misc import deep_merge_dicts from freqtrade.misc import deep_merge_dicts, parse_db_uri_for_logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -144,7 +144,7 @@ class Configuration:
config['db_url'] = constants.DEFAULT_DB_PROD_URL config['db_url'] = constants.DEFAULT_DB_PROD_URL
logger.info('Dry run is disabled') logger.info('Dry run is disabled')
logger.info(f'Using DB: "{config["db_url"]}"') logger.info(f'Using DB: "{parse_db_uri_for_logging(config["db_url"])}"')
def _process_common_options(self, config: Dict[str, Any]) -> None: def _process_common_options(self, config: Dict[str, Any]) -> None:

View File

@ -8,6 +8,7 @@ from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any, Iterator, List from typing import Any, Iterator, List
from typing.io import IO from typing.io import IO
from urllib.parse import urlparse
import rapidjson import rapidjson
@ -214,3 +215,16 @@ def chunks(lst: List[Any], n: int) -> Iterator[List[Any]]:
""" """
for chunk in range(0, len(lst), n): for chunk in range(0, len(lst), n):
yield (lst[chunk:chunk + n]) yield (lst[chunk:chunk + n])
def parse_db_uri_for_logging(uri: str):
"""
Helper method to parse the DB URI and return the same DB URI with the password censored
if it contains it. Otherwise, return the DB URI unchanged
:param uri: DB URI to parse for logging
"""
parsed_db_uri = urlparse(uri)
if not parsed_db_uri.netloc: # No need for censoring as no password was provided
return uri
pwd = parsed_db_uri.netloc.split(':')[1].split('@')[0]
return parsed_db_uri.geturl().replace(f':{pwd}@', ':*****@')

View File

@ -7,7 +7,7 @@ from unittest.mock import MagicMock
import pytest import pytest
from freqtrade.misc import (decimals_per_coin, file_dump_json, file_load_json, format_ms_time, from freqtrade.misc import (decimals_per_coin, file_dump_json, file_load_json, format_ms_time,
pair_to_filename, plural, render_template, pair_to_filename, parse_db_uri_for_logging, plural, render_template,
render_template_with_fallback, round_coin_value, safe_value_fallback, render_template_with_fallback, round_coin_value, safe_value_fallback,
safe_value_fallback2, shorten_date) safe_value_fallback2, shorten_date)
@ -179,3 +179,18 @@ def test_render_template_fallback(mocker):
) )
assert isinstance(val, str) assert isinstance(val, str)
assert 'if self.dp' in val assert 'if self.dp' in val
def test_parse_db_uri_for_logging() -> None:
postgresql_conn_uri = "postgresql+psycopg2://scott123:scott123@host/dbname"
mariadb_conn_uri = "mariadb+mariadbconnector://app_user:Password123!@127.0.0.1:3306/company"
mysql_conn_uri = "mysql+pymysql://user:pass@some_mariadb/dbname?charset=utf8mb4"
sqlite_conn_uri = "sqlite:////freqtrade/user_data/tradesv3.sqlite"
censored_pwd = "*****"
def get_pwd(x): return x.split(':')[2].split('@')[0]
assert get_pwd(parse_db_uri_for_logging(postgresql_conn_uri)) == censored_pwd
assert get_pwd(parse_db_uri_for_logging(mariadb_conn_uri)) == censored_pwd
assert get_pwd(parse_db_uri_for_logging(mysql_conn_uri)) == censored_pwd
assert sqlite_conn_uri == parse_db_uri_for_logging(sqlite_conn_uri)