Commit Graph
14 Commits
Author SHA1 Message Date
Claude Code b19cf53797 experiment: stop passing password="***" to real database connections and caches
Critical regression: SQLAlchemy 2.0 changed URL.__str__() to always
substitute "***" for the password rather than rendering it verbatim
(SQLAlchemy 1.4's str(URL) rendered the real value). Every
build_sqlalchemy_uri() implementation across the db_engine_specs
(base/Postgres+MySQL+etc, ClickHouse, Databricks x2, Snowflake,
Databend, Couchbase) built a URL with the user's real password and
returned str(url) - which is exactly the string
superset/databases/schemas.py's pre-load hook writes into
data["sqlalchemy_uri"] when a database is created or edited via the
parameterized connection form. Under SQLAlchemy 2.0 that stores the
literal password "***" instead of the real one, breaking every new
connection made that way. Switched all of these to
render_as_string(hide_password=False), which is the 2.0-native way to
get the real, unmasked URL string.

Two more instances of the same str(URL) regression in
superset/models/core.py, both with real functional impact:

- Database.set_sqlalchemy_uri() intentionally replaces the real
  password with Superset's own PASSWORD_MASK sentinel
  ("X" * 10, not a secret) before storing self.sqlalchemy_uri, so a
  later edit can compare conn.password != PASSWORD_MASK to detect
  "the user didn't touch the password field, keep the existing one."
  str(conn) under 2.0 was substituting its own "***" for that
  sentinel, so the stored URI no longer round-tripped to
  PASSWORD_MASK - it round-tripped to the meaningless literal "***",
  breaking password-preservation on every database edit.

- The per-process SQLAlchemy engine cache (superset/models/core.py,
  _ENGINE_CACHE) keys on str(sqlalchemy_url) specifically so that a
  password rotation naturally invalidates the cached engine (the
  module comment states this explicitly). Under 2.0, str(url) always
  masks to the same "***" regardless of the real password, so
  rotating a database's password would silently keep reusing the old,
  now-wrong cached engine/connection pool for the life of the worker
  process.

Also fixed a separate, unrelated 1.4->2.0 break in
superset/db_engine_specs/duckdb.py: two build_sqlalchemy_uri variants
called the raw URL(...) constructor, which SQLAlchemy 2.0 turned into
a strict NamedTuple requiring username/password/host/port to be
passed explicitly (they used to default to None). That raised
"URL.__new__() missing 4 required positional arguments" outright.
Switched both to URL.create(), which keeps those optional.

Test-side: model_tests.py/db_engine_specs test files that asserted
str(uri) == "<scheme>://user:realpassword@host/..." were relying on
the old unmasked str() behavior; switched them to
uri.render_as_string(hide_password=False) to keep verifying the real
underlying value rather than relaxing what's being checked.

Verified locally (sqlite): tests/integration_tests/db_engine_specs/
and tests/unit_tests/db_engine_specs/ - the password-masking and
duckdb URL() failures are gone (18 -> 12 remaining, unrelated:
mysqlclient not importable on this Mac, 5 bigquery test_fetch_data
failures, and a where_latest_partition literal-rendering cluster
across hive/presto/trino, tracked separately).
2026-08-10 04:39:57 -07:00
Maxime BeaucheminandBeto Dealmeida 2db8f809ba fix: proper handling of boolean filters with snowflake (#34199)
Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
2025-07-18 12:13:52 -07:00
Maxime BeaucheminandElizabeth Thompson e51b95ffa8 chore: enforce more ruff rules (#31447)
Co-authored-by: Elizabeth Thompson <eschutho@gmail.com>
2024-12-18 17:41:34 -08:00
Beto Dealmeida 4b59e42d3f chore: improve mask/unmask encrypted_extra (#29943) 2024-08-22 16:45:32 -04:00
Eyal EzerandEyal Ezer 07b2449bd7 refactor: Unify all json.(loads|dumps) usage to utils.json (#28702)
Co-authored-by: Eyal Ezer <eyal.ezer@ge.com>
2024-05-28 14:17:41 -07:00
Beto Dealmeida 5da6d2bd88 feat: add support for catalogs (#28416) 2024-05-16 12:49:31 -04:00
Maxime Beauchemin 2d63722150 chore: set up ruff as a new linter/formatter (#28158) 2024-04-24 17:19:53 -07:00
Beto Dealmeida 42e8d1b498 chore: improve schema security (#23385) 2023-03-17 08:05:50 -07:00
Ville Brofeldt cd6fc35f60 chore(db_engine_specs): clean up column spec logic and add tests (#22871) 2023-01-31 15:54:07 +02:00
Geido 3fd4718ecb fix: Convert TIMESTAMP_* to TIMESTAMP in Snowflake (#22872) 2023-01-26 19:49:44 +01:00
Josh SorefandJosh Soref 02e5dcbbf2 chore(misc): Spelling (#19678)
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
2023-01-25 16:35:08 -07:00
Beto Dealmeida bdeedaaf80 chore: set Snowflake user agent (#22432) 2022-12-15 17:08:34 -08:00
Jesse Yang 7e836e9b04 test: autouse app_context in unit tests (#20911) 2022-08-02 15:42:50 -07:00
Corbin RobbandCorbin Robb 0ae1ca7e02 chore(tests-backend): migrate snowflake and sqlite to unit tests (#18854)
* migrate snowflake and sqlite

* change structure to better match the other unit tests

Co-authored-by: Corbin Robb <corbin@Corbins-MacBook-Pro.local>
2022-02-23 11:11:10 -06:00