From 10512948c562778dae781e044af8555f6c258171 Mon Sep 17 00:00:00 2001 From: Honah J Date: Mon, 21 Apr 2025 13:11:09 -0700 Subject: [PATCH 1/4] auth for getApplicablePolicies --- .../auth/PolarisAuthorizableOperation.java | 3 +- .../PolicyCatalogHandlerAuthzTest.java | 64 +++++++++++++++++++ .../catalog/policy/PolicyCatalogHandler.java | 57 +++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) diff --git a/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java b/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java index 1eaea6c3f9..1f8e95bf22 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java @@ -208,8 +208,7 @@ public enum PolarisAuthorizableOperation { DETACH_POLICY_FROM_TABLE(POLICY_DETACH, TABLE_DETACH_POLICY), GET_APPLICABLE_POLICIES_ON_CATALOG(CATALOG_READ_PROPERTIES), GET_APPLICABLE_POLICIES_ON_NAMESPACE(NAMESPACE_READ_PROPERTIES), - GET_APPLICABLE_POLICIES_ON_TABLE(TABLE_READ_PROPERTIES), - GET_APPLICABLE_POLICIES_ON_VIEW(VIEW_READ_PROPERTIES), + GET_APPLICABLE_POLICIES_ON_TABLE(TABLE_READ_PROPERTIES) ; private final EnumSet privilegesOnTarget; diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java index b821be31e5..c2aea07e3b 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java @@ -722,4 +722,68 @@ public void testDetachFromPolicyInsufficientPrivileges() { newWrapper(Set.of(PRINCIPAL_ROLE2)).detachPolicy(POLICY_NS1_1, detachPolicyRequest); } + + @Test + public void testGetApplicablePoliciesOnCatalogSufficientPrivileges() { + doTestSufficientPrivileges( + List.of( + PolarisPrivilege.CATALOG_READ_PROPERTIES, + PolarisPrivilege.CATALOG_WRITE_PROPERTIES, + PolarisPrivilege.CATALOG_MANAGE_METADATA), + () -> newWrapper().getApplicablePolicies(null, null, null), + null /* cleanupAction */); + } + + @Test + public void testGetApplicablePoliciesOnCatalogInsufficientPrivileges() { + doTestInsufficientPrivileges( + List.of( + PolarisPrivilege.NAMESPACE_READ_PROPERTIES, + PolarisPrivilege.POLICY_READ, + PolarisPrivilege.TABLE_READ_PROPERTIES), + () -> newWrapper().getApplicablePolicies(null, null, null)); + } + + @Test + public void testGetApplicablePoliciesOnNamespaceSufficientPrivileges() { + doTestSufficientPrivileges( + List.of( + PolarisPrivilege.NAMESPACE_READ_PROPERTIES, + PolarisPrivilege.NAMESPACE_WRITE_PROPERTIES, + PolarisPrivilege.CATALOG_MANAGE_METADATA), + () -> newWrapper().getApplicablePolicies(NS1, null, null), + null /* cleanupAction */); + } + + @Test + public void testGetApplicablePoliciesOnNamespaceInSufficientPrivileges() { + doTestInsufficientPrivileges( + List.of( + PolarisPrivilege.CATALOG_READ_PROPERTIES, + PolarisPrivilege.POLICY_READ, + PolarisPrivilege.TABLE_READ_PROPERTIES), + () -> newWrapper().getApplicablePolicies(NS1, null, null)); + } + + @Test + public void testGetApplicablePoliciesOnTableSufficientPrivileges() { + doTestSufficientPrivileges( + List.of( + PolarisPrivilege.TABLE_READ_PROPERTIES, + PolarisPrivilege.TABLE_WRITE_PROPERTIES, + PolarisPrivilege.CATALOG_MANAGE_METADATA), + () -> newWrapper().getApplicablePolicies(TABLE_NS1_1.namespace(), TABLE_NS1_1.name(), null), + null /* cleanupAction */); + } + + @Test + public void testGetApplicablePoliciesOnTableInsufficientPrivileges() { + doTestInsufficientPrivileges( + List.of( + PolarisPrivilege.CATALOG_READ_PROPERTIES, + PolarisPrivilege.POLICY_READ, + PolarisPrivilege.NAMESPACE_READ_PROPERTIES), + () -> + newWrapper().getApplicablePolicies(TABLE_NS1_1.namespace(), TABLE_NS1_1.name(), null)); + } } diff --git a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java index fb0c71f2e7..2c85ee2736 100644 --- a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java +++ b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java @@ -18,6 +18,8 @@ */ package org.apache.polaris.service.catalog.policy; +import com.google.common.base.Strings; +import jakarta.annotation.Nullable; import jakarta.ws.rs.core.SecurityContext; import java.util.Arrays; import java.util.HashSet; @@ -26,6 +28,7 @@ import org.apache.iceberg.catalog.TableIdentifier; import org.apache.iceberg.exceptions.NoSuchNamespaceException; import org.apache.iceberg.exceptions.NoSuchTableException; +import org.apache.iceberg.exceptions.NotFoundException; import org.apache.polaris.core.auth.PolarisAuthorizableOperation; import org.apache.polaris.core.auth.PolarisAuthorizer; import org.apache.polaris.core.catalog.PolarisCatalogHelpers; @@ -43,6 +46,7 @@ import org.apache.polaris.service.types.AttachPolicyRequest; import org.apache.polaris.service.types.CreatePolicyRequest; import org.apache.polaris.service.types.DetachPolicyRequest; +import org.apache.polaris.service.types.GetApplicablePoliciesResponse; import org.apache.polaris.service.types.ListPoliciesResponse; import org.apache.polaris.service.types.LoadPolicyResponse; import org.apache.polaris.service.types.PolicyAttachmentTarget; @@ -134,6 +138,16 @@ public boolean detachPolicy(PolicyIdentifier identifier, DetachPolicyRequest req return policyCatalog.detachPolicy(identifier, request.getTarget()); } + public GetApplicablePoliciesResponse getApplicablePolicies( + @Nullable Namespace namespace, @Nullable String targetName, @Nullable PolicyType policyType) { + authorizeGetApplicablePoliciesOperationOrThrow(namespace, targetName); + + return GetApplicablePoliciesResponse.builder() + .setApplicablePolicies( + new HashSet<>(policyCatalog.getApplicablePolicies(namespace, targetName, policyType))) + .build(); + } + private void authorizeBasicPolicyOperationOrThrow( PolarisAuthorizableOperation op, PolicyIdentifier identifier) { resolutionManifest = @@ -161,6 +175,49 @@ private void authorizeBasicPolicyOperationOrThrow( initializeCatalog(); } + private void authorizeGetApplicablePoliciesOperationOrThrow( + @Nullable Namespace namespace, @Nullable String targetName) { + if (namespace == null || namespace.isEmpty()) { + // catalog + PolarisAuthorizableOperation op = + PolarisAuthorizableOperation.GET_APPLICABLE_POLICIES_ON_CATALOG; + authorizeBasicCatalogOperationOrThrow(op); + } else if (Strings.isNullOrEmpty(targetName)) { + // namespace + PolarisAuthorizableOperation op = + PolarisAuthorizableOperation.GET_APPLICABLE_POLICIES_ON_NAMESPACE; + authorizeBasicNamespaceOperationOrThrow(op, namespace); + } else { + // table + TableIdentifier tableIdentifier = TableIdentifier.of(namespace, targetName); + PolarisAuthorizableOperation op = + PolarisAuthorizableOperation.GET_APPLICABLE_POLICIES_ON_TABLE; + // only Iceberg tables are supported + authorizeBasicTableLikeOperationOrThrow( + op, PolarisEntitySubType.ICEBERG_TABLE, tableIdentifier); + } + } + + private void authorizeBasicCatalogOperationOrThrow(PolarisAuthorizableOperation op) { + resolutionManifest = + entityManager.prepareResolutionManifest(callContext, securityContext, catalogName); + resolutionManifest.resolveAll(); + + PolarisResolvedPathWrapper targetCatalog = + resolutionManifest.getResolvedReferenceCatalogEntity(); + if (targetCatalog == null) { + throw new NotFoundException("Catalog not found"); + } + authorizer.authorizeOrThrow( + authenticatedPrincipal, + resolutionManifest.getAllActivatedCatalogRoleAndPrincipalRoles(), + op, + targetCatalog, + null /* secondary */); + + initializeCatalog(); + } + private void authorizePolicyMappingOperationOrThrow( PolicyIdentifier identifier, PolicyAttachmentTarget target, boolean isAttach) { resolutionManifest = From 978e25a4e6a6f674a4303add9925ec66d0db08c0 Mon Sep 17 00:00:00 2001 From: Honah J Date: Mon, 21 Apr 2025 19:08:18 -0700 Subject: [PATCH 2/4] Fix style --- .../polaris/service/catalog/policy/PolicyCatalogHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java index 2c85ee2736..fb8c674ae7 100644 --- a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java +++ b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java @@ -26,8 +26,6 @@ import java.util.List; import org.apache.iceberg.catalog.Namespace; import org.apache.iceberg.catalog.TableIdentifier; -import org.apache.iceberg.exceptions.NoSuchNamespaceException; -import org.apache.iceberg.exceptions.NoSuchTableException; import org.apache.iceberg.exceptions.NotFoundException; import org.apache.polaris.core.auth.PolarisAuthorizableOperation; import org.apache.polaris.core.auth.PolarisAuthorizer; @@ -45,7 +43,6 @@ import org.apache.polaris.service.catalog.common.CatalogHandler; import org.apache.polaris.service.types.AttachPolicyRequest; import org.apache.polaris.service.types.CreatePolicyRequest; -import org.apache.polaris.service.types.DetachPolicyRequest; import org.apache.polaris.service.types.GetApplicablePoliciesResponse; import org.apache.polaris.service.types.ListPoliciesResponse; import org.apache.polaris.service.types.LoadPolicyResponse; From 19bfb408c43f5796f58c7ddc8de0a3d2e5157331 Mon Sep 17 00:00:00 2001 From: Honah J Date: Tue, 22 Apr 2025 10:46:27 -0700 Subject: [PATCH 3/4] Fix merge conflict --- .../apache/polaris/core/auth/PolarisAuthorizableOperation.java | 3 +-- .../polaris/service/catalog/policy/PolicyCatalogHandler.java | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java b/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java index 1f8e95bf22..e7f5a6cc00 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java @@ -208,8 +208,7 @@ public enum PolarisAuthorizableOperation { DETACH_POLICY_FROM_TABLE(POLICY_DETACH, TABLE_DETACH_POLICY), GET_APPLICABLE_POLICIES_ON_CATALOG(CATALOG_READ_PROPERTIES), GET_APPLICABLE_POLICIES_ON_NAMESPACE(NAMESPACE_READ_PROPERTIES), - GET_APPLICABLE_POLICIES_ON_TABLE(TABLE_READ_PROPERTIES) - ; + GET_APPLICABLE_POLICIES_ON_TABLE(TABLE_READ_PROPERTIES); private final EnumSet privilegesOnTarget; private final EnumSet privilegesOnSecondary; diff --git a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java index fb8c674ae7..2c85ee2736 100644 --- a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java +++ b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java @@ -26,6 +26,8 @@ import java.util.List; import org.apache.iceberg.catalog.Namespace; import org.apache.iceberg.catalog.TableIdentifier; +import org.apache.iceberg.exceptions.NoSuchNamespaceException; +import org.apache.iceberg.exceptions.NoSuchTableException; import org.apache.iceberg.exceptions.NotFoundException; import org.apache.polaris.core.auth.PolarisAuthorizableOperation; import org.apache.polaris.core.auth.PolarisAuthorizer; @@ -43,6 +45,7 @@ import org.apache.polaris.service.catalog.common.CatalogHandler; import org.apache.polaris.service.types.AttachPolicyRequest; import org.apache.polaris.service.types.CreatePolicyRequest; +import org.apache.polaris.service.types.DetachPolicyRequest; import org.apache.polaris.service.types.GetApplicablePoliciesResponse; import org.apache.polaris.service.types.ListPoliciesResponse; import org.apache.polaris.service.types.LoadPolicyResponse; From 0da7b1ebe5dc4f2e442abe044884b77cc55bfffe Mon Sep 17 00:00:00 2001 From: Honah J Date: Tue, 22 Apr 2025 16:21:46 -0700 Subject: [PATCH 4/4] nit --- .../polaris/service/catalog/policy/PolicyCatalogHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java index 2c85ee2736..f4dea27b43 100644 --- a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java +++ b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java @@ -213,7 +213,7 @@ private void authorizeBasicCatalogOperationOrThrow(PolarisAuthorizableOperation resolutionManifest.getAllActivatedCatalogRoleAndPrincipalRoles(), op, targetCatalog, - null /* secondary */); + null); initializeCatalog(); }