ADH-8486: fix Spark Ranger stale policy cache bypass#56
Open
iamlapa wants to merge 5 commits into
Open
Conversation
…ure/ADH-8486 # Conflicts: # security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql # security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql # security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql # security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql # security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
tigrulya-exe
approved these changes
Jun 30, 2026
werzerbb
reviewed
Jul 3, 2026
werzerbb
approved these changes
Jul 3, 2026
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
This PR fixes the Spark3 + Ranger stale policy cache bypass we reproduced around policy download authorization.
Spark3 runs under the end user's account, unlike Hive/Impala service processes. Because of that, Spark historically needed
*inpolicy.download.auth.usersandtag.download.auth.usersto let user-launched Spark apps download Ranger policies. That works functionally, but it also means any authorized Spark user can call Ranger Admin APIs and download the full Hive policy bundle.When
*is removed, Ranger Admin correctly returns401/403, but the Spark plugin used to keep authorizing with its last local policy cache. So after a user lost access, an already runningspark3-shellcould still use stale cached policies.This PR addresses the issue in three layers:
401/403.What changed
Ranger Admin download authorization
Added new service config parameters:
policy.download.auth.groupstag.download.auth.groupsPolicy and role download now allow access if the caller matches either:
policy.download.auth.userspolicy.download.auth.groupsTag download now allows access if the caller matches either:
tag.download.auth.userstag.download.auth.groupsThe existing
*behavior in*.auth.usersis preserved for compatibility, but Spark managed configs can now use a real group instead, for example:Group membership is resolved through Ranger's user/group store on each request. Kerberos-style login IDs are normalized into candidate short names, so principals like:
can still match Ranger users/groups stored as short names.
Spark fail-closed behavior
RangerAdminRESTClientnow treats401and403as a dedicated access-denied condition instead of a generic refresh failure.A new exception was added:
RangerAdminClientAccessDeniedExceptionThis is thrown for policy, role, and tag download when Ranger Admin explicitly denies access.
Spark/plugin refresh code now handles that differently from transient failures:
401/403: mark authz state invalid, do not fall back to stale cache.A new plugin config controls the fail-closed behavior:
ranger.plugin.<service>.policy.refresh.authz.denied.mode=failclosedWhen enabled, any new access check is denied while policy/role/tag refresh is in authz-denied state.
This covers:
Policy cache directory isolation
Added policy cache subdir mode:
ranger.plugin.spark.policy.cache.subdir.mode=disabled|peruser|pergroupModes:
This is used by:
The helper validates user/group path elements and rejects unsafe values like empty names, path separators, and
...It also rejects unsafe existing directories and symlinks.
Important detail: for
peruserandpergroup, the shared base directory must already exist and have expected permissions. The plugin only creates the final$USERor$GROUPleaf directory. This avoids the first Spark user accidentally creating/srv/ranger/...as a private0700parent and blocking everyone else.Audit spool directory isolation
Added audit spool subdir mode:
xasecure.audit.destination.solr.batch.filespool.subdir.mode=disabled|peruser|pergroupModes are the same:
This was wired into the file audit spool implementations so Spark users no longer need to share the same writable audit spool directory.
Why these changes are needed
The original bug is not just that a user could not refresh policies after losing download permission. The real issue is that Spark treated that condition as a normal refresh failure and kept using old cached policies.
That creates this unsafe flow:
After this PR, the flow becomes:
This means revocation takes effect after the next refresh instead of being bypassed by local cache.
Recommended Spark config
Example target config for Spark3:
pergroupis also supported for clusters where Spark users are intentionally administered through trusted primary groups.