Repository navigation
Stop connection extras from overriding the computed connection - #725
Open
chrisclark wants to merge 1 commit into
Open
chrisclark wants to merge 1 commit into
chrisclark wants to merge 1 commit into
Conversation
DatabaseConnection.extras is free-form JSON entered by whoever manages the
connection, and it was merged into the connection settings after the
computed ones. For an upload-backed connection that meant extras["NAME"]
won over the tenant's own local copy of their uploaded SQLite file:
NAME -> user_dbs/<their filename>
so one user could point an upload connection at another user's database
by naming its path. HOST, USER and PASSWORD could be replaced the same
way, and those are decrypted from the encrypted model fields that had just
been used to compute the settings. ENGINE could be swapped too, which
changes which driver is loaded.
Keys that Explorer manages are now dropped from extras rather than merged:
ENGINE always, and NAME/HOST/USER/PASSWORD additionally for uploads. The
upload path stays pinned to uploaded_db_local_path(name), which is derived
from the connection's own name in the shared user_dbs directory.
Everything else in extras keeps working (OPTIONS, TIME_ZONE, ...). The
keys are per-connection policy, so the filter lives on the model rather
than in any single caller.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes cross-tenant database access through connection
extras. High.DatabaseConnection.extrasis free-form JSON entered by whoever manages the connection, and it was merged into the connection settings after the computed ones:For an upload-backed connection that means
extras["NAME"]overrode the tenant's own local copy of their file, so one user could point an upload connection at another user's database by naming its path inuser_dbs/.HOST,USERandPASSWORDwere replaceable the same way — and those are the values that had just been decrypted from the encrypted model fields.ENGINEcould be swapped too, which changes which driver is loaded.I confirmed the override was reachable by watching a
ClientError: HeadObjectcome back from the real bucket for the injected path before this fix.Fix
Keys Explorer manages are dropped from
extrasinstead of merged:ENGINEalways;NAME/HOST/USER/PASSWORDadditionally for upload-backed connections.Everything else keeps working (
OPTIONS,TIME_ZONE, custom driver kwargs …). The uploadNAMEstays pinned touploaded_db_local_path(name), derived from the connection's own name in the shareduser_dbsdirectory.I put the filter on the model rather than in
DatabaseConnectionValidateView(which builds an unsaved instance from form data) because this is per-connection policy, not a single caller's concern — a second caller would silently reopen the hole. Ignored keys are logged at warning level so a legitimate-but-mistakenextrasentry is visible rather than mysteriously ignored.Deliberately not restricted:
NAMEfor non-upload connections. For a normal server-side connection it is just the database name the admin chose, and pinning it toaliaswould be wrong for Postgres/Oracle setups — happy to tighten further if you want uploads-only stricter.Tests
New, in
TestDjangoStyleConnection(exits via mockedload_backend, so the driver need not be installed):NAMEcannot be overridden; resolves toconn.local_name;USER/PASSWORD/HOSTcannot be overridden;OPTIONSinextrasstill applies to non-upload connections (guards against over-restricting).Full suite: 294 tests, OK.
ruff check explorer/: clean.Note: I had to remove stale
tst1/tst2/tst3files in the working tree first — the SQLite test DBs persisted from an interrupted run andmanage.py testwas blocking on the interactive "delete the test database?" prompt rather than running.