Repository navigation
fix(semantic_layers): partition cache keys by user when CACHE_QUERY_BY_USER is enabled (#45877) - #45895
Conversation
| except Exception as ex: | ||
| logger.debug( | ||
| "Could not resolve semantic execution context for cache: %s", ex | ||
| ) |
There was a problem hiding this comment.
Suggestion: When CACHE_QUERY_BY_USER is enabled, any context-building failure is swallowed and these keys lack a user discriminator, so cache lookup can return another user's semantic results.
Assessment: 🔴 Critical · 🔁 Occurrence: Rarely · 🏷️ Security
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset/semantic_layers/models.py
**Line:** 920:923
**Comment:**
*Security: When `CACHE_QUERY_BY_USER` is enabled, any context-building failure is swallowed and these keys lack a user discriminator, so cache lookup can return another user's semantic results.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fixThere was a problem hiding this comment.
Resolved in commit 3895a3a.
When CACHE_QUERY_BY_USER is enabled and context resolution encounters an unexpected failure, we now log a warning and append a distinct nonce ('semantic-user-unresolved', uuid.uuid4().hex). This ensures fail-safe user isolation so that failed context resolutions never collapse into a shared unpartitioned cache key or leak semantic results across users. Dedicated test coverage has been added in tests/unit_tests/semantic_layers/models_test.py exercising this fallback branch, ensuring 100% module coverage.
There was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 3895a3a.
If resolving the execution context raises an exception while user-based caching is enabled, the code now adds a fresh semantic-user-unresolved UUID to the cache keys, preventing reuse of another request’s cached results.
If that's not right, unresolve this thread and CodeAnt will leave it open.
There was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 5b2e270.
When execution-context resolution raises an exception, the cache keys now include a fresh semantic-user-unresolved UUID, preventing reuse of results from another context.
If that's not right, unresolve this thread and CodeAnt will leave it open.
There was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 7272883.
When execution-context resolution raises an exception, the cache keys now include a fresh semantic-user-unresolved UUID, preventing reuse of results from another context.
If that's not right, unresolve this thread and CodeAnt will leave it open.
There was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of d43e6e3.
When execution-context resolution raises an exception, the cache keys now include a fresh semantic-user-unresolved UUID, preventing reuse of results from another context.
If that's not right, unresolve this thread and CodeAnt will leave it open.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #45895 +/- ##
=======================================
Coverage 84.76% 84.76%
=======================================
Files 3072 3072
Lines 206119 206129 +10
Branches 48539 48541 +2
=======================================
+ Hits 174718 174732 +14
+ Misses 28101 28099 -2
+ Partials 3300 3298 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
/review |
…Y_USER is enabled (apache#45877) Semantic views have no database attribute, which caused QueryObject.cache_key to swallow AttributeError and omit user isolation when CACHE_QUERY_BY_USER was enabled. Adding user isolation directly to SemanticView.get_extra_cache_keys via execution context identity digest ensures per-user cache partitioning for semantic layer chart data while preserving shared caching for embedded guest users. When context resolution encounters an unexpected failure, fall back to a distinct unresolved key per invocation and log a warning to ensure fail-safe isolation without cross-user cache leakage. Signed-off-by: Francesco Castaldi <info@francescocastaldi.it>
b463346 to
3895a3a
Compare
PR Remediation & Coverage Hardening Update
|
✅ Deploy Preview for superset-docs-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
EnxDev
left a comment
There was a problem hiding this comment.
Partitioning in get_extra_cache_keys with guests left shared reads right, and flag-off keys don't move.
One note inline about what the key is built from.
| if not exec_context.is_guest and exec_context.identity_digest: | ||
| keys.append(("semantic-user", exec_context.identity_digest)) |
There was a problem hiding this comment.
identity_digest is an HMAC keyed with SECRET_KEY, so with the flag on a key rotation changes every user's cache key. That breaks what test_metadata_aliases_share_result_cache pins (a worker-cached result stays readable after SECRET_KEY changes), and mid-rotation web and workers keep missing each other's results.
Keying on principal_id avoids it. Heads up that #45900 fixes the same issue that way, so it's probably worth settling on one of the two.
| if not exec_context.is_guest and exec_context.identity_digest: | |
| keys.append(("semantic-user", exec_context.identity_digest)) | |
| if not exec_context.is_guest and exec_context.principal_id: | |
| keys.append(("semantic-user", exec_context.principal_id)) |
There was a problem hiding this comment.
Resolved in commit 5b2e270.
Updated the user cache partition key to use exec_context.principal_id rather than exec_context.identity_digest. As noted, keying on principal_id decouples the user cache partition from SECRET_KEY, ensuring that cache entries remain valid and shared across web/worker nodes during rolling key rotations and upholding the contract pinned in test_metadata_aliases_share_result_cache.
We also extended unit test coverage in tests/unit_tests/semantic_layers/models_test.py to assert exact principal_id keys (("semantic-user", "1")) and verify that rotating current_app.config["SECRET_KEY"] leaves the user's cache keys unchanged.
Review Feedback Resolution: Stable User Partitioning via
|
…e across secret rotation (apache#45877) Signed-off-by: FrancescoCastaldi <info@francescocastaldi.it>
5b2e270 to
7272883
Compare
EnxDev
left a comment
There was a problem hiding this comment.
Keying on principal_id takes care of the secret rotation problem, and the new check that rotating SECRET_KEY leaves the keys unchanged pins it. Ran the semantic_layers unit suite on 7272883 and it's green.
Two things outside the code. The description still says the key is built from identity_digest, so worth updating before merge. And #45900 is still open for the same issue, so one of the two should probably be closed once a maintainer picks.
SUMMARY
Fixes #45877.
Chart-data results for semantic views (
datasource_type: "semantic_view") were cached under the same key across all users, even whenCACHE_QUERY_BY_USERwas enabled.Root Cause
In
QueryObject.cache_key, per-user cache partitioning attempts to readself.datasource.database:A
SemanticViewobject does not have a.databaseattribute, so theAttributeErroris silently caught and bypassed, omitting user isolation.Solution
This PR encapsulates user cache partitioning cleanly and exclusively inside
SemanticView.get_extra_cache_keys():is_feature_enabled("CACHE_QUERY_BY_USER")is true, queriescurrent_host_execution_context().("semantic-user", exec_context.identity_digest)when the caller is not a guest (not exec_context.is_guest) andidentity_digestis present.is_guest=True) as intended by the guest token security model.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A (Backend caching behavior)
TESTING INSTRUCTIONS
Run unit tests:
ADDITIONAL INFORMATION
CACHE_QUERY_BY_USER