Spark: block DROP TABLE when the user cannot delete the table data on HDFS (1.11.0)#3
Merged
anandnalya merged 4 commits intoJul 3, 2026
Conversation
… HDFS With a Hive catalog, DROP TABLE removes the metastore entry without deleting data, and DROP TABLE PURGE removes the metastore entry before deleting files client-side, so a user without HDFS delete permission on the table location ends up with orphaned data that is no longer reachable through any catalog. DropTablePermissionValidator runs before both drop paths (hooked in dropTableWithoutPurging, which purgeTable also routes through) and calls FileSystem.access, a NameNode-side checkAccess RPC evaluated against the caller's UGI, requiring WRITE and EXECUTE on the table directory and its parent. Only hdfs locations are enforced since other filesystems fall back to non-authoritative client-side checks; null, empty, or missing locations pass through so dangling metastore entries can still be dropped. Applied to spark/v3.4, v3.5, v4.0, v4.1.
Mirror the NameNode's FSPermissionChecker sticky-bit rule on delete: when a directory has the sticky bit set, an entry can only be removed by the entry's owner or the directory's owner. The rule is applied to the parent directory (unlinking the table directory) and, when the table directory itself is sticky and not owned by the caller, to each of its immediate children via listStatus. The existence probe switches from exists() to getFileStatus() since the check now needs owner and permission bits anyway. HDFS superusers bypass sticky checks server-side but cannot be detected client-side, so they may be blocked spuriously; this is documented on the validator.
Usernames starting with bot- are pipeline service accounts that manage table lifecycles; skip the HDFS delete-permission validation entirely for them, before any filesystem RPC is issued.
There was a problem hiding this comment.
Pull request overview
This PR adds a Spark-side pre-drop filesystem permission validator to prevent DROP TABLE / DROP TABLE PURGE from orphaning HDFS data when the current user cannot delete the table’s directory. The change is wired into SparkCatalog#dropTableWithoutPurging across Spark 3.4, 3.5, 4.0, and 4.1, and includes unit tests for key allow/deny and sticky-bit scenarios.
Changes:
- Introduce
DropTablePermissionValidatorto perform HDFSFileSystem.access()checks (plus sticky-bit ownership rules) before drop/purge. - Invoke the validator from
SparkCatalog#dropTableWithoutPurging(both path identifiers and catalog-backed identifiers). - Add
TestDropTablePermissionValidatorcoverage across all supported Spark versions.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| spark/v3.4/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java | Calls pre-drop validator and stores Hadoop Configuration for reuse. |
| spark/v3.4/spark/src/main/java/org/apache/iceberg/spark/DropTablePermissionValidator.java | New HDFS permission/sticky-bit validator implementation. |
| spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/TestDropTablePermissionValidator.java | Unit tests for validator behavior (including sticky bit and bot exemption). |
| spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java | Calls pre-drop validator and stores Hadoop Configuration for reuse. |
| spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/DropTablePermissionValidator.java | New HDFS permission/sticky-bit validator implementation. |
| spark/v3.5/spark/src/test/java/org/apache/iceberg/spark/TestDropTablePermissionValidator.java | Unit tests for validator behavior (including sticky bit and bot exemption). |
| spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java | Calls pre-drop validator and stores Hadoop Configuration for reuse. |
| spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/DropTablePermissionValidator.java | New HDFS permission/sticky-bit validator implementation. |
| spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/TestDropTablePermissionValidator.java | Unit tests for validator behavior (including sticky bit and bot exemption). |
| spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java | Calls pre-drop validator and stores Hadoop Configuration for reuse. |
| spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/DropTablePermissionValidator.java | New HDFS permission/sticky-bit validator implementation. |
| spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/TestDropTablePermissionValidator.java | Unit tests for validator behavior (including sticky bit and bot exemption). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Reuse the sparkSession local in initialize() instead of re-resolving the active session, and let DROP TABLE proceed when loadTable fails with RuntimeIOException so that tables with unreadable metadata (wrapped IO failures during refresh) can still be cleaned up, matching the documented fail-open behavior for NotFoundException.
d846f3b
into
feat/spark-location-allowlist-1.11.0
15 of 25 checks passed
7 tasks
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.
What
Adds a pre-drop HDFS permission check so that
DROP TABLEandDROP TABLE PURGEfail up front when the current user cannot delete the table's files. Stacked on #2 (base branchfeat/spark-location-allowlist-1.11.0).Why
With a Hive catalog,
DROP TABLEremoves the metastore entry without deleting data, andDROP TABLE PURGEremoves the metastore entry before deleting files client-side. In both cases a user without HDFS delete permission on the table location ends up with orphaned data that is no longer reachable through any catalog. Failing the drop keeps the catalog entry and the data consistent.How
DropTablePermissionValidatorcallsFileSystem.access()— on HDFS a NameNode-sidecheckAccessRPC evaluated against the caller's UGI (groups and ACLs included) — requiring WRITE+EXECUTE on the table directory and on its parent (both are needed to delete the tree and unlink the directory).FSPermissionCheckerdoes on delete: when a directory has the sticky bit set, an entry can only be removed by the entry's owner or the directory's owner. The rule is applied to the parent directory (unlinking the table directory) and, when the table directory itself is sticky and not owned by the caller, to each of its immediate children.SparkCatalog#dropTableWithoutPurging, which bothdropTableandpurgeTableroute through, so plain drops, purges, andSparkSessionCatalogdelegation are all covered.hdfslocations are enforced; other filesystems (s3a, file) fall back to a non-authoritative client-side check and are skipped.bot-) are exempt from the check entirely.Limitations
purgeTablestill drops the metastore entry before deleting files; the pre-check shrinks but does not eliminate the orphaning window.Testing
TestDropTablePermissionValidator(15 cases: allow, deny on table dir, deny on parent, non-HDFS skip, missing location, concurrent delete race, RPC failure, null/empty location, six sticky-bit scenarios covering parent-sticky and table-dir-sticky with owner/non-owner combinations, and thebot-exemption viaUserGroupInformation.doAs) passes on all four Spark versions;checkstyle/spotlessclean.