diff --git a/involucro b/involucro new file mode 100755 index 00000000000..b32f784892e Binary files /dev/null and b/involucro differ diff --git a/lib/galaxy/config/__init__.py b/lib/galaxy/config/__init__.py index 5edf9adee90..a70fb9e3acf 100644 --- a/lib/galaxy/config/__init__.py +++ b/lib/galaxy/config/__init__.py @@ -786,6 +786,7 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): return val def _process_config(self, kwargs: Dict[str, Any]) -> None: + self._check_database_connection_strings() # Backwards compatibility for names used in too many places to fix self.datatypes_config = self.datatypes_config_file self.tool_configs = self.tool_config_file @@ -1195,6 +1196,29 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin): else: _load_theme(self.themes_config_file, self.themes) + def _check_database_connection_strings(self): + """ + Verify connection URI strings in galaxy's configuration are parseable with urllib. + """ + + def try_parsing(value, name): + try: + urlparse(value) + except ValueError as e: + msg = f"The `{name}` configuration property cannot be parsed as a connection URI." + if "Invalid IPv6 URL" in str(e): + msg += ( + "\nBesides an invalid IPv6 format, this may be caused by a bracket character in the `netloc` part of " + "the URI (most likely, the password). In this case, you should percent-encode that character: for `[` " + "use `%5B`, for `]` use `%5D`. For example, if your URI is `postgresql://user:pass[word@host/db`, " + "change it to `postgresql://user:pass%5Bword@host/db`. " + ) + raise ConfigurationError(msg) from e + + try_parsing(self.database_connection, "database_connection") + try_parsing(self.install_database_connection, "install_database_connection") + try_parsing(self.amqp_internal_connection, "amqp_internal_connection") + def _configure_dataset_storage(self): # The default for `file_path` has changed in 20.05; we may need to fall back to the old default self._set_alt_paths("file_path", self._in_data_dir("files")) # this is called BEFORE guessing id/uuid diff --git a/test/unit/config/test_config_values.py b/test/unit/config/test_config_values.py index 42b7e80bbb1..2f00824839d 100644 --- a/test/unit/config/test_config_values.py +++ b/test/unit/config/test_config_values.py @@ -4,6 +4,7 @@ import pytest from galaxy import config from galaxy.config import DEFAULT_EMAIL_FROM_LOCAL_PART +from galaxy.exceptions import ConfigurationError from galaxy.util.properties import running_from_source @@ -52,6 +53,20 @@ def test_assign_email_from(monkeypatch): assert appconfig.email_from == f"{DEFAULT_EMAIL_FROM_LOCAL_PART}@myhost" +@pytest.mark.parametrize("bracket", ["[", "]"]) +def test_error_if_database_connection_contains_brackets(bracket): + uri = f"dbscheme://user:pass{bracket}word@host/db" + + with pytest.raises(ConfigurationError): + config.GalaxyAppConfiguration(override_tempdir=False, database_connection=uri) + + with pytest.raises(ConfigurationError): + config.GalaxyAppConfiguration(override_tempdir=False, install_database_connection=uri) + + with pytest.raises(ConfigurationError): + config.GalaxyAppConfiguration(override_tempdir=False, amqp_internal_connection=uri) + + class TestIsFetchWithCeleryEnabled: def test_disabled_if_celery_disabled(self, appconfig): appconfig.enable_celery_tasks = False