diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java index ca7ca9e35bfe1..9621459cdb9b5 100644 --- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java +++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java @@ -538,7 +538,22 @@ public CompletableFuture allowNamespaceOperationAsync(NamespaceName nam String role, NamespaceOperation operation, AuthenticationDataSource authData) { - return validateTenantAdminAccess(namespaceName.getTenant(), role, authData); + CompletableFuture future = new CompletableFuture<>(); + configCache.policiesCache().getAsync(POLICY_ROOT + namespaceName.toString()) + .thenAccept(policies -> { + if (!policies.isPresent()) { + future.complete(false); + if (log.isDebugEnabled()) { + log.debug("Policies node couldn't be found for namespace : {}", namespaceName); + } + } else { + Set namespacesActions = policies.get().auth_policies.namespace_auth.get(role); + future.complete(namespacesActions.stream().anyMatch(authAction -> + authAction.toString().equals(operation.toString().toLowerCase()))); + } + }); + return validateTenantAdminAccess(namespaceName.getTenant(), role, authData) + .thenCombine(future, (isTenantAdmin, hasPermission) -> isTenantAdmin || hasPermission); } @Override diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PackagesBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PackagesBase.java index bd00b4191194c..031bb3c800b22 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PackagesBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PackagesBase.java @@ -166,7 +166,6 @@ protected void internalListPackages(String type, String tenant, String namespace private CompletableFuture checkPermissions(String tenant, String namespace) { CompletableFuture future = new CompletableFuture<>(); if (config().isAuthenticationEnabled()) { - String role = clientAppId(); NamespaceName namespaceName; try { namespaceName = NamespaceName.get(tenant, namespace); @@ -174,8 +173,9 @@ private CompletableFuture checkPermissions(String tenant, String namespace future.completeExceptionally(e); return future; } - getAuthorizationService().allowNamespaceOperationAsync(namespaceName, NamespaceOperation.PACKAGES, - originalPrincipal(), role, clientAuthData()) + getAuthorizationService() + .allowNamespaceOperationAsync(namespaceName, NamespaceOperation.PACKAGES, + originalPrincipal(), clientAppId(), clientAuthData()) .whenComplete((hasPermission, throwable) -> { if (throwable != null) { future.completeExceptionally(throwable); @@ -184,8 +184,8 @@ private CompletableFuture checkPermissions(String tenant, String namespace if (hasPermission) { future.complete(null); } else { - future.completeExceptionally(new RestException(Response.Status.UNAUTHORIZED, String.format( - "Role %s has not the 'package' permission to do the packages operations.", role))); + future.completeExceptionally(new RestException(Response.Status.FORBIDDEN, String.format( + "Role %s has not the 'package' permission to do the packages operations.", clientAppId()))); } }); } else { diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/TopicOperation.java b/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/TopicOperation.java index 7e54cca1515d3..5676b14e29cf9 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/TopicOperation.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/TopicOperation.java @@ -47,4 +47,6 @@ public enum TopicOperation { SUBSCRIBE, GET_SUBSCRIPTIONS, UNSUBSCRIBE, + + PACKAGES, } diff --git a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/auth/admin/PackagesOpsWithAuthTest.java b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/auth/admin/PackagesOpsWithAuthTest.java index ddaf3a26e073e..a70b0cd0c812a 100644 --- a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/auth/admin/PackagesOpsWithAuthTest.java +++ b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/auth/admin/PackagesOpsWithAuthTest.java @@ -197,14 +197,12 @@ public void testPackagesOps() throws Exception { clientAdmin.packages().listPackages("function", "public/default"); fail("list package operation should fail because the client hasn't permission to do"); } catch (PulsarAdminException e) { - assertEquals(e.getStatusCode(), 401); + assertEquals(e.getStatusCode(), 403); } // grant package permission to the role - TenantInfo tenantInfo = new TenantInfo(); - tenantInfo.setAdminRoles(new HashSet<>(Arrays.asList(SUPER_USER_ROLE, PROXY_ROLE, REGULAR_USER_ROLE))); - tenantInfo.setAllowedClusters(new HashSet<>(superUserAdmin.clusters().getClusters())); - superUserAdmin.tenants().updateTenant("public", tenantInfo); + superUserAdmin.namespaces().grantPermissionOnNamespace("public/default", + REGULAR_USER_ROLE, Set.of(AuthAction.packages)); // then do some package operations again, it should success List packagesName = clientAdmin.packages().listPackages("function", "public/default");