This is an automated email from the ASF dual-hosted git repository.
emaynard 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 dd223c1bd Make entity lookups by id honor the specified entity type
(#1401)
dd223c1bd is described below
commit dd223c1bd9a0ccfe2520d76e388f0e1940958737
Author: Alexandre Dutra <[email protected]>
AuthorDate: Wed Apr 23 19:25:55 2025 +0200
Make entity lookups by id honor the specified entity type (#1401)
* Make entity lookups by id honor the specified entity type
All implementations of
`TransactionalPersistence.lookupEntityInCurrentTxn()` are currently ignoring
the `typeCode` parameter completely and could potentially return an entity of
the wrong type.
This can become very concerning during authentication, since a principal
lookup could return some entity that is not a principal, and that would be
considered a successful authentication.
* review
---
.../PolarisEclipseLinkMetaStoreSessionImpl.java | 6 +-
.../impl/eclipselink/PolarisEclipseLinkStore.java | 12 ++--
.../TreeMapTransactionalPersistenceImpl.java | 7 +-
.../BasePolarisMetaStoreManagerTest.java | 6 ++
.../persistence/PolarisTestMetaStoreManager.java | 80 ++++++++++++++++++++++
5 files changed, 103 insertions(+), 8 deletions(-)
diff --git
a/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreSessionImpl.java
b/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreSessionImpl.java
index 14bb01d83..e19b0ef72 100644
---
a/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreSessionImpl.java
+++
b/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreSessionImpl.java
@@ -309,7 +309,8 @@ public class PolarisEclipseLinkMetaStoreSessionImpl extends
AbstractTransactiona
@Nonnull PolarisCallContext callCtx, @Nonnull PolarisEntityCore entity) {
// delete it
- this.store.deleteFromEntities(localSession.get(), entity.getCatalogId(),
entity.getId());
+ this.store.deleteFromEntities(
+ localSession.get(), entity.getCatalogId(), entity.getId(),
entity.getTypeCode());
}
/** {@inheritDoc} */
@@ -360,7 +361,8 @@ public class PolarisEclipseLinkMetaStoreSessionImpl extends
AbstractTransactiona
@Override
public @Nullable PolarisBaseEntity lookupEntityInCurrentTxn(
@Nonnull PolarisCallContext callCtx, long catalogId, long entityId, int
typeCode) {
- return ModelEntity.toEntity(this.store.lookupEntity(localSession.get(),
catalogId, entityId));
+ return ModelEntity.toEntity(
+ this.store.lookupEntity(localSession.get(), catalogId, entityId,
typeCode));
}
@Override
diff --git
a/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkStore.java
b/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkStore.java
index fc889656b..9ebb4e816 100644
---
a/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkStore.java
+++
b/extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkStore.java
@@ -84,7 +84,8 @@ public class PolarisEclipseLinkStore {
diagnosticServices.check(session != null, "session_is_null");
checkInitialized();
- ModelEntity model = lookupEntity(session, entity.getCatalogId(),
entity.getId());
+ ModelEntity model =
+ lookupEntity(session, entity.getCatalogId(), entity.getId(),
entity.getTypeCode());
if (model != null) {
// Update if the same entity already exists
model.update(entity);
@@ -129,11 +130,11 @@ public class PolarisEclipseLinkStore {
session.persist(ModelGrantRecord.fromGrantRecord(grantRec));
}
- void deleteFromEntities(EntityManager session, long catalogId, long
entityId) {
+ void deleteFromEntities(EntityManager session, long catalogId, long
entityId, int typeCode) {
diagnosticServices.check(session != null, "session_is_null");
checkInitialized();
- ModelEntity model = lookupEntity(session, catalogId, entityId);
+ ModelEntity model = lookupEntity(session, catalogId, entityId, typeCode);
diagnosticServices.check(model != null, "entity_not_found");
session.remove(model);
@@ -203,14 +204,15 @@ public class PolarisEclipseLinkStore {
LOGGER.debug("All entities deleted.");
}
- ModelEntity lookupEntity(EntityManager session, long catalogId, long
entityId) {
+ ModelEntity lookupEntity(EntityManager session, long catalogId, long
entityId, long typeCode) {
diagnosticServices.check(session != null, "session_is_null");
checkInitialized();
return session
.createQuery(
- "SELECT m from ModelEntity m where m.catalogId=:catalogId and
m.id=:id",
+ "SELECT m from ModelEntity m where m.catalogId=:catalogId and
m.id=:id and m.typeCode=:typeCode",
ModelEntity.class)
+ .setParameter("typeCode", typeCode)
.setParameter("catalogId", catalogId)
.setParameter("id", entityId)
.getResultStream()
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TreeMapTransactionalPersistenceImpl.java
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TreeMapTransactionalPersistenceImpl.java
index 822045673..e9cbd53f3 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TreeMapTransactionalPersistenceImpl.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TreeMapTransactionalPersistenceImpl.java
@@ -217,7 +217,12 @@ public class TreeMapTransactionalPersistenceImpl extends
AbstractTransactionalPe
@Override
public @Nullable PolarisBaseEntity lookupEntityInCurrentTxn(
@Nonnull PolarisCallContext callCtx, long catalogId, long entityId, int
typeCode) {
- return
this.store.getSliceEntities().read(this.store.buildKeyComposite(catalogId,
entityId));
+ PolarisBaseEntity entity =
+
this.store.getSliceEntities().read(this.store.buildKeyComposite(catalogId,
entityId));
+ if (entity != null && entity.getTypeCode() != typeCode) {
+ return null;
+ }
+ return entity;
}
/** {@inheritDoc} */
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 b37a57464..d11bed82d 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
@@ -273,6 +273,12 @@ public abstract class BasePolarisMetaStoreManagerTest {
polarisTestMetaStoreManager.testRename();
}
+ /** test entity lookup */
+ @Test
+ protected void testLookup() {
+ polarisTestMetaStoreManager.testLookup();
+ }
+
/** 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 81b95ab39..b401d4efb 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
@@ -192,6 +192,24 @@ public class PolarisTestMetaStoreManager {
return entity;
}
+ /**
+ * Validate that the specified identity identified by the pair catalogId,
entityId does not exist.
+ *
+ * @param catalogId catalog id of that entity
+ * @param entityId the entity id
+ * @param expectedType its expected type
+ */
+ private void ensureNotExistsById(long catalogId, long entityId,
PolarisEntityType expectedType) {
+
+ PolarisBaseEntity entity =
+ polarisMetaStoreManager
+ .loadEntity(this.polarisCallContext, catalogId, entityId,
expectedType)
+ .getEntity();
+
+ // assert entity was not found
+ Assertions.assertThat(entity).isNull();
+ }
+
/**
* Check if the specified grant record exists
*
@@ -2564,6 +2582,68 @@ public class PolarisTestMetaStoreManager {
this.renameEntity(List.of(catalog, N1, N1_N2), N1_N2_T1, List.of(catalog,
N5), "T7");
}
+ /** Play with looking up entities */
+ public void testLookup() {
+ // load all principals
+ List<EntityNameLookupRecord> principals =
+ polarisMetaStoreManager
+ .listEntities(
+ this.polarisCallContext,
+ null,
+ PolarisEntityType.PRINCIPAL,
+ PolarisEntitySubType.NULL_SUBTYPE)
+ .getEntities();
+
+ // ensure not null, one element only
+ Assertions.assertThat(principals).isNotNull().hasSize(1);
+
+ // get catalog list information
+ EntityNameLookupRecord principalListInfo = principals.get(0);
+
+ PolarisBaseEntity principal =
+ this.ensureExistsById(
+ null,
+ principalListInfo.getId(),
+ true,
+ PolarisEntityConstants.getRootPrincipalName(),
+ PolarisEntityType.PRINCIPAL,
+ PolarisEntitySubType.NULL_SUBTYPE);
+
+ this.ensureNotExistsById(
+ PolarisEntityConstants.getNullId(), principal.getId(),
PolarisEntityType.PRINCIPAL_ROLE);
+ this.ensureNotExistsById(
+ PolarisEntityConstants.getNullId(), principal.getId(),
PolarisEntityType.CATALOG);
+ this.ensureNotExistsById(
+ PolarisEntityConstants.getNullId(), principal.getId(),
PolarisEntityType.CATALOG_ROLE);
+
+ // create new catalog
+ PolarisBaseEntity catalog =
+ new PolarisBaseEntity(
+ PolarisEntityConstants.getNullId(),
+
polarisMetaStoreManager.generateNewEntityId(this.polarisCallContext).getId(),
+ PolarisEntityType.CATALOG,
+ PolarisEntitySubType.NULL_SUBTYPE,
+ PolarisEntityConstants.getRootEntityId(),
+ "test");
+ CreateCatalogResult catalogCreated =
+ polarisMetaStoreManager.createCatalog(this.polarisCallContext,
catalog, List.of());
+ Assertions.assertThat(catalogCreated).isNotNull();
+ catalog = catalogCreated.getCatalog();
+
+ // now create all objects
+ PolarisBaseEntity N1 = this.createEntity(List.of(catalog),
PolarisEntityType.NAMESPACE, "N1");
+ PolarisBaseEntity N1_N2 =
+ this.createEntity(List.of(catalog, N1), PolarisEntityType.NAMESPACE,
"N2");
+ PolarisBaseEntity T1 =
+ this.createEntity(
+ List.of(catalog, N1, N1_N2),
+ PolarisEntityType.TABLE_LIKE,
+ PolarisEntitySubType.ICEBERG_TABLE,
+ "T1");
+
+ this.ensureNotExistsById(catalog.getId(), T1.getId(),
PolarisEntityType.NAMESPACE);
+ }
+
/** Test the set of functions for the entity cache */
public void testEntityCache() {
// create test catalog