You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polaris.apache.org by yz...@apache.org on 2026/04/03 00:42:56 UTC
(polaris) branch yzou-generic-table-credential-vending updated: Parse access delegation mode in GenericTable load and create like Iceberg
This is an automated email from the ASF dual-hosted git repository.
yzou pushed a commit to branch yzou-generic-table-credential-vending
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/yzou-generic-table-credential-vending by this push:
new ab0f1bf264 Parse access delegation mode in GenericTable load and create like Iceberg
ab0f1bf264 is described below
commit ab0f1bf264cb41ce18062546c0421bd30767ebe0
Author: Yun Zou <yu...@gmail.com>
AuthorDate: Thu Apr 2 17:42:51 2026 -0700
Parse access delegation mode in GenericTable load and create like Iceberg
Made-with: Cursor
---
.../generic/GenericTableCatalogAdapter.java | 24 ++++++++++++++++--
.../generic/GenericTableCatalogHandler.java | 29 ++++++++++++++--------
...PolarisGenericTableCatalogHandlerAuthzTest.java | 23 ++++++++++++++---
3 files changed, 60 insertions(+), 16 deletions(-)
diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java
index 72a48e3054..c45844a77b 100644
--- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java
+++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java
@@ -18,18 +18,22 @@
*/
package org.apache.polaris.service.catalog.generic;
+import static org.apache.polaris.service.catalog.AccessDelegationMode.VENDED_CREDENTIALS;
import static org.apache.polaris.service.catalog.common.CatalogUtils.decodeNamespace;
+import com.google.common.base.Preconditions;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext;
+import java.util.EnumSet;
import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.polaris.core.auth.PolarisPrincipal;
import org.apache.polaris.core.config.FeatureConfiguration;
import org.apache.polaris.core.config.RealmConfig;
import org.apache.polaris.core.context.CallContext;
import org.apache.polaris.core.context.RealmContext;
+import org.apache.polaris.service.catalog.AccessDelegationMode;
import org.apache.polaris.service.catalog.CatalogPrefixParser;
import org.apache.polaris.service.catalog.api.PolarisCatalogGenericTableApiService;
import org.apache.polaris.service.catalog.common.CatalogAdapter;
@@ -67,6 +71,16 @@ public class GenericTableCatalogAdapter
return handlerFactory.createHandler(catalogName, principal);
}
+ private EnumSet<AccessDelegationMode> parseAccessDelegationModes(String accessDelegationMode) {
+ EnumSet<AccessDelegationMode> delegationModes =
+ AccessDelegationMode.fromProtocolValuesList(accessDelegationMode);
+ Preconditions.checkArgument(
+ delegationModes.isEmpty() || delegationModes.contains(VENDED_CREDENTIALS),
+ "Unsupported access delegation mode: %s",
+ accessDelegationMode);
+ return delegationModes;
+ }
+
@Override
public Response createGenericTable(
String prefix,
@@ -75,6 +89,8 @@ public class GenericTableCatalogAdapter
String polarisGenericTableAccessDelegation,
RealmContext realmContext,
SecurityContext securityContext) {
+ EnumSet<AccessDelegationMode> delegationModes =
+ parseAccessDelegationModes(polarisGenericTableAccessDelegation);
GenericTableCatalogHandler handler = newHandler(securityContext, prefix);
LoadGenericTableResponse response =
handler.createGenericTable(
@@ -82,7 +98,8 @@ public class GenericTableCatalogAdapter
createGenericTableRequest.getFormat(),
createGenericTableRequest.getBaseLocation(),
createGenericTableRequest.getDoc(),
- reservedProperties.removeReservedProperties(createGenericTableRequest.getProperties()));
+ reservedProperties.removeReservedProperties(createGenericTableRequest.getProperties()),
+ delegationModes);
return Response.ok(response).build();
}
@@ -120,9 +137,12 @@ public class GenericTableCatalogAdapter
String polarisGenericTableAccessDelegation,
RealmContext realmContext,
SecurityContext securityContext) {
+ EnumSet<AccessDelegationMode> delegationModes =
+ parseAccessDelegationModes(polarisGenericTableAccessDelegation);
GenericTableCatalogHandler handler = newHandler(securityContext, prefix);
LoadGenericTableResponse response =
- handler.loadGenericTable(TableIdentifier.of(decodeNamespace(namespace), genericTable));
+ handler.loadGenericTable(
+ TableIdentifier.of(decodeNamespace(namespace), genericTable), delegationModes);
return Response.ok(response).build();
}
}
diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java
index 4794642e3e..28a85d7090 100644
--- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java
+++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java
@@ -18,8 +18,11 @@
*/
package org.apache.polaris.service.catalog.generic;
+import static org.apache.polaris.service.catalog.AccessDelegationMode.VENDED_CREDENTIALS;
+
import io.smallrye.common.annotation.Identifier;
import jakarta.enterprise.inject.Instance;
+import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -40,6 +43,7 @@ import org.apache.polaris.core.entity.table.GenericTableEntity;
import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
import org.apache.polaris.core.storage.PolarisStorageActions;
import org.apache.polaris.immutables.PolarisImmutable;
+import org.apache.polaris.service.catalog.AccessDelegationMode;
import org.apache.polaris.service.catalog.common.CatalogHandler;
import org.apache.polaris.service.catalog.common.CatalogUtils;
import org.apache.polaris.service.catalog.io.StorageAccessConfigProvider;
@@ -120,7 +124,8 @@ public abstract class GenericTableCatalogHandler extends CatalogHandler {
String format,
String baseLocation,
String doc,
- Map<String, String> properties) {
+ Map<String, String> properties,
+ EnumSet<AccessDelegationMode> delegationModes) {
PolarisAuthorizableOperation op = PolarisAuthorizableOperation.CREATE_TABLE_DIRECT;
authorizeCreateTableLikeUnderNamespaceOperationOrThrow(op, identifier);
@@ -137,7 +142,7 @@ public abstract class GenericTableCatalogHandler extends CatalogHandler {
.build();
List<StorageAccessConfig> storageAccessConfigs =
- isCredentialVendingEnabled()
+ shouldVendCredentials(delegationModes)
? vendCredentials(
identifier,
createdEntity,
@@ -160,13 +165,14 @@ public abstract class GenericTableCatalogHandler extends CatalogHandler {
return this.genericTableCatalog.dropGenericTable(identifier);
}
- public LoadGenericTableResponse loadGenericTable(TableIdentifier identifier) {
+ public LoadGenericTableResponse loadGenericTable(
+ TableIdentifier identifier, EnumSet<AccessDelegationMode> delegationModes) {
ensureResolutionManifestForTable(identifier);
- boolean credentialVendingEnabled = isCredentialVendingEnabled();
+ boolean credentialVendingRequested = shouldVendCredentials(delegationModes);
Set<PolarisStorageActions> actionsRequested =
authorizeLoadTableLike(
- identifier, PolarisEntitySubType.GENERIC_TABLE, credentialVendingEnabled);
+ identifier, PolarisEntitySubType.GENERIC_TABLE, credentialVendingRequested);
GenericTableEntity loadedEntity = this.genericTableCatalog.loadGenericTable(identifier);
GenericTable loadedTable =
@@ -179,7 +185,7 @@ public abstract class GenericTableCatalogHandler extends CatalogHandler {
.build();
List<StorageAccessConfig> storageAccessConfigs =
- credentialVendingEnabled
+ credentialVendingRequested
? vendCredentials(identifier, loadedEntity, actionsRequested)
: List.of();
@@ -189,11 +195,12 @@ public abstract class GenericTableCatalogHandler extends CatalogHandler {
.build();
}
- private boolean isCredentialVendingEnabled() {
- return realmConfig()
- .getConfig(
- FeatureConfiguration.ENABLE_GENERIC_TABLES_CREDENTIAL_VENDING,
- resolutionManifest.getResolvedCatalogEntity());
+ private boolean shouldVendCredentials(EnumSet<AccessDelegationMode> delegationModes) {
+ return delegationModes.contains(VENDED_CREDENTIALS)
+ && realmConfig()
+ .getConfig(
+ FeatureConfiguration.ENABLE_GENERIC_TABLES_CREDENTIAL_VENDING,
+ resolutionManifest.getResolvedCatalogEntity());
}
private List<StorageAccessConfig> vendCredentials(
diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/PolarisGenericTableCatalogHandlerAuthzTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/PolarisGenericTableCatalogHandlerAuthzTest.java
index 0dceebe8c2..dfaeec776d 100644
--- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/PolarisGenericTableCatalogHandlerAuthzTest.java
+++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/PolarisGenericTableCatalogHandlerAuthzTest.java
@@ -21,6 +21,7 @@ package org.apache.polaris.service.catalog.generic;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;
import jakarta.inject.Inject;
+import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
@@ -28,6 +29,7 @@ import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.polaris.core.auth.PolarisPrincipal;
import org.apache.polaris.core.entity.PolarisPrivilege;
import org.apache.polaris.service.admin.PolarisAuthzTestBase;
+import org.apache.polaris.service.catalog.AccessDelegationMode;
import org.junit.jupiter.api.DynamicNode;
import org.junit.jupiter.api.TestFactory;
@@ -84,7 +86,13 @@ public class PolarisGenericTableCatalogHandlerAuthzTest extends PolarisAuthzTest
.action(
() ->
newWrapper(Set.of(PRINCIPAL_ROLE1))
- .createGenericTable(newtable, "format", "file:///temp/", "doc", Map.of()))
+ .createGenericTable(
+ newtable,
+ "format",
+ "file:///temp/",
+ "doc",
+ Map.of(),
+ EnumSet.noneOf(AccessDelegationMode.class)))
.cleanupAction(() -> newWrapper(Set.of(PRINCIPAL_ROLE2)).dropGenericTable(newtable))
.shouldPassWith(PolarisPrivilege.TABLE_CREATE)
.shouldPassWith(PolarisPrivilege.TABLE_FULL_METADATA)
@@ -96,7 +104,11 @@ public class PolarisGenericTableCatalogHandlerAuthzTest extends PolarisAuthzTest
@TestFactory
Stream<DynamicNode> testLoadGenericTablePrivileges() {
return authzTestsBuilder("loadGenericTable")
- .action(() -> newWrapper().loadGenericTable(TABLE_NS1_1_GENERIC))
+ .action(
+ () ->
+ newWrapper()
+ .loadGenericTable(
+ TABLE_NS1_1_GENERIC, EnumSet.noneOf(AccessDelegationMode.class)))
.shouldPassWith(PolarisPrivilege.TABLE_READ_PROPERTIES)
.shouldPassWith(PolarisPrivilege.TABLE_WRITE_PROPERTIES)
.shouldPassWith(PolarisPrivilege.TABLE_READ_DATA)
@@ -119,7 +131,12 @@ public class PolarisGenericTableCatalogHandlerAuthzTest extends PolarisAuthzTest
() ->
newWrapper(Set.of(PRINCIPAL_ROLE2))
.createGenericTable(
- TABLE_NS1_1_GENERIC, "format", "file:///temp/", "doc", Map.of()))
+ TABLE_NS1_1_GENERIC,
+ "format",
+ "file:///temp/",
+ "doc",
+ Map.of(),
+ EnumSet.noneOf(AccessDelegationMode.class)))
.shouldPassWith(PolarisPrivilege.TABLE_DROP)
.shouldPassWith(PolarisPrivilege.TABLE_FULL_METADATA)
.shouldPassWith(PolarisPrivilege.CATALOG_MANAGE_CONTENT)