feat: apply RLS conservatively (#38683)

This commit is contained in:
Beto Dealmeida
2026-03-17 10:20:09 -04:00
committed by GitHub
parent 1c8224f4c6
commit a854fa60a2
6 changed files with 416 additions and 16 deletions

View File

@@ -202,6 +202,7 @@ def validate_adhoc_subquery(
nested sub-queries with table
"""
parsed_statement = SQLStatement(sql, engine)
rls_applied = False
if parsed_statement.has_subquery():
if not is_feature_enabled("ALLOW_ADHOC_SUBQUERY"):
raise SupersetSecurityException(
@@ -213,9 +214,12 @@ def validate_adhoc_subquery(
)
# enforce RLS rules in any relevant tables
apply_rls(database, catalog, default_schema, parsed_statement)
rls_applied = apply_rls(database, catalog, default_schema, parsed_statement)
return parsed_statement.format()
# Only regenerate the SQL if RLS predicates were actually applied;
# unnecessary round-tripping through sqlglot can alter dialect-specific
# syntax.
return parsed_statement.format() if rls_applied else sql
def json_to_dict(json_str: str) -> dict[Any, Any]:
@@ -2049,15 +2053,23 @@ class ExploreMixin: # pylint: disable=too-many-public-methods
if parsed_script.statements:
default_schema = self.database.get_default_schema(self.catalog)
try:
rls_applied = False
for statement in parsed_script.statements:
apply_rls(
if apply_rls(
self.database,
self.catalog,
self.schema or default_schema or "",
statement,
)
# Regenerate the SQL after RLS application
from_sql = parsed_script.format()
):
rls_applied = True
# Only regenerate the SQL if RLS predicates were actually applied.
# Unnecessary round-tripping through sqlglot can alter SQL in
# dialect-specific ways (e.g. dropping column aliases, rewriting
# Redshift-specific syntax) and break virtual dataset queries.
if rls_applied:
from_sql = parsed_script.format()
except Exception as ex:
# Log the error but don't fail - RLS application is best-effort
logger.warning("Failed to apply RLS to virtual dataset SQL: %s", ex)