diff --git a/pycsw/core/repository.py b/pycsw/core/repository.py index 1bf9648c5..5e8265a8b 100644 --- a/pycsw/core/repository.py +++ b/pycsw/core/repository.py @@ -69,7 +69,7 @@ def create_engine(clazz, url): Engines are memoized by url ''' if url not in clazz._engines: - LOGGER.info('creating new engine: %s', url) + LOGGER.info('creating new engine: %s', util.sanitize_db_connect(url)) engine = create_engine('%s' % url, echo=False, pool_pre_ping=True) # load SQLite query bindings @@ -238,7 +238,7 @@ def __init__(self, database, context, app_root=None, table='records', repo_filte self.queryables['_all'].update(self.context.md_core_model['mappings']) def ping(self, max_tries=10, wait_seconds=10): - LOGGER.debug(f"Waiting for {self.database}...") + LOGGER.debug(f"Waiting for {util.sanitize_db_connect(self.database)}...") if self.database.startswith('sqlite'): sql = 'SELECT sqlite_version();' @@ -258,12 +258,12 @@ def ping(self, max_tries=10, wait_seconds=10): sleep(wait_seconds) else: raise RuntimeError( - f"Database not responding at {self.database} after {max_tries} tries. ") + f"Database not responding at {util.sanitize_db_connect(self.database)} after {max_tries} tries. ") def rebuild_db_indexes(self): """Rebuild database indexes""" - LOGGER.info('Rebuilding database %s, table %s', self.database, self.table) + LOGGER.info('Rebuilding database %s, table %s', util.sanitize_db_connect(self.database), self.table) connection = self.engine.connect() connection.autocommit = True connection.execute('REINDEX %s' % self.table) @@ -274,7 +274,7 @@ def optimize_db(self): """Optimize database""" from sqlalchemy.exc import ArgumentError, OperationalError - LOGGER.info('Optimizing database %s', self.database) + LOGGER.info('Optimizing database %s', util.sanitize_db_connect(self.database)) connection = self.engine.connect() try: # PostgreSQL @@ -720,7 +720,7 @@ def setup(database, table, create_sfsql_tables=True, postgis_geometry_column='wk from sqlalchemy.types import Float from sqlalchemy.orm import create_session - LOGGER.info('Creating database %s', database) + LOGGER.info('Creating database %s', util.sanitize_db_connect(database)) if database.startswith('sqlite:///'): _, filepath = database.split('sqlite:///') dirname = os.path.dirname(filepath) diff --git a/pycsw/core/util.py b/pycsw/core/util.py index 178a855b4..ea522abc1 100644 --- a/pycsw/core/util.py +++ b/pycsw/core/util.py @@ -532,6 +532,19 @@ def load_custom_repo_mappings(repository_mappings: str) -> typing.Optional[typin return result +def sanitize_db_connect (url): + """ + helper function to remove user:pw from db connect for logging purposes + + :param url: value to be sanitized + + :returns: `str` sanitized + """ + if '@' in url: + return url.split('://')[0] + '://***:***@' + url.split('@').pop() + else: + return url + def str2bool(value: typing.Union[bool, str]) -> bool: """ helper function to return Python boolean diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py index 9561bf168..66c278a6f 100644 --- a/tests/unittests/test_util.py +++ b/tests/unittests/test_util.py @@ -366,3 +366,7 @@ def test_programmatic_import(import_path, expected_attribute): def test_programmatic_import_with_invalid_path(invalid_import_path): result = util.programmatic_import(invalid_import_path) assert result is None + +def test_sanitize_url(): + result = util.sanitize_db_connect("postgresql://username:password@localhost/pycsw") + assert result == "postgresql://***:***@localhost/pycsw"