From b162544f72a0e4568f3877f7e2de00867d2e6730 Mon Sep 17 00:00:00 2001 From: Christopher Lambert <1204398+XN137@users.noreply.github.com> Date: Tue, 28 Oct 2025 13:13:43 +0100 Subject: [PATCH] Prefer PolarisPrincipal over SecurityContext The general idea is that `SecurityContext` comes from `jakarta.ws.rs` and there is no reason for non-REST related classes to rely on those details. Instead, once preprocessing of a REST-request has inferred the `PolarisPrincipal` all inner/core code should rely on only that. Note that this simplifies a bunch of tests that had to create their own `SecurityContext` around the principal that they wanted to use, thus having to decide how to implement `isUserInRole` and the other methods. --- .../resolver/PolarisResolutionManifest.java | 18 ++++------ .../resolver/ResolutionManifestFactory.java | 4 +-- .../ResolutionManifestFactoryImpl.java | 6 ++-- .../core/persistence/resolver/Resolver.java | 16 +++------ .../persistence/resolver/ResolverFactory.java | 4 +-- .../core/persistence/BaseResolverTest.java | 26 +------------- .../service/admin/PolarisAdminService.java | 18 ++-------- .../catalog/common/CatalogAdapter.java | 9 ++--- .../catalog/common/CatalogHandler.java | 15 ++------ .../generic/GenericTableCatalogAdapter.java | 5 +-- .../generic/GenericTableCatalogHandler.java | 6 ++-- .../catalog/iceberg/IcebergCatalog.java | 10 +++--- .../iceberg/IcebergCatalogAdapter.java | 6 ++-- .../iceberg/IcebergCatalogHandler.java | 8 ++--- .../catalog/policy/PolicyCatalogAdapter.java | 5 +-- .../catalog/policy/PolicyCatalogHandler.java | 6 ++-- .../service/config/ServiceProducers.java | 21 +++++++++-- .../catalog/CallContextCatalogFactory.java | 2 -- .../PolarisCallContextCatalogFactory.java | 4 +-- .../service/admin/ManagementServiceTest.java | 35 ++++--------------- .../admin/PolarisAdminServiceAuthzTest.java | 3 +- .../admin/PolarisAdminServiceTest.java | 9 +---- .../service/admin/PolarisAuthzTestBase.java | 21 +++-------- .../service/admin/PolarisServiceImplTest.java | 17 ++------- ...bstractPolarisGenericTableCatalogTest.java | 12 ++----- ...isGenericTableCatalogHandlerAuthzTest.java | 2 +- .../iceberg/AbstractIcebergCatalogTest.java | 19 ++++------ .../AbstractIcebergCatalogViewTest.java | 13 ++----- .../IcebergCatalogHandlerAuthzTest.java | 17 ++++----- ...CatalogHandlerFineGrainedDisabledTest.java | 2 +- .../service/catalog/io/FileIOFactoryTest.java | 4 +-- .../policy/AbstractPolicyCatalogTest.java | 12 ++----- .../policy/PolicyCatalogHandlerAuthzTest.java | 2 +- .../apache/polaris/service/TestServices.java | 9 ++--- .../PolarisPassthroughResolutionView.java | 10 +++--- 35 files changed, 125 insertions(+), 251 deletions(-) diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java index 84ad20be0a..1b9c26e02a 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java @@ -21,7 +21,6 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import jakarta.annotation.Nullable; -import jakarta.ws.rs.core.SecurityContext; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -52,7 +51,7 @@ public class PolarisResolutionManifest implements PolarisResolutionManifestCatal private static final Logger LOGGER = LoggerFactory.getLogger(PolarisResolutionManifest.class); private final ResolverFactory resolverFactory; - private final SecurityContext securityContext; + private final PolarisPrincipal principal; private final RealmContext realmContext; private final String catalogName; private final Resolver primaryResolver; @@ -73,20 +72,15 @@ public PolarisResolutionManifest( PolarisDiagnostics diagnostics, RealmContext realmContext, ResolverFactory resolverFactory, - SecurityContext securityContext, + PolarisPrincipal principal, String catalogName) { this.realmContext = realmContext; this.resolverFactory = resolverFactory; this.catalogName = catalogName; - this.primaryResolver = resolverFactory.createResolver(securityContext, catalogName); this.diagnostics = diagnostics; - this.diagnostics.checkNotNull(securityContext, "null_security_context_for_resolution_manifest"); - this.securityContext = securityContext; - diagnostics.check( - securityContext.getUserPrincipal() instanceof PolarisPrincipal, - "invalid_principal_type_for_resolution_manifest", - "principal={}", - securityContext.getUserPrincipal()); + this.diagnostics.checkNotNull(principal, "null_principal_for_resolution_manifest"); + this.principal = principal; + this.primaryResolver = resolverFactory.createResolver(principal, catalogName); // TODO: Make the rootContainer lookup no longer optional in the persistence store. // For now, we'll try to resolve the rootContainer as "optional", and only if we fail to find @@ -186,7 +180,7 @@ public PolarisResolvedPathWrapper getPassthroughResolvedPath(Object key) { ResolverPath requestedPath = passthroughPaths.get(key); // Run a single-use Resolver for this path. - Resolver passthroughResolver = resolverFactory.createResolver(securityContext, catalogName); + Resolver passthroughResolver = resolverFactory.createResolver(principal, catalogName); passthroughResolver.addPath(requestedPath); ResolverStatus status = passthroughResolver.resolveAll(); diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactory.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactory.java index 70b4bd122b..0fe3d5a2cc 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactory.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactory.java @@ -21,11 +21,11 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import jakarta.ws.rs.core.SecurityContext; +import org.apache.polaris.core.auth.PolarisPrincipal; public interface ResolutionManifestFactory { @Nonnull PolarisResolutionManifest createResolutionManifest( - @Nonnull SecurityContext securityContext, @Nullable String referenceCatalogName); + @Nonnull PolarisPrincipal principal, @Nullable String referenceCatalogName); } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactoryImpl.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactoryImpl.java index 6e866e400c..1246bac9e4 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactoryImpl.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactoryImpl.java @@ -21,8 +21,8 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import jakarta.ws.rs.core.SecurityContext; import org.apache.polaris.core.PolarisDiagnostics; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.context.RealmContext; public class ResolutionManifestFactoryImpl implements ResolutionManifestFactory { @@ -43,8 +43,8 @@ public ResolutionManifestFactoryImpl( @Nonnull @Override public PolarisResolutionManifest createResolutionManifest( - @Nonnull SecurityContext securityContext, @Nullable String referenceCatalogName) { + @Nonnull PolarisPrincipal principal, @Nullable String referenceCatalogName) { return new PolarisResolutionManifest( - diagnostics, realmContext, resolverFactory, securityContext, referenceCatalogName); + diagnostics, realmContext, resolverFactory, principal, referenceCatalogName); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java index 913086ce7a..50c4a4f193 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java @@ -20,7 +20,6 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import jakarta.ws.rs.core.SecurityContext; import java.util.AbstractSet; import java.util.ArrayList; import java.util.HashMap; @@ -116,7 +115,7 @@ public class Resolver { * * @param polarisCallContext the polaris call context * @param polarisMetaStoreManager meta store manager - * @param securityContext The {@link SecurityContext} for the current request + * @param principal The {@link PolarisPrincipal} for the current request * @param cache shared entity cache * @param referenceCatalogName if not null, specifies the name of the reference catalog. The * reference catalog is the catalog used to resolve catalog roles and catalog path. Also, if a @@ -130,7 +129,7 @@ public Resolver( @Nonnull PolarisDiagnostics diagnostics, @Nonnull PolarisCallContext polarisCallContext, @Nonnull PolarisMetaStoreManager polarisMetaStoreManager, - @Nonnull SecurityContext securityContext, + @Nonnull PolarisPrincipal principal, @Nullable EntityCache cache, @Nullable String referenceCatalogName) { this.polarisCallContext = polarisCallContext; @@ -143,16 +142,9 @@ public Resolver( this.diagnostics.checkNotNull(polarisCallContext, "unexpected_null_polarisCallContext"); this.diagnostics.checkNotNull( polarisMetaStoreManager, "unexpected_null_polarisMetaStoreManager"); - this.diagnostics.checkNotNull(securityContext, "security_context_must_be_specified"); - this.diagnostics.checkNotNull( - securityContext.getUserPrincipal(), "principal_must_be_specified"); - this.diagnostics.check( - securityContext.getUserPrincipal() instanceof PolarisPrincipal, - "unexpected_principal_type", - "class={}", - securityContext.getUserPrincipal().getClass().getName()); + this.diagnostics.checkNotNull(principal, "principal_must_be_specified"); - this.polarisPrincipal = (PolarisPrincipal) securityContext.getUserPrincipal(); + this.polarisPrincipal = principal; // paths to resolve this.pathsToResolve = new ArrayList<>(); this.resolvedPaths = new ArrayList<>(); diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolverFactory.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolverFactory.java index 97d2816745..71c050e5d1 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolverFactory.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolverFactory.java @@ -21,9 +21,9 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import jakarta.ws.rs.core.SecurityContext; +import org.apache.polaris.core.auth.PolarisPrincipal; public interface ResolverFactory { Resolver createResolver( - @Nonnull SecurityContext securityContext, @Nullable String referenceCatalogName); + @Nonnull PolarisPrincipal principal, @Nullable String referenceCatalogName); } diff --git a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BaseResolverTest.java b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BaseResolverTest.java index 89fd94fcbb..d40d13813f 100644 --- a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BaseResolverTest.java +++ b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BaseResolverTest.java @@ -20,8 +20,6 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import jakarta.ws.rs.core.SecurityContext; -import java.security.Principal; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; @@ -442,29 +440,7 @@ private Resolver allocateResolver( diagServices, callCtx(), metaStoreManager(), - new SecurityContext() { - @Override - public Principal getUserPrincipal() { - return authenticatedPrincipal; - } - - @Override - public boolean isUserInRole(String role) { - return roleEntities - .map(l -> l.stream().map(PrincipalRoleEntity::getName).anyMatch(role::equals)) - .orElse(allRoles); - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public String getAuthenticationScheme() { - return ""; - } - }, + authenticatedPrincipal, this.shouldUseCache ? this.cache : null, referenceCatalogName); } diff --git a/runtime/service/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java b/runtime/service/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java index 44e2d95f1d..3aaeafbaf1 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java @@ -26,7 +26,6 @@ import jakarta.annotation.Nullable; import jakarta.enterprise.context.RequestScoped; import jakarta.inject.Inject; -import jakarta.ws.rs.core.SecurityContext; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -47,7 +46,6 @@ import org.apache.iceberg.exceptions.NotFoundException; import org.apache.iceberg.exceptions.ValidationException; import org.apache.polaris.core.PolarisCallContext; -import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.admin.model.AuthenticationParameters; import org.apache.polaris.core.admin.model.BearerAuthenticationParameters; import org.apache.polaris.core.admin.model.Catalog; @@ -146,7 +144,6 @@ public class PolarisAdminService { private final CallContext callContext; private final RealmConfig realmConfig; private final ResolutionManifestFactory resolutionManifestFactory; - private final SecurityContext securityContext; private final PolarisPrincipal polarisPrincipal; private final PolarisAuthorizer authorizer; private final PolarisMetaStoreManager metaStoreManager; @@ -156,28 +153,19 @@ public class PolarisAdminService { @Inject public PolarisAdminService( - @Nonnull PolarisDiagnostics diagnostics, @Nonnull CallContext callContext, @Nonnull ResolutionManifestFactory resolutionManifestFactory, @Nonnull PolarisMetaStoreManager metaStoreManager, @Nonnull UserSecretsManager userSecretsManager, @Nonnull ServiceIdentityProvider serviceIdentityProvider, - @Nonnull SecurityContext securityContext, + @Nonnull PolarisPrincipal principal, @Nonnull PolarisAuthorizer authorizer, @Nonnull ReservedProperties reservedProperties) { this.callContext = callContext; this.realmConfig = callContext.getRealmConfig(); this.resolutionManifestFactory = resolutionManifestFactory; this.metaStoreManager = metaStoreManager; - this.securityContext = securityContext; - diagnostics.checkNotNull(securityContext, "null_security_context"); - diagnostics.checkNotNull(securityContext.getUserPrincipal(), "null_security_context"); - diagnostics.check( - securityContext.getUserPrincipal() instanceof PolarisPrincipal, - "unexpected_principal_type", - "class={}", - securityContext.getUserPrincipal().getClass().getName()); - this.polarisPrincipal = (PolarisPrincipal) securityContext.getUserPrincipal(); + this.polarisPrincipal = principal; this.authorizer = authorizer; this.userSecretsManager = userSecretsManager; this.serviceIdentityProvider = serviceIdentityProvider; @@ -197,7 +185,7 @@ private ServiceIdentityProvider getServiceIdentityProvider() { } private PolarisResolutionManifest newResolutionManifest(@Nullable String catalogName) { - return resolutionManifestFactory.createResolutionManifest(securityContext, catalogName); + return resolutionManifestFactory.createResolutionManifest(polarisPrincipal, catalogName); } private static PrincipalEntity getPrincipalByName( diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogAdapter.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogAdapter.java index 6fe9dcf48d..b518330a62 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogAdapter.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogAdapter.java @@ -35,10 +35,11 @@ default Namespace decodeNamespace(String namespace) { return RESTUtil.decodeNamespace(URLEncoder.encode(namespace, Charset.defaultCharset())); } - default void validatePrincipal(SecurityContext securityContext) { - var authenticatedPrincipal = (PolarisPrincipal) securityContext.getUserPrincipal(); - if (authenticatedPrincipal == null) { - throw new NotAuthorizedException("Failed to find authenticatedPrincipal in SecurityContext"); + default PolarisPrincipal validatePrincipal(SecurityContext securityContext) { + var authenticatedPrincipal = securityContext.getUserPrincipal(); + if (authenticatedPrincipal instanceof PolarisPrincipal polarisPrincipal) { + return polarisPrincipal; } + throw new NotAuthorizedException("Failed to find authenticatedPrincipal in SecurityContext"); } } diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java index 4be7a55f52..9d5778ac29 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java @@ -21,7 +21,6 @@ import static org.apache.polaris.core.entity.PolarisEntitySubType.ICEBERG_TABLE; import jakarta.enterprise.inject.Instance; -import jakarta.ws.rs.core.SecurityContext; import java.util.Arrays; import java.util.EnumSet; import java.util.List; @@ -70,13 +69,12 @@ public abstract class CatalogHandler { protected final CallContext callContext; protected final RealmConfig realmConfig; protected final PolarisPrincipal polarisPrincipal; - protected final SecurityContext securityContext; public CatalogHandler( PolarisDiagnostics diagnostics, CallContext callContext, ResolutionManifestFactory resolutionManifestFactory, - SecurityContext securityContext, + PolarisPrincipal principal, String catalogName, PolarisAuthorizer authorizer, PolarisCredentialManager credentialManager, @@ -86,14 +84,7 @@ public CatalogHandler( this.realmConfig = callContext.getRealmConfig(); this.resolutionManifestFactory = resolutionManifestFactory; this.catalogName = catalogName; - diagnostics.checkNotNull(securityContext, "null_security_context"); - diagnostics.checkNotNull(securityContext.getUserPrincipal(), "null_user_principal"); - diagnostics.check( - securityContext.getUserPrincipal() instanceof PolarisPrincipal, - "invalid_principal_type", - "Principal must be a PolarisPrincipal"); - this.securityContext = securityContext; - this.polarisPrincipal = (PolarisPrincipal) securityContext.getUserPrincipal(); + this.polarisPrincipal = principal; this.authorizer = authorizer; this.credentialManager = credentialManager; this.externalCatalogFactories = externalCatalogFactories; @@ -104,7 +95,7 @@ protected PolarisCredentialManager getPolarisCredentialManager() { } protected PolarisResolutionManifest newResolutionManifest() { - return resolutionManifestFactory.createResolutionManifest(securityContext, catalogName); + return resolutionManifestFactory.createResolutionManifest(polarisPrincipal, catalogName); } /** Initialize the catalog once authorized. Called after all `authorize...` methods. */ 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 5cf634aedd..e52122dbcf 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 @@ -27,6 +27,7 @@ import org.apache.iceberg.catalog.TableIdentifier; import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.auth.PolarisAuthorizer; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.catalog.ExternalCatalogFactory; import org.apache.polaris.core.config.FeatureConfiguration; import org.apache.polaris.core.config.RealmConfig; @@ -92,14 +93,14 @@ private GenericTableCatalogHandler newHandlerWrapper( SecurityContext securityContext, String prefix) { FeatureConfiguration.enforceFeatureEnabledOrThrow( realmConfig, FeatureConfiguration.ENABLE_GENERIC_TABLES); - validatePrincipal(securityContext); + PolarisPrincipal principal = validatePrincipal(securityContext); return new GenericTableCatalogHandler( diagnostics, callContext, resolutionManifestFactory, metaStoreManager, - securityContext, + principal, prefixParser.prefixToCatalogName(realmContext, prefix), polarisAuthorizer, polarisCredentialManager, 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 55d52070f5..eeb8206da0 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 @@ -20,7 +20,6 @@ import io.smallrye.common.annotation.Identifier; import jakarta.enterprise.inject.Instance; -import jakarta.ws.rs.core.SecurityContext; import java.util.LinkedHashSet; import java.util.Map; import org.apache.iceberg.catalog.Namespace; @@ -28,6 +27,7 @@ import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.auth.PolarisAuthorizableOperation; import org.apache.polaris.core.auth.PolarisAuthorizer; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.catalog.ExternalCatalogFactory; import org.apache.polaris.core.catalog.GenericTableCatalog; import org.apache.polaris.core.config.FeatureConfiguration; @@ -59,7 +59,7 @@ public GenericTableCatalogHandler( CallContext callContext, ResolutionManifestFactory resolutionManifestFactory, PolarisMetaStoreManager metaStoreManager, - SecurityContext securityContext, + PolarisPrincipal principal, String catalogName, PolarisAuthorizer authorizer, PolarisCredentialManager polarisCredentialManager, @@ -68,7 +68,7 @@ public GenericTableCatalogHandler( diagnostics, callContext, resolutionManifestFactory, - securityContext, + principal, catalogName, authorizer, polarisCredentialManager, diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java index 39315d8386..1f94cde9cb 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java @@ -28,7 +28,6 @@ import com.google.common.collect.ImmutableMap; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import jakarta.ws.rs.core.SecurityContext; import java.io.Closeable; import java.io.IOException; import java.net.URLEncoder; @@ -90,6 +89,7 @@ import org.apache.iceberg.view.ViewUtil; import org.apache.polaris.core.PolarisCallContext; import org.apache.polaris.core.PolarisDiagnostics; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.catalog.PolarisCatalogHelpers; import org.apache.polaris.core.config.BehaviorChangeConfiguration; import org.apache.polaris.core.config.FeatureConfiguration; @@ -166,7 +166,7 @@ public class IcebergCatalog extends BaseMetastoreViewCatalog private final PolarisResolutionManifestCatalogView resolvedEntityView; private final CatalogEntity catalogEntity; private final TaskExecutor taskExecutor; - private final SecurityContext securityContext; + private final PolarisPrincipal principal; private final PolarisEventListener polarisEventListener; private final AtomicBoolean loggedPrefixOverlapWarning = new AtomicBoolean(false); @@ -195,7 +195,7 @@ public IcebergCatalog( PolarisMetaStoreManager metaStoreManager, CallContext callContext, PolarisResolutionManifestCatalogView resolvedEntityView, - SecurityContext securityContext, + PolarisPrincipal principal, TaskExecutor taskExecutor, AccessConfigProvider accessConfigProvider, FileIOFactory fileIOFactory, @@ -206,7 +206,7 @@ public IcebergCatalog( this.realmConfig = callContext.getRealmConfig(); this.resolvedEntityView = resolvedEntityView; this.catalogEntity = resolvedEntityView.getResolvedCatalogEntity(); - this.securityContext = securityContext; + this.principal = principal; this.taskExecutor = taskExecutor; this.catalogId = catalogEntity.getId(); this.catalogName = catalogEntity.getName(); @@ -1163,7 +1163,7 @@ private void validateNoLocationO diagnostics, callContext.getRealmContext(), resolverFactory, - securityContext, + principal, parentPath.getFirst().getName()); siblingTables.forEach( tbl -> diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java index dbbdd17551..e7ac691415 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java @@ -208,7 +208,7 @@ private Response withCatalog( @VisibleForTesting IcebergCatalogHandler newHandlerWrapper(SecurityContext securityContext, String catalogName) { - validatePrincipal(securityContext); + PolarisPrincipal principal = validatePrincipal(securityContext); return new IcebergCatalogHandler( diagnostics, @@ -216,7 +216,7 @@ IcebergCatalogHandler newHandlerWrapper(SecurityContext securityContext, String resolutionManifestFactory, metaStoreManager, credentialManager, - securityContext, + principal, catalogFactory, catalogName, polarisAuthorizer, @@ -799,7 +799,7 @@ public Response getConfig( if (warehouse == null) { throw new BadRequestException("Please specify a warehouse"); } - Resolver resolver = resolverFactory.createResolver(securityContext, warehouse); + Resolver resolver = resolverFactory.createResolver(authenticatedPrincipal, warehouse); ResolverStatus resolverStatus = resolver.resolveAll(); if (!resolverStatus.getStatus().equals(ResolverStatus.StatusEnum.SUCCESS)) { throw new NotFoundException("Unable to find warehouse %s", warehouse); diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java index c3b92971aa..772aaf4772 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java @@ -28,7 +28,6 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import jakarta.enterprise.inject.Instance; -import jakarta.ws.rs.core.SecurityContext; import java.io.Closeable; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -80,6 +79,7 @@ import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.auth.PolarisAuthorizableOperation; import org.apache.polaris.core.auth.PolarisAuthorizer; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.catalog.ExternalCatalogFactory; import org.apache.polaris.core.config.FeatureConfiguration; import org.apache.polaris.core.connection.ConnectionConfigInfoDpo; @@ -156,7 +156,7 @@ public IcebergCatalogHandler( ResolutionManifestFactory resolutionManifestFactory, PolarisMetaStoreManager metaStoreManager, PolarisCredentialManager credentialManager, - SecurityContext securityContext, + PolarisPrincipal principal, CallContextCatalogFactory catalogFactory, String catalogName, PolarisAuthorizer authorizer, @@ -169,7 +169,7 @@ public IcebergCatalogHandler( diagnostics, callContext, resolutionManifestFactory, - securityContext, + principal, catalogName, authorizer, credentialManager, @@ -269,7 +269,7 @@ protected void initializeCatalog() { LOGGER.atInfo().log("Initializing non-federated catalog"); this.baseCatalog = catalogFactory.createCallContextCatalog( - callContext, polarisPrincipal, securityContext, resolutionManifest); + callContext, polarisPrincipal, resolutionManifest); } this.namespaceCatalog = (baseCatalog instanceof SupportsNamespaces) ? (SupportsNamespaces) baseCatalog : null; diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java index aa5e75fee0..9bdfef4835 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java @@ -28,6 +28,7 @@ import org.apache.iceberg.rest.RESTUtil; import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.auth.PolarisAuthorizer; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.catalog.ExternalCatalogFactory; import org.apache.polaris.core.config.FeatureConfiguration; import org.apache.polaris.core.config.RealmConfig; @@ -92,14 +93,14 @@ public PolicyCatalogAdapter( private PolicyCatalogHandler newHandlerWrapper(SecurityContext securityContext, String prefix) { FeatureConfiguration.enforceFeatureEnabledOrThrow( realmConfig, FeatureConfiguration.ENABLE_POLICY_STORE); - validatePrincipal(securityContext); + PolarisPrincipal principal = validatePrincipal(securityContext); return new PolicyCatalogHandler( diagnostics, callContext, resolutionManifestFactory, metaStoreManager, - securityContext, + principal, prefixParser.prefixToCatalogName(realmContext, prefix), polarisAuthorizer, polarisCredentialManager, diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java index 504b0a8d3c..712193e400 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java @@ -21,7 +21,6 @@ import com.google.common.base.Strings; import jakarta.annotation.Nullable; import jakarta.enterprise.inject.Instance; -import jakarta.ws.rs.core.SecurityContext; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -33,6 +32,7 @@ import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.auth.PolarisAuthorizableOperation; import org.apache.polaris.core.auth.PolarisAuthorizer; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.catalog.ExternalCatalogFactory; import org.apache.polaris.core.catalog.PolarisCatalogHelpers; import org.apache.polaris.core.context.CallContext; @@ -68,7 +68,7 @@ public PolicyCatalogHandler( CallContext callContext, ResolutionManifestFactory resolutionManifestFactory, PolarisMetaStoreManager metaStoreManager, - SecurityContext securityContext, + PolarisPrincipal principal, String catalogName, PolarisAuthorizer authorizer, PolarisCredentialManager polarisCredentialManager, @@ -77,7 +77,7 @@ public PolicyCatalogHandler( diagnostics, callContext, resolutionManifestFactory, - securityContext, + principal, catalogName, authorizer, polarisCredentialManager, diff --git a/runtime/service/src/main/java/org/apache/polaris/service/config/ServiceProducers.java b/runtime/service/src/main/java/org/apache/polaris/service/config/ServiceProducers.java index 6b5181929f..01e9f6e896 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/config/ServiceProducers.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/config/ServiceProducers.java @@ -32,6 +32,8 @@ import jakarta.inject.Singleton; import jakarta.ws.rs.container.ContainerRequestContext; import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.SecurityContext; +import java.security.Principal; import java.time.Clock; import java.util.stream.Collectors; import org.apache.polaris.core.PolarisCallContext; @@ -40,6 +42,7 @@ import org.apache.polaris.core.auth.DefaultPolarisAuthorizerFactory; import org.apache.polaris.core.auth.PolarisAuthorizer; import org.apache.polaris.core.auth.PolarisAuthorizerFactory; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.config.PolarisConfigurationStore; import org.apache.polaris.core.config.RealmConfig; import org.apache.polaris.core.context.CallContext; @@ -175,12 +178,12 @@ public ResolverFactory resolverFactory( PolarisMetaStoreManager polarisMetaStoreManager) { EntityCache entityCache = metaStoreManagerFactory.getOrCreateEntityCache(realmContext, realmConfig); - return (securityContext, referenceCatalogName) -> + return (principal, referenceCatalogName) -> new Resolver( diagnostics, callContext.getPolarisCallContext(), polarisMetaStoreManager, - securityContext, + principal, entityCache, referenceCatalogName); } @@ -192,6 +195,20 @@ public ResolutionManifestFactory resolutionManifestFactory( return new ResolutionManifestFactoryImpl(diagnostics, realmContext, resolverFactory); } + @Produces + @RequestScoped + public PolarisPrincipal polarisPrincipal( + PolarisDiagnostics diagnostics, @Context SecurityContext securityContext) { + Principal userPrincipal = securityContext.getUserPrincipal(); + diagnostics.checkNotNull(userPrincipal, "null_security_context_principal"); + diagnostics.check( + userPrincipal instanceof PolarisPrincipal, + "unexpected_principal_type", + "class={}", + userPrincipal.getClass().getName()); + return (PolarisPrincipal) userPrincipal; + } + // Polaris service beans - selected from @Identifier-annotated beans @Produces diff --git a/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/CallContextCatalogFactory.java b/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/CallContextCatalogFactory.java index 9e8f74e2b9..c0f9fc351e 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/CallContextCatalogFactory.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/CallContextCatalogFactory.java @@ -18,7 +18,6 @@ */ package org.apache.polaris.service.context.catalog; -import jakarta.ws.rs.core.SecurityContext; import org.apache.iceberg.catalog.Catalog; import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.context.CallContext; @@ -29,6 +28,5 @@ public interface CallContextCatalogFactory { Catalog createCallContextCatalog( CallContext context, PolarisPrincipal polarisPrincipal, - SecurityContext securityContext, PolarisResolutionManifest resolvedManifest); } diff --git a/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/PolarisCallContextCatalogFactory.java b/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/PolarisCallContextCatalogFactory.java index d52e1c0fbb..7284a0745a 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/PolarisCallContextCatalogFactory.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/context/catalog/PolarisCallContextCatalogFactory.java @@ -20,7 +20,6 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import jakarta.ws.rs.core.SecurityContext; import java.util.HashMap; import java.util.Map; import org.apache.iceberg.CatalogProperties; @@ -75,7 +74,6 @@ public PolarisCallContextCatalogFactory( public Catalog createCallContextCatalog( CallContext context, PolarisPrincipal polarisPrincipal, - SecurityContext securityContext, final PolarisResolutionManifest resolvedManifest) { CatalogEntity catalog = resolvedManifest.getResolvedCatalogEntity(); String catalogName = catalog.getName(); @@ -91,7 +89,7 @@ public Catalog createCallContextCatalog( metaStoreManagerFactory.getOrCreateMetaStoreManager(context.getRealmContext()), context, resolvedManifest, - securityContext, + polarisPrincipal, taskExecutor, accessConfigProvider, fileIOFactory, diff --git a/runtime/service/src/test/java/org/apache/polaris/service/admin/ManagementServiceTest.java b/runtime/service/src/test/java/org/apache/polaris/service/admin/ManagementServiceTest.java index e13d6fe080..5439366962 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/admin/ManagementServiceTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/admin/ManagementServiceTest.java @@ -22,8 +22,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.SecurityContext; -import java.security.Principal; import java.time.Instant; import java.util.List; import java.util.Map; @@ -371,38 +369,19 @@ public void testUpdateCatalogWithDisallowedConfigs() { private PolarisAdminService setupPolarisAdminService( PolarisMetaStoreManager metaStoreManager, PolarisCallContext callContext) { + PolarisPrincipal principal = + PolarisPrincipal.of( + new PrincipalEntity.Builder() + .setName(PolarisEntityConstants.getRootPrincipalName()) + .build(), + Set.of(PolarisEntityConstants.getNameOfPrincipalServiceAdminRole())); return new PolarisAdminService( - services.polarisDiagnostics(), callContext, services.resolutionManifestFactory(), metaStoreManager, new UnsafeInMemorySecretsManager(), new DefaultServiceIdentityProvider(), - new SecurityContext() { - @Override - public Principal getUserPrincipal() { - return PolarisPrincipal.of( - new PrincipalEntity.Builder() - .setName(PolarisEntityConstants.getRootPrincipalName()) - .build(), - Set.of(PolarisEntityConstants.getNameOfPrincipalServiceAdminRole())); - } - - @Override - public boolean isUserInRole(String role) { - return true; - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public String getAuthenticationScheme() { - return ""; - } - }, + principal, new PolarisAuthorizerImpl(services.realmConfig()), ReservedProperties.NONE); } diff --git a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceAuthzTest.java b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceAuthzTest.java index 066aebf209..cc3c9aeeb2 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceAuthzTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceAuthzTest.java @@ -51,13 +51,12 @@ private PolarisAdminService newTestAdminService(Set activatedPrincipalRo final PolarisPrincipal authenticatedPrincipal = PolarisPrincipal.of(principalEntity, activatedPrincipalRoles); return new PolarisAdminService( - diagServices, callContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext(authenticatedPrincipal), + authenticatedPrincipal, polarisAuthorizer, reservedProperties); } diff --git a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java index fb58dc3442..d584dc0bdb 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java @@ -26,15 +26,12 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import jakarta.ws.rs.core.SecurityContext; import java.util.List; import org.apache.iceberg.catalog.Namespace; import org.apache.iceberg.catalog.TableIdentifier; import org.apache.iceberg.exceptions.NoSuchTableException; import org.apache.iceberg.exceptions.NotFoundException; import org.apache.polaris.core.PolarisCallContext; -import org.apache.polaris.core.PolarisDefaultDiagServiceImpl; -import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.auth.PolarisAuthorizer; import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.config.FeatureConfiguration; @@ -67,14 +64,12 @@ import org.mockito.MockitoAnnotations; public class PolarisAdminServiceTest { - private PolarisDiagnostics diagnostics = new PolarisDefaultDiagServiceImpl(); @Mock private CallContext callContext; @Mock private PolarisCallContext polarisCallContext; @Mock private ResolutionManifestFactory resolutionManifestFactory; @Mock private PolarisMetaStoreManager metaStoreManager; @Mock private UserSecretsManager userSecretsManager; @Mock private ServiceIdentityProvider identityProvider; - @Mock private SecurityContext securityContext; @Mock private PolarisAuthorizer authorizer; @Mock private ReservedProperties reservedProperties; @Mock private PolarisPrincipal authenticatedPrincipal; @@ -87,7 +82,6 @@ public class PolarisAdminServiceTest { @BeforeEach void setUp() throws Exception { MockitoAnnotations.openMocks(this); - when(securityContext.getUserPrincipal()).thenReturn(authenticatedPrincipal); when(callContext.getPolarisCallContext()).thenReturn(polarisCallContext); when(polarisCallContext.getRealmConfig()).thenReturn(realmConfig); @@ -105,13 +99,12 @@ void setUp() throws Exception { adminService = new PolarisAdminService( - diagnostics, callContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, identityProvider, - securityContext, + authenticatedPrincipal, authorizer, reservedProperties); } diff --git a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAuthzTestBase.java b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAuthzTestBase.java index 743418d657..95fd0a67ff 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAuthzTestBase.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisAuthzTestBase.java @@ -30,7 +30,6 @@ import jakarta.enterprise.inject.Alternative; import jakarta.inject.Inject; import jakarta.ws.rs.container.ContainerRequestContext; -import jakarta.ws.rs.core.SecurityContext; import java.io.IOException; import java.util.Date; import java.util.List; @@ -261,13 +260,12 @@ public void before(TestInfo testInfo) { this.adminService = new PolarisAdminService( - diagServices, callContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext(authenticatedRoot), + authenticatedRoot, polarisAuthorizer, reservedProperties); @@ -458,12 +456,6 @@ protected static void assertSuccess(BaseResult result) { Assertions.assertThat(result.isSuccess()).isTrue(); } - protected @Nonnull SecurityContext securityContext(PolarisPrincipal p) { - SecurityContext securityContext = Mockito.mock(SecurityContext.class); - Mockito.when(securityContext.getUserPrincipal()).thenReturn(p); - return securityContext; - } - protected @Nonnull PrincipalEntity rotateAndRefreshPrincipal( PolarisMetaStoreManager metaStoreManager, String principalName, @@ -494,11 +486,9 @@ private void initBaseCatalog() { throw new RuntimeException(e); } } - SecurityContext securityContext = Mockito.mock(SecurityContext.class); - Mockito.when(securityContext.getUserPrincipal()).thenReturn(authenticatedRoot); PolarisPassthroughResolutionView passthroughView = new PolarisPassthroughResolutionView( - resolutionManifestFactory, securityContext, CATALOG_NAME); + resolutionManifestFactory, authenticatedRoot, CATALOG_NAME); this.baseCatalog = new IcebergCatalog( diagServices, @@ -506,7 +496,7 @@ private void initBaseCatalog() { metaStoreManager, callContext, passthroughView, - securityContext, + authenticatedRoot, Mockito.mock(), accessConfigProvider, fileIOFactory, @@ -554,13 +544,10 @@ public TestPolarisCallContextCatalogFactory( public Catalog createCallContextCatalog( CallContext context, PolarisPrincipal polarisPrincipal, - SecurityContext securityContext, final PolarisResolutionManifest resolvedManifest) { // This depends on the BasePolarisCatalog allowing calling initialize multiple times // to override the previous config. - Catalog catalog = - super.createCallContextCatalog( - context, polarisPrincipal, securityContext, resolvedManifest); + Catalog catalog = super.createCallContextCatalog(context, polarisPrincipal, resolvedManifest); catalog.initialize( CATALOG_NAME, ImmutableMap.of( diff --git a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java index 0a8996e5f9..2fe0e52680 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java @@ -22,11 +22,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.when; -import jakarta.ws.rs.core.SecurityContext; import java.lang.reflect.Method; import java.util.List; -import org.apache.polaris.core.PolarisDefaultDiagServiceImpl; -import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.admin.model.AuthenticationParameters; import org.apache.polaris.core.admin.model.Catalog; import org.apache.polaris.core.admin.model.CatalogProperties; @@ -44,19 +41,14 @@ import org.apache.polaris.core.persistence.PolarisMetaStoreManager; import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory; import org.apache.polaris.core.secrets.UserSecretsManager; -import org.apache.polaris.core.secrets.UserSecretsManagerFactory; import org.apache.polaris.service.config.ReservedProperties; -import org.apache.polaris.service.events.listeners.NoOpPolarisEventListener; -import org.apache.polaris.service.events.listeners.PolarisEventListener; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class PolarisServiceImplTest { - private final PolarisDiagnostics diagnostics = new PolarisDefaultDiagServiceImpl(); private ResolutionManifestFactory resolutionManifestFactory; - private UserSecretsManagerFactory userSecretsManagerFactory; private PolarisMetaStoreManager metaStoreManager; private UserSecretsManager userSecretsManager; private ServiceIdentityProvider serviceIdentityProvider; @@ -64,7 +56,6 @@ public class PolarisServiceImplTest { private CallContext callContext; private ReservedProperties reservedProperties; private RealmConfig realmConfig; - private PolarisEventListener polarisEventListener; private PolarisAdminService adminService; private PolarisServiceImpl polarisService; @@ -79,10 +70,7 @@ void setUp() { callContext = Mockito.mock(CallContext.class); reservedProperties = Mockito.mock(ReservedProperties.class); realmConfig = Mockito.mock(RealmConfig.class); - SecurityContext securityContext = Mockito.mock(SecurityContext.class); - Mockito.when(securityContext.getUserPrincipal()) - .thenReturn(Mockito.mock(PolarisPrincipal.class)); - polarisEventListener = new NoOpPolarisEventListener(); + PolarisPrincipal principal = Mockito.mock(PolarisPrincipal.class); when(callContext.getRealmConfig()).thenReturn(realmConfig); when(realmConfig.getConfig(FeatureConfiguration.SUPPORTED_CATALOG_CONNECTION_TYPES)) @@ -93,13 +81,12 @@ void setUp() { adminService = new PolarisAdminService( - diagnostics, callContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext, + principal, polarisAuthorizer, reservedProperties); polarisService = diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/AbstractPolarisGenericTableCatalogTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/AbstractPolarisGenericTableCatalogTest.java index e8488ad535..f4dceffe62 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/AbstractPolarisGenericTableCatalogTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/AbstractPolarisGenericTableCatalogTest.java @@ -25,7 +25,6 @@ import com.google.common.collect.ImmutableMap; import io.quarkus.test.junit.QuarkusMock; import jakarta.inject.Inject; -import jakarta.ws.rs.core.SecurityContext; import java.io.IOException; import java.lang.reflect.Method; import java.util.List; @@ -120,7 +119,6 @@ public abstract class AbstractPolarisGenericTableCatalogTest { private FileIOFactory fileIOFactory; private PolarisPrincipal authenticatedRoot; private PolarisEntity catalogEntity; - private SecurityContext securityContext; private AccessConfigProvider accessConfigProvider; protected static final Schema SCHEMA = @@ -165,21 +163,17 @@ public void before(TestInfo testInfo) { metaStoreManager.findRootPrincipal(polarisContext).orElseThrow(); authenticatedRoot = PolarisPrincipal.of(rootPrincipal, Set.of()); - securityContext = Mockito.mock(SecurityContext.class); - when(securityContext.getUserPrincipal()).thenReturn(authenticatedRoot); - PolarisAuthorizer authorizer = new PolarisAuthorizerImpl(realmConfig); ReservedProperties reservedProperties = ReservedProperties.NONE; adminService = new PolarisAdminService( - diagServices, polarisContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext, + authenticatedRoot, authorizer, reservedProperties); @@ -212,7 +206,7 @@ public void before(TestInfo testInfo) { PolarisPassthroughResolutionView passthroughView = new PolarisPassthroughResolutionView( - resolutionManifestFactory, securityContext, CATALOG_NAME); + resolutionManifestFactory, authenticatedRoot, CATALOG_NAME); TaskExecutor taskExecutor = Mockito.mock(); this.fileIOFactory = new DefaultFileIOFactory(); @@ -246,7 +240,7 @@ public void before(TestInfo testInfo) { metaStoreManager, polarisContext, passthroughView, - securityContext, + authenticatedRoot, taskExecutor, accessConfigProvider, fileIOFactory, 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 c3a5ac21c9..75067a48e2 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 @@ -50,7 +50,7 @@ private GenericTableCatalogHandler newWrapper( callContext, resolutionManifestFactory, metaStoreManager, - securityContext(authenticatedPrincipal), + authenticatedPrincipal, catalogName, polarisAuthorizer, null, diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogTest.java index 0f22737625..fa05af7efd 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogTest.java @@ -38,7 +38,6 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import jakarta.inject.Inject; -import jakarta.ws.rs.core.SecurityContext; import java.io.IOException; import java.io.UncheckedIOException; import java.lang.reflect.Method; @@ -250,7 +249,7 @@ public Map getConfigOverrides() { private FileIOFactory fileIOFactory; private InMemoryFileIO fileIO; private PolarisEntity catalogEntity; - private SecurityContext securityContext; + private PolarisPrincipal authenticatedRoot; private TestPolarisEventListener testPolarisEventListener; private ReservedProperties reservedProperties; private AccessConfigProvider accessConfigProvider; @@ -295,12 +294,12 @@ public void before(TestInfo testInfo) { new AccessConfigProvider(storageCredentialCache, metaStoreManagerFactory); EntityCache entityCache = createEntityCache(diagServices, realmConfig, metaStoreManager); resolverFactory = - (securityContext, referenceCatalogName) -> + (principal, referenceCatalogName) -> new Resolver( diagServices, polarisContext, metaStoreManager, - securityContext, + principal, entityCache, referenceCatalogName); QuarkusMock.installMockForType(resolverFactory, ResolverFactory.class); @@ -310,23 +309,19 @@ public void before(TestInfo testInfo) { PrincipalEntity rootPrincipal = metaStoreManager.findRootPrincipal(polarisContext).orElseThrow(); - PolarisPrincipal authenticatedRoot = PolarisPrincipal.of(rootPrincipal, Set.of()); - - securityContext = Mockito.mock(SecurityContext.class); - when(securityContext.getUserPrincipal()).thenReturn(authenticatedRoot); + authenticatedRoot = PolarisPrincipal.of(rootPrincipal, Set.of()); PolarisAuthorizer authorizer = new PolarisAuthorizerImpl(realmConfig); reservedProperties = new ReservedProperties() {}; adminService = new PolarisAdminService( - diagServices, polarisContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext, + authenticatedRoot, authorizer, reservedProperties); @@ -449,7 +444,7 @@ protected IcebergCatalog newIcebergCatalog( String catalogName, PolarisMetaStoreManager metaStoreManager, FileIOFactory fileIOFactory) { PolarisPassthroughResolutionView passthroughView = new PolarisPassthroughResolutionView( - resolutionManifestFactory, securityContext, catalogName); + resolutionManifestFactory, authenticatedRoot, catalogName); TaskExecutor taskExecutor = Mockito.mock(TaskExecutor.class); return new IcebergCatalog( diagServices, @@ -457,7 +452,7 @@ protected IcebergCatalog newIcebergCatalog( metaStoreManager, polarisContext, passthroughView, - securityContext, + authenticatedRoot, taskExecutor, accessConfigProvider, fileIOFactory, diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogViewTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogViewTest.java index 091cc7aac6..2406108abb 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogViewTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogViewTest.java @@ -18,12 +18,9 @@ */ package org.apache.polaris.service.catalog.iceberg; -import static org.mockito.Mockito.when; - import com.google.common.collect.ImmutableMap; import io.quarkus.test.junit.QuarkusMock; import jakarta.inject.Inject; -import jakarta.ws.rs.core.SecurityContext; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -171,21 +168,17 @@ public void before(TestInfo testInfo) { metaStoreManager.findRootPrincipal(polarisContext).orElseThrow(); PolarisPrincipal authenticatedRoot = PolarisPrincipal.of(rootPrincipal, Set.of()); - SecurityContext securityContext = Mockito.mock(SecurityContext.class); - when(securityContext.getUserPrincipal()).thenReturn(authenticatedRoot); - PolarisAuthorizer authorizer = new PolarisAuthorizerImpl(realmConfig); ReservedProperties reservedProperties = ReservedProperties.NONE; PolarisAdminService adminService = new PolarisAdminService( - diagServices, polarisContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext, + authenticatedRoot, authorizer, reservedProperties); adminService.createCatalog( @@ -208,7 +201,7 @@ public void before(TestInfo testInfo) { PolarisPassthroughResolutionView passthroughView = new PolarisPassthroughResolutionView( - resolutionManifestFactory, securityContext, CATALOG_NAME); + resolutionManifestFactory, authenticatedRoot, CATALOG_NAME); FileIOFactory fileIOFactory = new DefaultFileIOFactory(); testPolarisEventListener = (TestPolarisEventListener) polarisEventListener; @@ -220,7 +213,7 @@ public void before(TestInfo testInfo) { metaStoreManager, polarisContext, passthroughView, - securityContext, + authenticatedRoot, Mockito.mock(), accessConfigProvider, fileIOFactory, diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerAuthzTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerAuthzTest.java index 5cf6ab92c6..e5ebcc62e5 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerAuthzTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerAuthzTest.java @@ -23,7 +23,6 @@ import io.quarkus.test.junit.TestProfile; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; -import jakarta.ws.rs.core.SecurityContext; import java.time.Instant; import java.util.List; import java.util.Map; @@ -127,7 +126,7 @@ private IcebergCatalogHandler newWrapper( resolutionManifestFactory, metaStoreManager, credentialManager, - securityContext(authenticatedPrincipal), + authenticatedPrincipal, factory, catalogName, polarisAuthorizer, @@ -267,7 +266,7 @@ public void testInsufficientPermissionsPriorToSecretRotation() { resolutionManifestFactory, metaStoreManager, credentialManager, - securityContext(authenticatedPrincipal), + authenticatedPrincipal, callContextCatalogFactory, CATALOG_NAME, polarisAuthorizer, @@ -305,7 +304,7 @@ public void testInsufficientPermissionsPriorToSecretRotation() { resolutionManifestFactory, metaStoreManager, credentialManager, - securityContext(authenticatedPrincipal1), + authenticatedPrincipal1, callContextCatalogFactory, CATALOG_NAME, polarisAuthorizer, @@ -1125,9 +1124,7 @@ private IcebergCatalogHandler newWrapperWithFineGrainedAuthzDisabled() { CallContextCatalogFactory mockFactory = Mockito.mock(CallContextCatalogFactory.class); // Mock the catalog factory to return our regular catalog but with mocked config - Mockito.when( - mockFactory.createCallContextCatalog( - Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + Mockito.when(mockFactory.createCallContextCatalog(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(baseCatalog); return newWrapperWithFineLevelAuthDisabled(Set.of(), CATALOG_NAME, mockFactory, false); @@ -1185,7 +1182,7 @@ public T getConfig(PolarisConfiguration config, CatalogEntity catalogEnti resolutionManifestFactory, metaStoreManager, credentialManager, - securityContext(authenticatedPrincipal), + authenticatedPrincipal, factory, catalogName, polarisAuthorizer, @@ -1906,11 +1903,9 @@ public void testSendNotificationSufficientPrivileges() { public Catalog createCallContextCatalog( CallContext context, PolarisPrincipal polarisPrincipal, - SecurityContext securityContext, PolarisResolutionManifest resolvedManifest) { Catalog catalog = - super.createCallContextCatalog( - context, polarisPrincipal, securityContext, resolvedManifest); + super.createCallContextCatalog(context, polarisPrincipal, resolvedManifest); String fileIoImpl = "org.apache.iceberg.inmemory.InMemoryFileIO"; catalog.initialize( externalCatalog, ImmutableMap.of(CatalogProperties.FILE_IO_IMPL, fileIoImpl)); diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerFineGrainedDisabledTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerFineGrainedDisabledTest.java index e6434020ef..7c5ae41b61 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerFineGrainedDisabledTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandlerFineGrainedDisabledTest.java @@ -63,7 +63,7 @@ private IcebergCatalogHandler newWrapper() { resolutionManifestFactory, metaStoreManager, credentialManager, - securityContext(authenticatedPrincipal), + authenticatedPrincipal, callContextCatalogFactory, CATALOG_NAME, polarisAuthorizer, diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java index 32af648616..731ab6f071 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java @@ -206,7 +206,7 @@ IcebergCatalog createCatalog(TestServices services, String scheme) { PolarisPassthroughResolutionView passthroughView = new PolarisPassthroughResolutionView( - services.resolutionManifestFactory(), services.securityContext(), CATALOG_NAME); + services.resolutionManifestFactory(), services.principal(), CATALOG_NAME); IcebergCatalog polarisCatalog = new IcebergCatalog( services.polarisDiagnostics(), @@ -214,7 +214,7 @@ IcebergCatalog createCatalog(TestServices services, String scheme) { services.metaStoreManager(), callContext, passthroughView, - services.securityContext(), + services.principal(), services.taskExecutor(), services.accessConfigProvider(), services.fileIOFactory(), diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/AbstractPolicyCatalogTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/AbstractPolicyCatalogTest.java index 112775e21c..69b9cde7b6 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/AbstractPolicyCatalogTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/AbstractPolicyCatalogTest.java @@ -31,7 +31,6 @@ import com.google.common.collect.ImmutableMap; import io.quarkus.test.junit.QuarkusMock; import jakarta.inject.Inject; -import jakarta.ws.rs.core.SecurityContext; import java.io.IOException; import java.lang.reflect.Method; import java.util.Arrays; @@ -146,7 +145,6 @@ public abstract class AbstractPolicyCatalogTest { private FileIOFactory fileIOFactory; private PolarisPrincipal authenticatedRoot; private PolarisEntity catalogEntity; - private SecurityContext securityContext; private AccessConfigProvider accessConfigProvider; @BeforeAll @@ -186,21 +184,17 @@ public void before(TestInfo testInfo) { metaStoreManager.findRootPrincipal(polarisContext).orElseThrow(); authenticatedRoot = PolarisPrincipal.of(rootPrincipal, Set.of()); - securityContext = Mockito.mock(SecurityContext.class); - when(securityContext.getUserPrincipal()).thenReturn(authenticatedRoot); - PolarisAuthorizer authorizer = new PolarisAuthorizerImpl(realmConfig); ReservedProperties reservedProperties = ReservedProperties.NONE; adminService = new PolarisAdminService( - diagServices, polarisContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext, + authenticatedRoot, authorizer, reservedProperties); @@ -231,7 +225,7 @@ public void before(TestInfo testInfo) { PolarisPassthroughResolutionView passthroughView = new PolarisPassthroughResolutionView( - resolutionManifestFactory, securityContext, CATALOG_NAME); + resolutionManifestFactory, authenticatedRoot, CATALOG_NAME); TaskExecutor taskExecutor = Mockito.mock(); this.fileIOFactory = new DefaultFileIOFactory(); @@ -263,7 +257,7 @@ public void before(TestInfo testInfo) { metaStoreManager, polarisContext, passthroughView, - securityContext, + authenticatedRoot, taskExecutor, accessConfigProvider, fileIOFactory, diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandlerAuthzTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandlerAuthzTest.java index 5a7e5149fd..4bd6dc5c81 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandlerAuthzTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandlerAuthzTest.java @@ -55,7 +55,7 @@ private PolicyCatalogHandler newWrapper(Set activatedPrincipalRoles, Str callContext, resolutionManifestFactory, metaStoreManager, - securityContext(authenticatedPrincipal), + authenticatedPrincipal, catalogName, polarisAuthorizer, null, diff --git a/runtime/service/src/testFixtures/java/org/apache/polaris/service/TestServices.java b/runtime/service/src/testFixtures/java/org/apache/polaris/service/TestServices.java index cd1652ab02..b39ff5a08e 100644 --- a/runtime/service/src/testFixtures/java/org/apache/polaris/service/TestServices.java +++ b/runtime/service/src/testFixtures/java/org/apache/polaris/service/TestServices.java @@ -105,6 +105,7 @@ public record TestServices( MetaStoreManagerFactory metaStoreManagerFactory, RealmContext realmContext, RealmConfig realmConfig, + PolarisPrincipal principal, SecurityContext securityContext, PolarisMetaStoreManager metaStoreManager, FileIOFactory fileIOFactory, @@ -207,12 +208,12 @@ public TestServices build() { EntityCache entityCache = metaStoreManagerFactory.getOrCreateEntityCache(realmContext, realmConfig); ResolverFactory resolverFactory = - (securityContext, referenceCatalogName) -> + (_principal, referenceCatalogName) -> new Resolver( diagnostics, callContext.getPolarisCallContext(), metaStoreManager, - securityContext, + _principal, entityCache, referenceCatalogName); @@ -321,13 +322,12 @@ public String getAuthenticationScheme() { PolarisAdminService adminService = new PolarisAdminService( - diagnostics, callContext, resolutionManifestFactory, metaStoreManager, userSecretsManager, serviceIdentityProvider, - securityContext, + principal, authorizer, reservedProperties); PolarisCatalogsApi catalogsApi = @@ -349,6 +349,7 @@ public String getAuthenticationScheme() { metaStoreManagerFactory, realmContext, realmConfig, + principal, securityContext, metaStoreManager, fileIOFactory, diff --git a/runtime/service/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java b/runtime/service/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java index 4eb7210f0d..c647c17015 100644 --- a/runtime/service/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java +++ b/runtime/service/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java @@ -18,10 +18,10 @@ */ package org.apache.polaris.service.catalog; -import jakarta.ws.rs.core.SecurityContext; import java.util.Arrays; import org.apache.iceberg.catalog.Namespace; import org.apache.iceberg.catalog.TableIdentifier; +import org.apache.polaris.core.auth.PolarisPrincipal; import org.apache.polaris.core.catalog.PolarisCatalogHelpers; import org.apache.polaris.core.entity.PolarisEntitySubType; import org.apache.polaris.core.entity.PolarisEntityType; @@ -41,20 +41,20 @@ */ public class PolarisPassthroughResolutionView implements PolarisResolutionManifestCatalogView { private final ResolutionManifestFactory resolutionManifestFactory; - private final SecurityContext securityContext; + private final PolarisPrincipal polarisPrincipal; private final String catalogName; public PolarisPassthroughResolutionView( ResolutionManifestFactory resolutionManifestFactory, - SecurityContext securityContext, + PolarisPrincipal polarisPrincipal, String catalogName) { this.resolutionManifestFactory = resolutionManifestFactory; - this.securityContext = securityContext; + this.polarisPrincipal = polarisPrincipal; this.catalogName = catalogName; } private PolarisResolutionManifest newResolutionManifest() { - return resolutionManifestFactory.createResolutionManifest(securityContext, catalogName); + return resolutionManifestFactory.createResolutionManifest(polarisPrincipal, catalogName); } @Override