You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polaris.apache.org by ad...@apache.org on 2026/04/17 19:42:14 UTC
(polaris) branch main updated: NoSQL: filter stale grants with deleted grantees from resolved entities (#4231)
This is an automated email from the ASF dual-hosted git repository.
adutra pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new 10d67d76df NoSQL: filter stale grants with deleted grantees from resolved entities (#4231)
10d67d76df is described below
commit 10d67d76dfa0bcbb4501845797fa1e083e8ab67c
Author: Alexandre Dutra <ad...@apache.org>
AuthorDate: Fri Apr 17 21:42:10 2026 +0200
NoSQL: filter stale grants with deleted grantees from resolved entities (#4231)
The `allGrantRecords()` method only checked securable existence when filtering stale grants. For directed entries (d/...) the securable is the current entity itself, so deleted grantees were never filtered and leaked into resolved-entity grant sets.
---
.../nosql/metastore/NoSqlMetaStore.java | 28 +++++--
.../BasePolarisMetaStoreManagerTest.java | 6 ++
.../persistence/PolarisTestMetaStoreManager.java | 90 ++++++++++++++++++++++
3 files changed, 119 insertions(+), 5 deletions(-)
diff --git a/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStore.java b/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStore.java
index d3c928018e..5aabab71c1 100644
--- a/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStore.java
+++ b/persistence/nosql/persistence/metastore/src/main/java/org/apache/polaris/persistence/nosql/metastore/NoSqlMetaStore.java
@@ -1203,19 +1203,37 @@ class NoSqlMetaStore extends NonFunctionalBasePersistence {
catalogId,
aclName,
(securableAndGrantee, granted) -> {
- var indexedAccess =
- memoizedIndexedAccess.indexedAccess(
+ var securableExists =
+ entityExists(
securableAndGrantee.securableCatalogId(),
+ securableAndGrantee.securableId(),
securableAndGrantee.securableTypeCode());
- var existing = indexedAccess.nameKeyById(securableAndGrantee.securableId());
- if (existing.isPresent()) {
- collector.handle(securableAndGrantee, granted);
+ if (!securableExists) {
+ LOGGER.trace("Skipping stale grant record due to missing securable reference");
+ return;
+ }
+
+ var granteeExists =
+ entityExists(
+ securableAndGrantee.granteeCatalogId(),
+ securableAndGrantee.granteeId(),
+ securableAndGrantee.granteeTypeCode());
+ if (!granteeExists) {
+ LOGGER.trace("Skipping stale grant record due to missing grantee reference");
+ return;
}
+
+ collector.handle(securableAndGrantee, granted);
},
securablesIndex);
return collector.grantRecords;
}
+ private boolean entityExists(long catalogId, long id, int typeCode) {
+ var indexedAccess = memoizedIndexedAccess.indexedAccess(catalogId, typeCode);
+ return indexedAccess.nameKeyById(id).isPresent();
+ }
+
private void collectGrantRecords(
long catalogStableId, String aclName, AclEntryHandler aclEntryConsumer) {
LOGGER.debug("Checking ACL '{}'", aclName);
diff --git a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java
index 726bbfc6f8..c40449cf19 100644
--- a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java
+++ b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java
@@ -289,6 +289,12 @@ public abstract class BasePolarisMetaStoreManagerTest {
polarisTestMetaStoreManager.testLoadResolvedEntitiesGranteeVsSecurableRecords();
}
+ /** test that resolved entities do not include grant records referencing dropped grantees */
+ @Test
+ protected void testLoadResolvedEntitySkipsDroppedGranteeReferences() {
+ polarisTestMetaStoreManager.testLoadResolvedEntitySkipsDroppedGranteeReferences();
+ }
+
/** Test the set of functions for the entity cache */
@Test
protected void testEntityCache() {
diff --git a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java
index 9a5b938df3..60ab96de2b 100644
--- a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java
+++ b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java
@@ -2873,6 +2873,96 @@ public class PolarisTestMetaStoreManager {
.doesNotContainAnyElementsOf(resolved.getGrantRecordsAsSecurable());
}
+ public void testLoadResolvedEntitySkipsDroppedGranteeReferences() {
+ // create a catalog
+ PolarisBaseEntity catalog =
+ new PolarisBaseEntity(
+ PolarisEntityConstants.getNullId(),
+ polarisMetaStoreManager.generateNewEntityId(this.polarisCallContext).getId(),
+ PolarisEntityType.CATALOG,
+ PolarisEntitySubType.NULL_SUBTYPE,
+ PolarisEntityConstants.getRootEntityId(),
+ "staleGrantCatalog");
+ CreateCatalogResult catalogCreated =
+ polarisMetaStoreManager.createCatalog(this.polarisCallContext, catalog, List.of());
+ Assertions.assertThat(catalogCreated).isNotNull();
+ catalog = catalogCreated.getCatalog();
+
+ // read the built-in catalog_admin role (will be the securable)
+ EntityResult catalogAdminRoleResult =
+ polarisMetaStoreManager.readEntityByName(
+ this.polarisCallContext,
+ List.of(catalog),
+ PolarisEntityType.CATALOG_ROLE,
+ PolarisEntitySubType.ANY_SUBTYPE,
+ PolarisEntityConstants.getNameOfCatalogAdminRole());
+ Assertions.assertThat(catalogAdminRoleResult.isSuccess()).isTrue();
+ PolarisBaseEntity catalogAdminRole = catalogAdminRoleResult.getEntity();
+ Assertions.assertThat(catalogAdminRole).isNotNull();
+
+ // create a principal role (will be the grantee)
+ PolarisBaseEntity principalRole =
+ new PolarisBaseEntity(
+ PolarisEntityConstants.getNullId(),
+ polarisMetaStoreManager.generateNewEntityId(this.polarisCallContext).getId(),
+ PolarisEntityType.PRINCIPAL_ROLE,
+ PolarisEntitySubType.NULL_SUBTYPE,
+ PolarisEntityConstants.getRootEntityId(),
+ "staleGrantPrincipalRole");
+ EntityResult principalRoleCreate =
+ polarisMetaStoreManager.createEntityIfNotExists(
+ this.polarisCallContext, null, principalRole);
+ Assertions.assertThat(principalRoleCreate.isSuccess()).isTrue();
+ PolarisBaseEntity createdPrincipalRole = principalRoleCreate.getEntity();
+ Assertions.assertThat(createdPrincipalRole).isNotNull();
+ long principalRoleId = createdPrincipalRole.getId();
+
+ // grant usage on catalog_admin role to the principal role
+ Assertions.assertThat(
+ polarisMetaStoreManager
+ .grantUsageOnRoleToGrantee(
+ this.polarisCallContext, catalog, catalogAdminRole, createdPrincipalRole)
+ .isSuccess())
+ .isTrue();
+
+ // verify the grant appears in the catalog_admin role's resolved entity
+ ResolvedEntityResult beforeDrop =
+ polarisMetaStoreManager.loadResolvedEntityById(
+ this.polarisCallContext,
+ catalogAdminRole.getCatalogId(),
+ catalogAdminRole.getId(),
+ PolarisEntityType.CATALOG_ROLE);
+ Assertions.assertThat(beforeDrop.isSuccess()).isTrue();
+ Assertions.assertThat(beforeDrop.getEntityGrantRecords())
+ .anySatisfy(
+ grantRecord -> {
+ Assertions.assertThat(grantRecord.getSecurableId())
+ .isEqualTo(catalogAdminRole.getId());
+ Assertions.assertThat(grantRecord.getGranteeId()).isEqualTo(principalRoleId);
+ });
+
+ // drop the principal role (grantee)
+ Assertions.assertThat(
+ polarisMetaStoreManager
+ .dropEntityIfExists(
+ this.polarisCallContext, null, createdPrincipalRole, null, false)
+ .isSuccess())
+ .isTrue();
+
+ // verify the stale grant is filtered out from the catalog_admin role's resolved entity
+ ResolvedEntityResult afterDrop =
+ polarisMetaStoreManager.loadResolvedEntityById(
+ this.polarisCallContext,
+ catalogAdminRole.getCatalogId(),
+ catalogAdminRole.getId(),
+ PolarisEntityType.CATALOG_ROLE);
+ Assertions.assertThat(afterDrop.isSuccess()).isTrue();
+ Assertions.assertThat(afterDrop.getEntityGrantRecords())
+ .noneSatisfy(
+ grantRecord ->
+ Assertions.assertThat(grantRecord.getGranteeId()).isEqualTo(principalRoleId));
+ }
+
private static PolarisEntityCore getEntityCore(PolarisBaseEntity entity) {
return new PolarisEntityCore.Builder<>(entity).build();
}